MintedVodka - Smart Contract Audit Report

Summary

Minted Vodka Audit Report Alchemy Toys is building an NFT marketplace.

For this audit, we reviewed the Alchemy Toys' MintedVodka, Deal, Deed, DeedIssuer, and ERC721Enumerable contracts at commit 9d1705aeec1531e131144a509e5f80c2adc25ee8 on the project team's private GitLab repository.

Notes on the Contracts:
  • The MintedVodka contract allows users to create, accept, and cancel deals.
  • Users may offer or demand either properties or ETH, as long as there are equal amounts of both offers and demands in a single deal.
  • There is a maximum number of items that can be involved in a single deal, and the owner can update this to any value at any time.
  • The contract allows users to place Premium trades by using GAT token as the single position on either the offer or demand side; for these trades, the trade fee will be waived upon accepting the deal.
  • A unique encoded trade ID is assigned to each deal based on many global, environment, and deal-related values.
  • While creating a deal, a for loop is used to create deeds for each offer property, performing an external call to the Deed contract.
  • While accepting a deal, a for loop is used to transfer funds for each demand property, performing an external call to the deal owner’s address.
  • The team must ensure the maximum number of items that can be involved in a single deal is no more than 200 to prevent these loops from hitting the block gas limit.
  • Once a deal is created, deeds for each offer property are minted, and the value of the property is transferred from the owner of the property to the contract address.
  • A deal can be accepted or canceled by the creator of the the deal, owner of the contract, or an approved address set by the creator of the deal.
  • After the offer and demand properties are appropriately distributed, the Deed is burned.

  • The owner has the ability to set the fee receiver wallet address, set the list fee multiplier, set the trade fee multiplier, set the fee update interval, and set the max items involved in a deal (offer properties + demand properties).
  • The owner has the ability to send the ETH in the MintedVodka contract balance, which are the accumulated fees, to the fee receiver wallet at any time; this is also done periodically when fees are updated.
  • The owner has the ability to withdraw ETH sent to the Deal contract to the fee receiver wallet at any time.

  • The list fee is calculated by taking the average gas price per transaction since fees were last updated, multiplying it by a gasBase variable which is set by the team on construction, and further multiplying it by a listFeeMultiplier which can be set by the team to any value at any time.
  • The trade fee is calculated using the same formula as the list fee.
  • The owner has the ability to force update the fees at any time in order to recalculate the average gas price per transaction; otherwise it will be updated at an interval set by the team on construction that can be updated by the team to any value at any time.

  • The team has worked with us to optimize these contracts for gas optimization.
  • Solidity 0.8.4 is used across all contracts to prevent overflows.
Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • Ensure trust in the team as they have some control in the ecosystem.
  • Date: June 29th, 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
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 +  Initializable 

 +  ContextUpgradeable (Initializable)
    - [Int] __Context_init #
       - modifiers: initializer
    - [Int] __Context_init_unchained #
       - modifiers: initializer
    - [Int] _msgSender
    - [Int] _msgData

 +  OwnableUpgradeable (Initializable, ContextUpgradeable)
    - [Int] __Ownable_init #
       - modifiers: initializer
    - [Int] __Ownable_init_unchained #
       - modifiers: initializer
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner

 +  ReentrancyGuardUpgradeable (Initializable)
    - [Int] __ReentrancyGuard_init #
       - modifiers: initializer
    - [Int] __ReentrancyGuard_init_unchained #
       - modifiers: initializer

 +  PausableUpgradeable (Initializable, ContextUpgradeable)
    - [Int] __Pausable_init #
       - modifiers: initializer
    - [Int] __Pausable_init_unchained #
       - modifiers: initializer
    - [Pub] paused
    - [Int] _pause #
       - modifiers: whenNotPaused
    - [Int] _unpause #
       - modifiers: whenPaused

 + [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] IERC165Upgradeable 
    - [Ext] supportsInterface

 + [Int] IERC721Upgradeable (IERC165Upgradeable)
    - [Ext] balanceOf
    - [Ext] ownerOf
    - [Ext] safeTransferFrom #
    - [Ext] transferFrom #
    - [Ext] approve #
    - [Ext] getApproved
    - [Ext] setApprovalForAll #
    - [Ext] isApprovedForAll
    - [Ext] safeTransferFrom #

 + [Int] IERC721ReceiverUpgradeable 
    - [Ext] onERC721Received #

 + [Int] IERC721MetadataUpgradeable (IERC721Upgradeable)
    - [Ext] name
    - [Ext] symbol
    - [Ext] tokenURI

 + [Lib] AddressUpgradeable 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Prv] _verifyCallResult

 + [Lib] StringsUpgradeable 
    - [Int] toString
    - [Int] toHexString
    - [Int] toHexString

 +  ERC165Upgradeable (Initializable, IERC165Upgradeable)
    - [Int] __ERC165_init #
       - modifiers: initializer
    - [Int] __ERC165_init_unchained #
       - modifiers: initializer
    - [Pub] supportsInterface

 +  ERC721Upgradeable (Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable)
    - [Int] __ERC721_init #
       - modifiers: initializer
    - [Int] __ERC721_init_unchained #
       - modifiers: initializer
    - [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] IDeedIssuer 
    - [Ext] depositDeed #
    - [Ext] withdrawDeed #
    - [Ext] transferDeed #

 + [Int] IERC721Enumerable (IERC721Upgradeable)
    - [Ext] totalSupply
    - [Ext] tokenOfOwnerByIndex
    - [Ext] tokenByIndex

 +  ERC721Enumerable (ERC721Upgradeable, IERC721Enumerable)
    - [Pub] supportsInterface
    - [Ext] tokenOfOwnerByIndex
    - [Pub] totalSupply
    - [Ext] tokenByIndex
    - [Int] _beforeTokenTransfer #
    - [Prv] _addTokenToOwnerEnumeration #
    - [Prv] _addTokenToAllTokensEnumeration #
    - [Prv] _removeTokenFromOwnerEnumeration #
    - [Prv] _removeTokenFromAllTokensEnumeration #

 +  Deed (ERC721Enumerable)
    - [Ext] initialize #
       - modifiers: initializer
    - [Ext] withdraw #
    - [Pub] withdrawTo #
    - [Ext] deposit ($)
    - [Int] _beforeTokenTransfer #
    - [Int] _getId

 +  DeedIssuer (IDeedIssuer)
    - [Int] __DeedIssuer_init #
    - [Ext] withdrawDeed #
       - modifiers: onlyDeed
    - [Ext] transferDeed #
       - modifiers: onlyDeed
    - [Ext] depositDeed #
       - modifiers: onlyDeed

 +  Deal (DeedIssuer, ERC721Enumerable, OwnableUpgradeable)
    - [Ext] initialize #
       - modifiers: initializer
    - [Ext] getDeal
    - [Ext] create ($)
       - modifiers: onlyOwner
    - [Ext] cancel #
       - modifiers: onlyOwner
    - [Ext] accept ($)
       - modifiers: onlyOwner
    - [Ext] withdrawTips #
       - modifiers: onlyOwner
    - [Ext] withdrawDeed #
       - modifiers: onlyDeed
    - [Ext] transferDeed #
       - modifiers: onlyDeed
    - [Int] _closeTrade #
    - [Int] _transferProperties #

 +  MintedVodka (Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable)
    - [Ext] initialize #
       - modifiers: initializer,updateFees
    - [Ext] createDeal ($)
       - modifiers: whenNotPaused,nonReentrant,updateFees
    - [Ext] acceptDeal ($)
       - modifiers: whenNotPaused,nonReentrant,updateFees
    - [Ext] cancelDeal #
       - modifiers: whenNotPaused,nonReentrant,updateFees
    - [Ext] setFeereceiver #
       - modifiers: onlyOwner
    - [Ext] setDeal #
       - modifiers: onlyOwner
    - [Ext] setListFeeMultiplier #
       - modifiers: onlyOwner
    - [Ext] setTradeFeeMultiplier #
       - modifiers: onlyOwner
    - [Ext] setFeeUpdateInterval #
       - modifiers: onlyOwner
    - [Ext] setMaxItems #
       - modifiers: onlyOwner
    - [Ext] forceUpdateFees #
       - modifiers: onlyOwner,updateFees
    - [Ext] forceResetFees #
       - modifiers: onlyOwner
    - [Ext] withdraw #
    - [Prv] _updateFees #
    - [Prv] _sendFees #