Crypto Date - Smart Contract Audit Report
Summary
CryptoDate is a new protocol that allows users to purchase CryptoDate NFTs as well as stake their CryptoDate tokens to earn rewards.
We reviewed the project team's Token, NFT, and Staking Rewards contracts at commit a3473951fb965ff98fc94504b2a744b4a2a395c9 on the team's Github repository.
Notes on the individual contracts
CryptoDate Token contract:
- The total supply of the token will be set at the time of deployment and minted to the owner.
- No minting functions are accessible beyond deployment.
- Any user can burn their own tokens to reduce the total supply.
- As the token has not yet been deployed to the mainnet, there was no token allocation for our team to analyze.
- As the project is implemented with Solidity v0.8.0, it is protected from overflows.
- The contract complies with the ERC20 token standard.
CryptoDate NFT Contract:Staking Rewards Contract:
- Each CryptoDate NFT represents a specific day between January 1st, 1950 and December 31st, 2049. Any user has the ability to purchase a CryptoDate NFT with ETH by entering in the desired date for the NFT that they would like to purchase. Once a date is claimed, it can no longer be claimed by another user.
- At the time of writing this report, the standard price for purchasing 1 NFT is 0.1 ETH, however the owner can modify this price to any value at any time.
- There are certain dates that are considered rare which is reflected in the price. The price for purchasing a CryptoDate NFT where the month and day are matching will cost the user 10 times the amount of the standard price.
- The price for purchasing an NFT on any leap day will cost 100 times the amount of the standard price.
- One half of the ETH collected from purchases is converted to WETH and is paired with CryptoDate tokens. This pair is then used the fund the Uniswap liquidity pool.
- The other half of ETH collected from purchases is sent directly to the team's Treasury address.
- Users who purchase NFTs also receive a reward in Cryptodate tokens. The amount of tokens rewarded to the user is 100 times the ETH value used to purchase their NFT.
- Users can manually claim rewards in CryptoDate tokens based on the amount of CryptoDate NFTs in their balance.
- Users will not recieve any awards if the contract balance does not have the sufficient amount of CryptoDate tokens.
- Any user has the ability to recover ETH and tokens (with the exception of CryptoDate tokens) erroneously sent to the contract.
- The contract complies with the ERC721 standard.
Audit Findings Summary
- Users can stake their CryptoDate tokens into the Staking Rewards contract in order to earn more CryptoDate tokens as a reward.
- There is a no fee associated with making a deposit to or withdrawing from the contract.
- User's have the ability to claim their CryptoDate token rewards at any time.
- Users will not recieve any rewards if the contract balance does not have the sufficient amount of CryptoDate tokens.
- Users have the ability to begin a new period of staking if there is a sufficient enough balance of CryptoDate tokens to begin a new period.
- The contract utilizes the SafeMath library to prevent overflows.
- No external threats were identified.
- Please ensure trust in the team as they have notable control in the ecosystem.
- Date: October 1st, 2021
Audit Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
Details: CryptoDateToken Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC20Metadata (IERC20)
- [Ext] name
- [Ext] symbol
- [Ext] decimals
+ Context
- [Int] _msgSender
- [Int] _msgData
+ ERC20 (Context, IERC20, IERC20Metadata)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _beforeTokenTransfer #
- [Int] _afterTokenTransfer #
+ ERC20Burnable (Context, ERC20)
- [Pub] burn #
- [Pub] burnFrom #
+ ERC20PresetFixedSupply (ERC20Burnable)
- [Pub] #
- modifiers: ERC20
+ CryptoDateToken (ERC20PresetFixedSupply)
- [Pub] #
- modifiers: ERC20PresetFixedSupply
Details: CryptoDate NFT Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IERC165
- [Ext] supportsInterface
+ [Int] IERC721 (IERC165)
- [Ext] balanceOf
- [Ext] ownerOf
- [Ext] safeTransferFrom #
- [Ext] transferFrom #
- [Ext] approve #
- [Ext] getApproved
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
+ [Int] IERC721Receiver
- [Ext] onERC721Received #
+ [Int] IERC721Metadata (IERC721)
- [Ext] name
- [Ext] symbol
- [Ext] tokenURI
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Lib] Strings
- [Int] toString
- [Int] toHexString
- [Int] toHexString
+ ERC165 (IERC165)
- [Pub] supportsInterface
+ ERC721 (Context, ERC165, IERC721, IERC721Metadata)
- [Pub] #
- [Pub] supportsInterface
- [Pub] balanceOf
- [Pub] ownerOf
- [Pub] name
- [Pub] symbol
- [Pub] tokenURI
- [Int] _baseURI
- [Pub] approve #
- [Pub] getApproved
- [Pub] setApprovalForAll #
- [Pub] isApprovedForAll
- [Pub] transferFrom #
- [Pub] safeTransferFrom #
- [Pub] safeTransferFrom #
- [Int] _safeTransfer #
- [Int] _exists
- [Int] _isApprovedOrOwner
- [Int] _safeMint #
- [Int] _safeMint #
- [Int] _mint #
- [Int] _burn #
- [Int] _transfer #
- [Int] _approve #
- [Prv] _checkOnERC721Received #
- [Int] _beforeTokenTransfer #
+ [Int] IERC721Enumerable (IERC721)
- [Ext] totalSupply
- [Ext] tokenOfOwnerByIndex
- [Ext] tokenByIndex
+ ERC721Enumerable (ERC721, IERC721Enumerable)
- [Pub] supportsInterface
- [Pub] tokenOfOwnerByIndex
- [Pub] totalSupply
- [Pub] tokenByIndex
- [Int] _beforeTokenTransfer #
- [Prv] _addTokenToOwnerEnumeration #
- [Prv] _addTokenToAllTokensEnumeration #
- [Prv] _removeTokenFromOwnerEnumeration #
- [Prv] _removeTokenFromAllTokensEnumeration #
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Lib] Math
- [Int] max
- [Int] min
- [Int] average
- [Int] ceilDiv
+ ReentrancyGuard
- [Pub] #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ Ownable (Context)
- [Pub] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Int] _transferOwnership #
+ [Int] IUniswapV2Router02
- [Ext] quote
+ [Int] IUniswapV2Pair
- [Ext] getReserves
- [Ext] sync #
+ [Int] IWETH
- [Ext] deposit ($)
+ [Int] IExist
- [Ext] exists #
+ CryptoDate (ERC721Enumerable, ReentrancyGuard, Ownable)
- [Pub] #
- modifiers: ERC721
- [Int] _baseURI
- [Ext] mintWithETH ($)
- modifiers: nonReentrant
- [Ext] updatePrice #
- modifiers: onlyOwner
- [Pub] getPriceInETH
- [Ext] migrationMint #
- modifiers: nonReentrant
- [Prv] valiDate #
- [Ext] extendRewards #
- [Pub] lastTimeRewardApplicable
- [Pub] rewardPerToken
- [Pub] earned
- [Ext] getRewardForDuration
- [Ext] getReward #
- modifiers: nonReentrant
- [Int] updateReward #
- [Int] _beforeTokenTransfer #
- [Ext] recoverWrongTokens #
- [Ext] withdrawETH ($)
- [Ext] ($)
Details: Staking Rewards Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Int] verifyCallResult
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Lib] Math
- [Int] max
- [Int] min
- [Int] average
- [Int] ceilDiv
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ ReentrancyGuard
- [Pub] #
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ StakingRewards (ReentrancyGuard)
- [Pub] #
- [Ext] totalSupply
- [Ext] balanceOf
- [Pub] lastTimeRewardApplicable
- [Pub] rewardPerToken
- [Pub] earned
- [Ext] getRewardForDuration
- [Ext] stake #
- modifiers: nonReentrant
- [Ext] withdraw #
- modifiers: nonReentrant
- [Ext] getReward #
- modifiers: nonReentrant
- [Ext] startRewards #
- [Int] updateReward #