RandomWalkNFT - Smart Contract Audit Report

Summary

crypto_audit RandomWalkNFT is a new NFT marketplace with randomly generated NFTs that allow users to potentially win large amounts of ETH.

For this audit, we reviewed the RandomWalkNFT, MintMany, and NFTMarket contracts at commit 22ec08634d0020f80cfad1fc5a1bff1521511f02 on the team's private GitHub repository.

Notes on the Contracts:
RandomWalkNFT Contract:
  • Any address that pays the minting cost is able to mint a RandomWalk NFT once the starting sale time has passed.
  • The cost to mint the first NFT is 0.0010011 ETH. After the first NFT is minted, each NFT costs 0.11% more to mint than the previous NFT.
  • Any extra ETH sent to pay for minting will be returned to the user.
  • If no NFTs are minted for a 1 month period, the last user that minted is able to withdraw half of the contract's ETH balance.
  • Users are able to name their NFTs, up to a size limit of 32 bytes.
  • NFT metadata that contains information about the NFT is stored using an off-chain URI endpoint.
  • The seed generation that determines the NFT metadata uses a somewhat weak source of randomness, potentially allowing outcomes to be determined by miners while a block is being mined.
  • The owner is able to update the URI endpoint at any time.
MintMany Contract:
  • This contract enables the owner to mint RandomWalk NFTs in bulk.
  • There is no limit to the number of NFTs that can be minted at once as long as enough ETH is provided and the gas block limit is not hit.
  • The owner may change the address of the NFT contract at any time.
NFTMarket Contract:
  • Anyone can use this contract to list or accept a buy or sell offer for an NFT at any time.
  • Users may cancel any of their buy or sell offers at any time.
  • Listed NFTs are held in the contract until they are sold or the listing is cancelled.
  • The amount of ETH provided determines the price of a buy offer.
  • ETH is the only accepted payment for NFTs listed on the Market.
  • There are no fees associated with listings on the Market.
  • There is no ownership restricted functionality present.
  • Due to the way offers are stored, the gas cost of most of the functions will quickly increase until it is guaranteed that the gas block limit is reached.
  • We recommend that the team implement seperate storage for buy and sell offers, as well as mappings for individual user's listings. Additionally, orders could be deleted after being completed or cancelled, if the team does not need to retain that information in the future.
  • As the contracts are implemented with Solidity v0.8.x, they are protected from overflows/underflows
Audit Findings Summary
  • No external threats were identified.
  • Ensure trust in the team as they have some control within the ecosystem.
  • The data storage structure will lead to loss of functionality due to the block gas limit.
  • Date: November 23rd, 2021.

Audit Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
OraclesN/APASS
SuicideN/APASS
State Change External CallsN/APASS
Unbounded LoopsThe data structure will lead to loss of functionality due to the block gas limit.FAIL
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety FAIL

RandomWalkNFT Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

 + [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] 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 #

 + [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] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 +  RandomWalkNFT (ERC721Enumerable, Ownable)
    - [Pub] Constructor #
       - modifiers: ERC721
    - [Pub] setBaseURI #
       - modifiers: onlyOwner
    - [Pub] setTokenName #
    - [Int] _baseURI
    - [Pub] getMintPrice
    - [Pub] timeUntilSale
    - [Pub] timeUntilWithdrawal
    - [Pub] withdrawalAmount
    - [Pub] withdraw #
    - [Pub] mint ($)
    - [Pub] walletOfOwner
    - [Pub] seedsOfOwner

							

MintMany Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

 + [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] 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 #

 + [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] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 +  RandomWalkNFT (ERC721Enumerable, Ownable)
    - [Pub] Constructor #
       - modifiers: ERC721
    - [Pub] setBaseURI #
       - modifiers: onlyOwner
    - [Pub] setTokenName #
    - [Int] _baseURI
    - [Pub] getMintPrice
    - [Pub] timeUntilSale
    - [Pub] timeUntilWithdrawal
    - [Pub] withdrawalAmount
    - [Pub] withdraw #
    - [Pub] mint ($)
    - [Pub] walletOfOwner
    - [Pub] seedsOfOwner

 +  MintMany (Ownable)
    - [Pub] Constructor #
    - [Pub] setNFTAddr #
       - modifiers: onlyOwner
    - [Pub] mintMultiple ($)
       - modifiers: onlyOwner
    - [Pub] onERC721Received #

							

NFTMarket Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

 + [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 #

 +  NFTMarket 
    - [Pub] makeBuyOffer ($)
    - [Pub] makeSellOffer #
    - [Pub] acceptBuyOffer #
    - [Pub] acceptSellOffer ($)
    - [Pub] cancelBuyOffer #
    - [Pub] cancelSellOffer #
    - [Pub] onERC721Received
    - [Pub] getSellTokenBy
    - [Pub] getBuyTokensBy
    - [Pub] getSellOffersBy
    - [Pub] getBuyOffersBy
    - [Pub] getBuyOffers
    - [Pub] getSellOffers