CouncilOfKingz NFT - Smart Contract Audit Report

Audit Summary

CouncilofKingz Audit Report CouncilOfKingz is a new NFT collection with a presale and public sale format.

For this audit, we reviewed the CouncilOfKingz contract provided to us by the project team.

Audit Findings

Please ensure trust in the team prior to investing as they have notable control in the ecosystem.
Date: January 23th, 2022.
Updated: January 24th, 2022 to address resolved issues and changes by the team.

Contract Overview

  • The CouncilOfKingz contract is used to facilitate a presale and a public sale for the CouncilOfKingz NFTs.
  • The maximum total supply of CouncilOfKingz NFTs is 7,777, of which 100 are minted to the owner on deployment.
  • While the presale is active, eligible users can each purchase up to 5 NFTs until the maximum total supply has been reached.
  • The contract uses an off-chain generated Merkle tree provided by the owner to store and verify addresses that are eligible to mint during the presale.
  • While the public sale is active, users can each purchase up to 5 NFTs per transaction until the maximum total supply or the maximum wallet limit has been reached.
  • CouncilOfKingz NFT presale and public sale prices are set separately; the presale price is 0.13 ETH while the public sale price is 0.15 ETH.
  • In the event that the address receiving an NFT is a contract, the contract must have implemented the onERC721Received() function in order to successfully receive the NFT.
  • The base URI value is set on deployment, but is not meant to be the final base URI. This is intended so that users will not know which CouncilOfKingz NFT they have received until the true base URI is "revealed".
  • The contract will only accept the correct amount of ETH that is required for the specified amount of NFTs to be purchased.
  • The owner can withdraw all funds from the contract at any time.
  • The owner can mint NFTs while the contract is not paused and the maximum supply limit has not been reached.
  • The owner can toggle the presale and public sale at any time.
  • The owner can pause the contract at any time which disables all minting functionality.
  • The owner can enable burn functionality at any time; once it is enabled it cannot be disabled.
  • The owner can set the maximum burn limit to any value at any time.
  • The owner can reveal the token URIs at any time.
  • The owner can set the root of the Merkle tree at any time, effectively controlling the presale whitelist.
  • The owner can set the hidden URI, base URI, and base extension at any time.
  • This contract complies with the ERC-721 standard.
  • As the contract is developed with Solidity 0.8.x, it is protected from overflow/underflow attacks.

Resolved Issues

Finding #1 - CouncilOfKingz - Informational

Description: Several functions are declared public, but are never called internally. Several state variables can never be modified, but are not declared constant.
Functions:
totalSupply, publicMint, presaleMint, ownerMint, walletOfOwner, contractURI, burn, publicSaleStart, reveal, enableBurn, setmaxMintAmount, setMaxTokensPerWalletPresale, setMaxTokensPerWallet, setCostPublicSale, setCostPresale, setTotalBurnTokens, setBaseExtension

State Variables:
marketingWallet, totalTokens 

Recommendation: We recommend declaring these functions external and declaring these state variables constant for additional gas savings on each call.
Resolution: The team has declared these functions as external, removed the marketingWallet variable and declared the totalTokens variable as constant.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of ControlN/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
Logical IssuesN/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

Function Graph

Bridge Contract Graph

Inheritence Chart

Multi-file Token

Functions Overview

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

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

 + [Int] IERC165 
    - [Ext] supportsInterface

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 + [Lib] MerkleProof 
    - [Int] verify
    - [Int] processProof

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

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

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

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

 +  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 #
    - [Int] _setApprovalForAll #
    - [Prv] _checkOnERC721Received #
    - [Int] _beforeTokenTransfer #

 +  CouncilOfKingz (ERC721, Ownable)
    - [Pub]  #
       - modifiers: ERC721
    - [Ext] totalSupply
    - [Pub] totalBurned
    - [Pub] totalMinted
    - [Ext] publicMint ($)
       - modifiers: onlyAllowValidCountAndActiveSale
    - [Ext] presaleMint ($)
       - modifiers: onlyAllowValidCountAndActiveSale
    - [Ext] ownerMint #
       - modifiers: onlyOwner,onlyAllowValidCountAndActiveSale
    - [Prv] _mintNFT #
    - [Prv] _getTokenToBeMinted #
    - [Prv] _getRandomNumber
    - [Ext] walletOfOwner
    - [Ext] contractURI
    - [Int] _baseURI
    - [Pub] tokenURI
    - [Ext] burn #
    - [Ext] flipSaleState #
       - modifiers: onlyOwner
    - [Ext] publicSaleStart #
       - modifiers: onlyOwner
    - [Ext] reveal #
       - modifiers: onlyOwner
    - [Ext] enableBurn #
       - modifiers: onlyOwner
    - [Ext] setCostPublicSale #
       - modifiers: onlyOwner
    - [Ext] setCostPresale #
       - modifiers: onlyOwner
    - [Ext] setTotalBurnTokens #
       - modifiers: onlyOwner
    - [Pub] setContractURI #
       - modifiers: onlyOwner
    - [Pub] setNotRevealedURI #
       - modifiers: onlyOwner
    - [Pub] setCurrentBaseURI #
       - modifiers: onlyOwner
    - [Ext] setBaseExtension #
       - modifiers: onlyOwner
    - [Ext] setPresaleListEnabled #
       - modifiers: onlyOwner
    - [Ext] setMerkleRoot #
       - modifiers: onlyOwner
    - [Pub] withdraw ($)
       - modifiers: onlyOwner
    - [Ext] Fallback ($)
    - [Ext] Receive Ether ($)