Meta Travelers - Smart Contract Audit Report
Summary
Meta Travelers is a new non-fungible token with multiple minting periods and randomly determined metadata.
Notes on the Contract:Audit Findings Summary
- The maximum total supply of MetaTravelers NFTs is 7777.
- Users are able to burn any of their NFTs reducing the total supply.
- The cost of minting an NFT during any stage is 0.123 ETH.
- There is toggleable Early Adopter and Presale minting that allows approved users to mint.
- While the Early Adopter stage is enabled, anyone on the Early Adopter list can mint up to 5 NFTs. The maximum mintable NFTs via Early Adopter stage is 1665.
- While the Presale stage is enabled, anyone on the Presale list can mint up to 3 NFTs, as long as their total count of NFTs including those minted in the Early Adopter stage is no more than 3. The maximum mintable NFTs increases to 3330 via the Presale stage.
- While the Mint Pass stage is enabled, anyone with a Mint Pass is able to redeem the Mint Pass for 1 NFT. The maximum mintable NFTs increases to 5661 via the Mint Pass stage.
- While the Public Sale stage is enabled, anyone is able to mint up to 3 NFTs at a time. The maximum mintable NFTs increases to the maximum amount of 7777 via the Public Sale stage.
- NFT metadata that contains information about the NFT is stored using an off-chain URI endpoint.
- NFTs are minted but not indexed; the random starting index will determine the metadata that is assigned to the NFT.
- Chainlink VRF is used to generate random numbers to select a starting index. This is the industry standard and is resistant to manipulation.
- LINK will need to be held in the contract to pay the fee associated with the randomness request.
- The owner is able to mint themselves any amount of NFTs at any time.
- The owner is able to toggle any of the minting functionality at any time.
- The owner is able to add any address to the Early Adopters and Presale list at any time.
- The owner is able to give users any amount of Mint Passes at anytime.
- The owner is able to change the URI endpoint at any time.
- The owner can withdraw all ETH from the contract at any time.
- The owner can pause and unpause the contract at anytime which prevents any transfer, minting, and burning functionality.
- The contract is ERC721 compliant; all standard functionality is present.
- As the project is implemented with solidity version ^0.8.0, it is protected from overflows.
Resolved Issues
- No external threats were identified.
- Ensure trust in the team as they have considerable control within the ecosystem.
- Date: November 1st, 2021.
- Updated: November 1st, 2021 to address multiple improvements.
The team worked with us to implement changes related to gas optimization. The team has communicated their plan to generate the random data after NFTs have been minted in line with our recommendation. Restricted the call to Chainlink VRF to only the owner to prevent concurrent requests for randomness.
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 |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | 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 |
($) = payable function
# = non-constant function
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] Constructor #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Prv] _setOwner #
+ [Lib] Counters
- [Int] current
- [Int] increment #
- [Int] decrement #
- [Int] reset #
+ [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
+ [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
+ [Lib] Strings
- [Int] toString
- [Int] toHexString
- [Int] toHexString
+ ERC165 (IERC165)
- [Pub] supportsInterface
+ ERC721 (Context, ERC165, IERC721, IERC721Metadata)
- [Pub] Constructor #
- [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 #
+ Pausable (Context)
- [Pub] Constructor #
- [Pub] paused
- [Int] _pause #
- modifiers: whenNotPaused
- [Int] _unpause #
- modifiers: whenPaused
+ ERC721Pausable (ERC721, Pausable)
- [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 #
+ ERC721Burnable (Context, ERC721)
- [Pub] burn #
+ [Int] LinkTokenInterface
- [Ext] allowance
- [Ext] approve #
- [Ext] balanceOf
- [Ext] decimals
- [Ext] decreaseApproval #
- [Ext] increaseApproval #
- [Ext] name
- [Ext] symbol
- [Ext] totalSupply
- [Ext] transfer #
- [Ext] transferAndCall #
- [Ext] transferFrom #
+ VRFRequestIDBase
- [Int] makeVRFInputSeed
- [Int] makeRequestId
+ VRFConsumerBase (VRFRequestIDBase)
- [Int] fulfillRandomness #
- [Int] requestRandomness #
- [Pub] Constructor #
- [Ext] rawFulfillRandomness #
+ MetaTravelers (ERC721Enumerable, ERC721Pausable, ERC721Burnable, VRFConsumerBase, Ownable)
- [Pub] Constructor #
- modifiers: ERC721,VRFConsumerBase
- [Ext] setBaseTokenURI #
- modifiers: onlyOwner
- [Ext] addToEarlyAdopterList #
- modifiers: onlyOwner
- [Ext] addToPreSaleList #
- modifiers: onlyOwner
- [Ext] addToMintPassList #
- modifiers: onlyOwner
- [Ext] toggleEarlyAdopter #
- modifiers: onlyOwner
- [Ext] togglePreSale #
- modifiers: onlyOwner
- [Ext] toggleMintPassSale #
- modifiers: onlyOwner
- [Prv] _baseMint #
- [Ext] earlyAdopterMint ($)
- [Ext] preSaleMint ($)
- [Ext] mintPassMint ($)
- [Ext] publicSaleMint ($)
- [Pub] reserveMetaTravelers #
- modifiers: onlyOwner
- [Pub] setProvenanceHash #
- modifiers: onlyOwner
- [Pub] setStartingIndex #
- [Int] fulfillRandomness #
- [Pub] withdraw #
- modifiers: onlyOwner
- [Pub] tokenURI
- [Ext] pause #
- modifiers: onlyOwner
- [Ext] unpause #
- modifiers: onlyOwner
- [Pub] supportsInterface
- [Int] _beforeTokenTransfer #