CryptoHamsters - Smart Contract Audit Report
CryptoHamsters is building a platform to generate Hamster NFTs with pseudo-randomly chosen skills and attributes.
We reviewed CryptoHamsters's CryptoHamsters, Randomness, ERC721Tradable, ContextMixin, and NativeMetaTransaction contracts at commit 4bd7fffa0d55c1ed7fc083cc4457f9ad836a0364 on the team's private Github repository.
Notes on the Contracts:
- The CryptoHamsters contract is used to mint various CryptoHamsters NFTs to users with specific skill levels for attributes that are selected on a pseudo-random basis; only the owner is able to mint the NFTs.
- The randomness algorithm relies on some predictable variables that can be manipulated by miners to some extent.
- The contract contains logic to require a signature from the user in order to forward all gas payments to the Proxy Registry Address via meta-transactions in an effort to promote "gas-less" transactions.
- The owner is able to set the Proxy Registry Address to any value at any time; the Proxy Registry Address is automatically approved for any and all CryptoHamsters NFTs.
- The owner is able to set the address of the Randomness contract at any time, as long as the address implements isRandomness() function.
- The owner is able to set the base token URI and the contract URI to any values at any time.
- The owner is able to add any address to the list of acknowledgements at any time.
- The team worked with us to implement changes related to gas optimization.
- As these contracts are implemented with Solidity v0.8.x, they are protected from overflows.
Audit Findings Summary:
- No security issues from outside attackers were identified.
- Please ensure trust in the project team as they have substantial control in the ecosystem and can influence the Hamster produced as a result of minting.
- Date: October 15th, 2021.
External Threat Results
|Arbitrary Storage Write||N/A||PASS|
|Delegate Call to Untrusted Contract||N/A||PASS|
|Dependence on Predictable Variables||Decisions are made based on the block.timestamp|
and block.difficulty environment variables
which can be manipulated by a malicious miner.
This is extremley unlikely to occur.
|State Change External Calls||N/A||PASS|
|User Supplied Assertion||N/A||PASS|
|Critical Solidity Compiler||N/A||PASS|
|Overall Contract Safety||PASS|
($) = 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 # + Ownable (Context) - [Pub] # - [Pub] owner - [Pub] renounceOwnership # - modifiers: onlyOwner - [Pub] transferOwnership # - modifiers: onlyOwner - [Prv] _setOwner # + [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 + ContextMixin - [Int] msgSender + Initializable + EIP712Base (Initializable) - [Int] _initializeEIP712 # - modifiers: initializer - [Int] _setDomainSeperator # - [Pub] getDomainSeperator - [Pub] getChainId - [Int] toTypedMessageHash + NativeMetaTransaction (EIP712Base) - [Pub] executeMetaTransaction ($) - [Int] hashMetaTransaction - [Pub] getNonce - [Int] verify + ERC721Tradable (ContextMixin, ERC721Enumerable, NativeMetaTransaction, Ownable) - [Pub] # - modifiers: ERC721 - [Pub] isApprovedForAll - [Ext] setProxyRegistryAddress # - modifiers: onlyOwner - [Int] _msgSender + RandomnessInterface - [Ext] isRandomness # - [Ext] rarity # - [Ext] mastery # - [Ext] stats # - [Ext] seed # + CryptoHamsters (ERC721Tradable) - [Pub] # - modifiers: ERC721Tradable - [Pub] mintTo # - modifiers: onlyOwner - [Ext] setRandomnessAddress # - modifiers: onlyOwner - [Pub] raritySupply - [Pub] tokenURI - [Pub] setBaseTokenURI # - modifiers: onlyOwner - [Pub] setContractURI # - modifiers: onlyOwner - [Pub] contractURI - [Ext] getHamster - [Ext] acknowledge # - modifiers: onlyOwner
($) = payable function # = non-constant function Int = Internal Ext = External Pub = Public + Randomness - [Ext] isRandomness - [Ext] rarity - [Ext] mastery - [Ext] stats - [Pub] seed - [Prv] _random