Hentai Holiday - Smart Contract Audit Report

Summary

Hentai Holiday Audit Report Hentai Holiday is deploying a pair of smart contracts to facilitate NFT buying and selling on the Binance Smart Chain.

For this audit we reviewed the project team's HentaiHolidaySingle and HentaiHolidayMultiple contracts using code provided to us by the contract team.

Notes on the HentaiHolidayMultiple Contract:

  • Users are able to mint any amount of any Hentai NFTs at any time. The user who mints is credited as being the creator and will receive the NFTs minted and the royalties from buying and selling that NFT ID.
  • As any user can mint at any time, and there is no check if an NFT ID exists already, a user could mint an NFT ID that already exists. This would cause the NFTs to be minted again and the new user to be credited as the creator of all NFTs of that ID and receive the new NFTs as well as royalties for all NFTs of that ID.
  • There is no limit on the number of any type of NFT that can be minted.
  • Any valid BEP20 token can be added to the contract as a valid payment token. The team should exercise caution when adding new payment tokens to avoid ERC777-compliant tokens.
  • NFT metadata that contains information about the NFT is stored using a URI endpoint. While this endpoint cannot be changed, the information at the endpoint is not stored on the blockchain.
  • The owner of the endpoint could change the underlying data thus changing the NFT's information stored there.

  • Users are able to buy NFTs using BNB and other approved BEP20 tokens by completing a sell order. Sell orders are created by the NFT owner specifying the price.
  • When buying with tokens the amount is measured in number of tokens, this allows the owner to use tokens with very little monetary value. The owner or a user could exploit this to buy NFTs at a much lower price than the seller anticipated.
  • Users are able to place a sell order for NFTs they own at any time.
  • Users are able to change the price of that order at any time.
  • Users are able to cancel their sell orders at any time.
  • Users are able to sell NFTs by accepting a bid. A bid is made when the buyer gives the contract allowance in the selected approved token. The seller then accepts the bid and transfers the NFTs.
  • Users are able to accept a bid only in approved tokens.
  • There is no way to bid for a specific NFT. Any seller is able to accept any bid.
  • Accepting bids to sell NFTs does not have the same issues as buying NFTs.
  • There are service, admin, and royalty fees for purchasing and selling NFTs.
  • The royalty fee is set by the creator of the NFT upon minting. They receive all royalties.
  • The service and admin fee are the same amount and are sent to the owner. This value is set by the owner.
  • None of the fees are limited and could be set to 100%.
  • The remaining value after fees is sent to the seller of the NFT.
  • Users are able to burn any amount of any NFTs they own at any time.
  • If a user grants the contract full permision, the contract owner is able to burn any amount of their NFTs at any time.

  • The owner is able to change the service fee at any time.
  • The owner is able to add and remove addresses as a permitted payment token type at any time.
Notes on the HentaiHolidaySingle Contract:
  • Only the owner is able to mint any amount of any NFT as long as it has not been minted before.
  • If a sell price is provided a sell order is automatically created.
  • Any valid BEP20 token can be added to the contract as a valid payment token. The team should exercise caution when adding new payment tokens to avoid ERC777-compliant tokens.
  • NFT metadata that contains information about the NFT is stored using a URI endpoint. The information at the endpoint is not stored on the blockchain
  • The owner of the endpoint could change the underlying data thus changing the NFT's information stored there.

  • Users are able to sell NFTs by accepting a bid. A bid is made when the buyer gives the contract allowance in the selected approved token. The seller then accepts the bid and transfers the NFTs.
  • Users are able to accept a bid only in approved tokens.
  • There is no way to bid for a specific NFT. Any seller is able to accept any bid.
  • Users are able to buy NFTs using BNB and other tokens approved by the owner.
  • Users are able to buy any other users NFTs with approved tokens at any time without a sell order being placed.
  • Users are able to buy other users NFTs using BNB by completing a sell orders.
  • An NFT owner places a sell order specifying the sell amount. A user then uses BNB to buy the NFT at the specified amount.
  • Buying or selling an NFT will remove the existing sell order for that NFT even if the owner has more of that NFT available to be sold.
  • There are service, admin, and royalty fees for purchasing and selling NFTs.
  • The royalty fee is set by the creator of the NFT upon minting the NFT. They receive all royalties.
  • The service and admin fee are the same and sent to the owner. This value is set by the owner.
  • The remaining value is sent to the seller of the NFT.
  • Users are able to place a sell order for NFTs they own at any time.
  • Users are able to lower the price of that order at any time. To increase the price you must cancel the order and place a new one with a higher price.
  • Users are able to cancel their sell order at any time.
  • Users are able to burn any NFTs they own as long as they only own 1 of them.
  • If an address has approval to transfer NFTs on another's behalf, that address can opt to burn NFTs from the account that has provided the approval as long as the balance of the NFT is 1.

  • The owner is able to change the service fee at any time.
  • The owner is able to add and remove addresses as a permitted payment token type at any time.
  • The owner is able to change the URI endpoint at any time.

  • Solidity v0.8.x is used across both contracts to prevent overflows.
Audit Findings Summary:
  • Within the HentaiHolidaySingle contract users are able to buy NFTs with tokens without a sell order being placed.
  • Ensure trust in the team as they have substantial control in the ecosystem.
  • Date: October 7th, 2021.
  • Updated: October 25th, 2021 - to resolve an issue with the dumTokenTransfer function.
Resolved Issues
  • The team addressed an issue where NFTs could be transferred without paying in certain circumstances.

Audit Results

Vulnerability CategoryNotesResult
Logical IssuesN/APASS
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

Hentai Holiday Multiple Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
  +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 + [Int] IBEP165 
    - [Ext] supportsInterface

 +  BEP165 (IBEP165)
    - [Pub] supportsInterface

 + [Int] IBEP1155 (IBEP165)
    - [Ext] balanceOf
    - [Ext] balanceOfBatch
    - [Ext] setApprovalForAll #
    - [Ext] isApprovedForAll
    - [Ext] safeTransferFrom #
    - [Ext] safeBatchTransferFrom #

 + [Int] IBEP1155MetadataURI (IBEP1155)
    - [Ext] uri
    - [Ext] name
    - [Ext] symbol

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

 +  BEP1155 (Context, BEP165, IBEP1155, IBEP1155MetadataURI)
    - [Pub]  #
    - [Pub] name
    - [Pub] symbol
    - [Pub] supportsInterface
    - [Pub] uri
    - [Pub] balanceOf
    - [Pub] balanceOfBatch
    - [Pub] setApprovalForAll #
    - [Pub] isApprovedForAll
    - [Pub] safeTransferFrom #
    - [Pub] safeBatchTransferFrom #
    - [Int] _safeTransferFrom #
    - [Int] _safeBatchTransferFrom #
    - [Int] _setURI #
    - [Int] _mint #
    - [Int] _mintBatch #
    - [Int] _burn #
    - [Int] _burnBatch #
    - [Int] _beforeTokenTransfer #
    - [Prv] _doSafeTransferAcceptanceCheck #
    - [Prv] _doSafeBatchTransferAcceptanceCheck #
    - [Prv] _asSingletonArray

 + [Int] IBEP1155Receiver (IBEP165)
    - [Ext] onBEP1155Received #
    - [Ext] onBEP1155BatchReceived #

 +  BEP1155Burnable (BEP1155)
    - [Pub] burn #
    - [Pub] burnBatch #

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

 + [Int] BEP20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 +  HentaiholidayMULTIPLE (BEP1155, Ownable, BEP1155Burnable)
    - [Pub]  #
       - modifiers: BEP1155
    - [Pub] getServiceFee
    - [Pub] serviceFunction #
       - modifiers: onlyOwner
    - [Pub] addID #
    - [Pub] getTokenAddress
    - [Pub] addTokenType #
       - modifiers: onlyOwner
    - [Pub] setApproval #
    - [Pub] mint #
    - [Pub] mintBatch #
    - [Pub] saleWithToken #
    - [Pub] saleToken ($)
    - [Int] _saleToken #
    - [Int] pBEPent
    - [Int] calc
    - [Int] saleTokenTransfer #
    - [Pub] dumTokenTransfer #
    - [Pub] acceptBId #
    - [Int] _acceptBId #
    - [Int] tokenTrans #
    - [Pub] orderPlace #
    - [Pub] cancelOrder #
    - [Pub] changePrice #
    - [Pub] burnToken #

Hentai Holiday Single Contract

Smart Contract Graph

Contract Inheritance


 ($) = payable function
 # = non-constant function
 
 + [Int] IBEP165 
    - [Ext] supportsInterface

 + [Lib] SafeMath 
    - [Int] add
    - [Int] sub
    - [Int] sub
    - [Int] mul
    - [Int] div
    - [Int] div
    - [Int] mod
    - [Int] mod

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

 + [Int] IBEP721Receiver 
    - [Ext] onBEP721Received #

 + [Int] IBEP721Metadata (IBEP721)
    - [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 #
    - [Prv] _verifyCallResult

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

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

 +  BEP165 (IBEP165)
    - [Pub] supportsInterface

 +  BEP721 (Context, BEP165, IBEP721, IBEP721Metadata)
    - [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] _checkOnBEP721Received #
    - [Int] _beforeTokenTransfer #

 + [Int] IBEP721Enumerable (IBEP721)
    - [Ext] totalSupply
    - [Ext] tokenOfOwnerByIndex
    - [Ext] tokenByIndex

 +  BEP721Enumerable (BEP721, IBEP721Enumerable)
    - [Pub] supportsInterface
    - [Pub] tokenOfOwnerByIndex
    - [Pub] totalSupply
    - [Pub] tokenByIndex
    - [Int] _beforeTokenTransfer #
    - [Prv] _addTokenToOwnerEnumeration #
    - [Prv] _addTokenToAllTokensEnumeration #
    - [Prv] _removeTokenFromOwnerEnumeration #
    - [Prv] _removeTokenFromAllTokensEnumeration #

 +  BEP721URIStorage (BEP721)
    - [Pub] tokenURI
    - [Int] _setTokenURI #
    - [Int] _burn #

 +  BEP721Burnable (Context, BEP721)
    - [Pub] burn #

 +  Ownable (Context)
    - [Pub]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Prv] _setOwner #

 + [Int] BEP20 
    - [Ext] totalSupply
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 +  HentaiholidaySingle (BEP721, BEP721Enumerable, BEP721URIStorage, BEP721Burnable, Ownable)
    - [Pub]  #
       - modifiers: BEP721
    - [Pub] getServiceFee
    - [Pub] serviceFunction #
       - modifiers: onlyOwner
    - [Pub] addID #
    - [Pub] getTokenAddress
    - [Pub] addTokenType #
       - modifiers: onlyOwner
    - [Int] _addTokenType #
       - modifiers: onlyOwner
    - [Pub] setApproval #
    - [Pub] safeMint #
       - modifiers: onlyOwner
    - [Pub] setBaseURI #
       - modifiers: onlyOwner
    - [Int] _beforeTokenTransfer #
    - [Int] _burn #
    - [Pub] tokenURI
    - [Pub] supportsInterface
    - [Pub] mint #
    - [Pub] orderPlace #
    - [Int] _orderPlace #
    - [Ext] get
    - [Int] calc
    - [Int] pBEPent
    - [Int] SalewithToken #
    - [Pub] saleTokenwithToken #
    - [Int] newtokenasbid #
    - [Int] _acceptBId #
    - [Pub] saleToken ($)
    - [Int] _saleToken #
    - [Int] saleTokenTransfer #
    - [Int] tokenTrans #
    - [Pub] acceptBId #
    - [Pub] cancelOrder #
    - [Pub] changePrice #
    - [Pub] burnToken #