Meka Miners - Audit Report

Audit Summary

WEMP BSC Token and Bridges Audit Report MEKA is building a new NFT platform where users can buy, sell, and create Robots and Pieces. In addition, the team is creating a time-locked token vesting contract to distribute Meka tokens to beneficiaries.

For this audit, we reviewed the following contracts on the Binance Smartchain Testnet:

The Marketplace contract was not included in the scope of this audit, so we cannot verify the security or functionality of this contract's interactions with it.

Audit Findings

Please ensure trust in the team prior to investing as they have substantial control in the ecosystem and will operate off-chain logic.
Date: January 17th, 2022.
Updated: January 18th, 2022 to reflect changes from the previous PieceCore contract at 0x3A18CEf717aCF5d447CD8B9eA1D10b8eb670E081, RobotCore contract at 0xF9bbB2A0280B83ecbddF12697676aeaFefe794e1, and TokenTimelock contract at 0xcF287c134B7a2f51264F9bAa0828Ee0253573944.

Finding #1 - PieceCore - Low

Description: The Piece ID assigned to a new Piece is pseudorandomly fetched from a list of available Piece IDs using a hash of the user, block difficulty, and block timestamp. This is common, albeit not best practice. Miners and bots in the memory pool may be able to predict the results and may take action accordingly to secure profits; though the chance of this is extremely low.
Risk/Impact: It is possible for miners/validators to predict the results of a Piece creation in order to mint a Piece with a favorable Piece ID.
Recommendation: The team can consider using a more reliable source of randomness, such as Chainlink.

Contracts Overview

MekaDeployer Contract:
  • Users must use this contract in order to create new Robots, new Pieces, and attach their Pieces to their Robots via the RobotCore and PieceCore contracts.
  • Anyone can also use this contract to deposit and withdraw $Meka tokens.
  • Users are not able to use contracts to deposit or withdraw $Meka tokens; these transactions must be originated by externally-owned accounts (EOAs).
  • Upon depositing, users must deposit at least the minimum amount determined by the project team.
  • For each externally facing function, users must provide a signature in order to verify that the contract's signature address has indeed signed a message to allow for the transaction to occur.
  • Users must also provide a nonce to ensure that signatures cannot be used more than once, avoiding replay attacks.
  • The owner can withdraw any tokens from the contract at any time.
  • The owner can set the RobotCore and PieceCore contract addresses at any time.
  • The owner can set the signature address to any address at any time; initially, it is set to the owner's address.
  • The owner can set the $Meka token address to any address at any time.
  • The owner can set the minimum deposit amount to any value at any time.
PieceCore Contract:
  • This ERC-721 contract allows users to purchase Pieces with assigned Piece IDs, which are separate from the token ID.
  • Users can purchase a Piece by calling this contract from the MekaDeployer contract.
  • A user specified amount of $Meka tokens are transferred from the owner's address to this contract as payment.
  • The amount to be transferred must be greater than or equal to an owner specified "Piece price".
  • A Piece is then minted to the user with a "birth time" of the current timestamp and a Piece ID that is pseudorandomly fetched from a list of available Piece IDs using a hash of the user, block difficulty, and block timestamp.
  • Users can create multiple Pieces by calling this contract from either the Piece Package address or Piece Package Gen 1 address.
  • The passed quantity of Pieces will be minted to the passed address.
  • Off-chain logic is used to handle functionality related to the Piece's Package, which is taken as a passed parameter.
  • Users can also "create a sale" for their Piece, approving the Marketplace address to transfer the token, where it then calls createSale() with the user specified starting price.
  • To create a sale, users must pay an owner specified BNB fee.
  • If the contributor of the Piece ID has not been set by the owner, the 0 address will be passed in to the MarketPlace contract's createSale() function.
  • The Marketplace contract was not included in the scope of this audit, so we cannot verify the security or functionality of this contract's interactions with it.
  • The owner an set the contributor of a Piece ID at any time.
  • The owner can update the set of available Pieces at any time.
  • The owner can allow or disallow contracts to receive tokens at any time.
  • When contracts are disallowed, the Marketplace contract address can still receive tokens.
  • The owner can update the base URI at any time.
  • The owner can add or remove any address from a blacklist at any time, preventing them from sending or receiving tokens.
  • The owner can update the Piece price at any time.
  • The owner can update the $Meka token address, Piece Package address, Piece Package Gen 1 address, Marketplace address, and MekaDeployer address at any time.
  • The owner can allow or disallow burns at any time. If burns are disallowed, users can still transfer their tokens to the 0 address to reduce circulating supply, if desired.
  • The owner can disallow the creation of Pieces at any time.
  • The owner can pause the contract at any time, disabling Piece creation, selling, burning, and transfers.
  • The owner can withdraw any BNB or tokens from the contract at any time.
RobotCore Contract:
  • This ERC-721 contract allows users to purchase Robots, attach Pieces to their Robots, and sell their Robots on a marketplace.
  • Users can create a Robot by calling this contract from the MekaDeployer contract.
  • $Meka tokens are transferred from the owner's address to this contract as payment.
  • The amount to be transferred must be greater than or equal to an owner specified "Robot price".
  • A new Robot is then minted to the user with a birth time of the current timestamp.
  • If a user is purchasing a Robot for the first time, they have the ability to purchase a Robot with "ore" instead of $Meka tokens.
  • A user cannot be minted more than a specified mint limit of Robots.
  • Users can purchase multiple Robots by calling this contract from either the Robot Package address or Robot Package Gen 1 address.
  • The passed quantity of Robots will be minted to the passed address. The mint limit is not checked when using this function.
  • Off-chain logic is used to handle functionality related to the Robot's generation, which is based on the specified package type.
  • Users can attach a Piece to a specified Robot by calling this contract from the MekaDeployer contract.
  • $Meka tokens are transferred from the Robot owner's address to this contract as payment.
  • The amount to be transferred must be greater than or equal to an owner specified "attach price".
  • If the owner has enabled a replaceable option, users can overwrite an already attached part with a new one.
  • The owner can enable or disable the replaceable option at any time.
  • Users can also "create a sale" for their Robot, approving the Marketplace address to transfer the token, where it then calls createSale() with the user specified starting price.
  • To create a sale, users must pay an owner specified BNB fee.
  • The Marketplace contract was not included in the scope of this audit, so we cannot verify the security or functionality of this contract's interactions with it.
  • The owner can allow or disallow burns at any time. If burns are disallowed, users can still transfer their tokens to the 0 address to reduce circulating supply, if desired.
  • The owner can allow or disallow contracts to receive tokens at any time.
  • When contracts are disallowed, the Marketplace contract address can still receive tokens.
  • The owner can also update the $Meka token address, Marketplace address, MekaDeployer address, Robot Package address, Robot Package Gen 1 address at any time.
  • The owner can update the base URI at any time.
  • The owner can add or remove any address from a blacklist at any time, preventing them from sending or receiving tokens.
  • The owner can disallow the creation of Robots at any time.
  • The owner can update the attach price, Robot price, BNB fee, and mint limit at any time.
  • The owner can pause the contract at any time, disabling Robot creation, Piece attachment, selling, burning, and transfers.
  • The owner can withdraw any BNB or tokens from the contract at any time.
TokenTimelock Contract:
  • This contract is intended to be used by the project team to facilitate a time-locked token vesting structure to distribute $Meka tokens to various beneficiaries.
  • The owner is able to create a vesting structure for any user at any time, specifying the amount of tokens to lock, the total vesting duration, and the total lock duration.
  • The owner can increase the locked amount or the vesting duration for any beneficiary at any time.
  • The owner can remove a beneficiary from vesting at any time.
  • Any active beneficiary can trigger the release() function in order to claim the amount of tokens that have fully vested.
  • Alternatively, the owner can trigger the release() function on behalf of any active beneficiary in order to deliver the user's vested tokens.
  • Tokens are released to users on a monthly basis.
  • The owner can set the designated token address to any address at any time.
General Notes Across Contracts:
  • Proper structuring of logic is used to prevent reentrancy attacks, including the use of ReentrancyGuard.
  • Solidity 0.8.x is used to prevent any overflows.

Resolved Issues

Resolved #1 - RobotCore & PieceCore - High

Description: Users are able to bypass any limits in these contracts' overridden transferFrom() functions by calling safeTransferFrom();
Risk/Impact: Users will be able to transfer while a contract is paused, transfer to contracts when not permitted to, and bypass blacklists.
Recommendation: Instead of overriding the transferFrom() method, the project team should override the _transfer() function, which is called by both transferFrom() and safeTransferFrom().
Resolution: The team has implemented the above recommendation by overriding the _transfer() function in both contracts, preventing users from bypass transfer limitations.

Resolved #2 - RobotCore - Medium

Description: This contract attempts to allow users to purchase Robots using "ore"; however, the current code prevents this from being possible.
			
if (_withOre) {
	require(_walletBoughtWithOre[_owner], "not-available-with-ore");
	_walletBoughtWithOre[_owner] = true;
}
Risk/Impact: Users will not be able to purchase Robots using ore.
Recommendation: Functionality should be added to allow the _walletBoughtWithOre mapping to be updated.
Resolution: The team has added logic to enable users to purchase Robots with ore for their first Robot purchase only.

Resolved #3 - RobotCore - Informational

Description: The attachPrice variable cannot be updated, but is not declared constant.
Recommendation: This variable can be declared constant for additional gas savings on each reference.
Resolution: The team has added a setter for the attachPrice variable, allowing the price for Piece attachment to be updated by the owner at any time.

Resolved #4 - RobotCore - Informational

Description: The following functions are declared public, but are never called internally:
			
getBalance()
release()
releaseTo()
addBeneficiary()
getBeneficiary()
getAmountToLock()
getAmountToClaim()

Recommendation: These functions can be declared external for additional gas savings on each call.
Resolution: The team has declared the above functions external.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of Control
  • The owner has the permissions listed above.
  • Signed messages require the use of off chain logic.
  • Off-chain logic is also used to handle any functionality related to a Robot's "generation" and a Piece's "package".
  • WARNING
    Delegate Call to Untrusted ContractN/APASS
    Dependence on Predictable VariablesIt is possible for users to predict the Piece ID of a Piece before it is minted to them; however, the likelihood of this along with its use for exploitation is very low.PASS
    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

    MekaDeployer Contract

    Bridge Contract Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
    
     +  Context 
        - [Pub]  #
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] isOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [Int] IBEP20 
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IRobotCore 
        - [Ext] createRobot #
        - [Ext] attachPiece #
        - [Ext] createRobotFromBundle #
    
     + [Int] IPieceCore 
        - [Ext] createPiece #
        - [Ext] burnPiece #
        - [Ext] createPieceFromBundle #
    
     +  MekaDeployer (Ownable)
        - [Pub]  #
        - [Ext] setRobotddress #
           - modifiers: onlyOwner
        - [Ext] setPieceAddress #
           - modifiers: onlyOwner
        - [Ext] setMekaMinersAddress #
           - modifiers: onlyOwner
        - [Ext] setSignatureAddress #
           - modifiers: onlyOwner
        - [Ext] setMekaConversionRate #
           - modifiers: onlyOwner
        - [Ext] getSignatureAddress
           - modifiers: onlyOwner
        - [Ext] convertToMeka #
        - [Ext] convertFromMeka #
        - [Ext] attachToRobot #
        - [Ext] createRobot #
        - [Ext] createPiece #
        - [Pub] getBalance
        - [Ext] withdraw #
           - modifiers: onlyOwner
        - [Pub] getMessageHash
        - [Int] getEthSignedMessageHash
        - [Prv] isContract
        - [Pub] verify
        - [Int] recoverSigner
        - [Int] splitSignature
    
     

    PieceCore Contract

    Bridge Contract Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
     
      + [Int] IBEP20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IMarketplace 
        - [Ext] createSale #
    
     +  Context 
        - [Pub]  #
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] isOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [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] EnumerableSet 
        - [Prv] _add #
        - [Prv] _remove #
        - [Prv] _contains
        - [Prv] _length
        - [Prv] _at
        - [Prv] _values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
    
     +  AccessControl (Context)
        - [Pub] hasRole
        - [Pub] getRoleMemberCount
        - [Pub] getRoleMember
        - [Pub] getRoleAdmin
        - [Pub] grantRole #
        - [Pub] revokeRole #
        - [Pub] renounceRole #
        - [Int] _setupRole #
        - [Int] _setRoleAdmin #
        - [Prv] _grantRole #
        - [Prv] _revokeRole #
    
     + [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 #
    
     + [Lib] SafeMath 
        - [Int] add
        - [Int] sub
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] div
        - [Int] mod
        - [Int] mod
    
     + [Lib] Strings 
        - [Int] toString
    
     + [Int] IERC721Enumerable (IERC721)
        - [Ext] totalSupply
        - [Ext] tokenOfOwnerByIndex
        - [Ext] tokenOfOwner
        - [Ext] tokenByIndex
    
     + [Lib] EnumerableMap 
        - [Prv] _set #
        - [Prv] _remove #
        - [Prv] _contains
        - [Prv] _length
        - [Prv] _at
        - [Prv] _tryGet
        - [Prv] _get
        - [Prv] _get
        - [Int] set #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] tryGet
        - [Int] get
        - [Int] get
    
     + [Int] IERC721Receiver 
        - [Ext] onERC721Received #
    
     + [Int] IERC721Metadata (IERC721)
        - [Ext] name
        - [Ext] symbol
        - [Ext] tokenURI
    
     +  ERC165 (IERC165)
        - [Pub]  #
        - [Pub] supportsInterface
        - [Int] _registerInterface #
    
     +  ERC721 (Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable)
        - [Pub]  #
        - [Pub] balanceOf
        - [Pub] ownerOf
        - [Pub] name
        - [Pub] symbol
        - [Pub] tokenURI
        - [Pub] baseURI
        - [Pub] tokenOfOwnerByIndex
        - [Pub] tokenOfOwner
        - [Pub] totalSupply
        - [Pub] tokenByIndex
        - [Pub] approve #
        - [Pub] getApproved
        - [Pub] setApprovalForAll #
        - [Pub] isApprovedForAll
        - [Pub] transferFrom #
        - [Pub] safeTransferFrom #
        - [Pub] safeTransferFrom #
        - [Int] _safeTransfer #
        - [Int] _exists
        - [Int] _isApprovedOrOwner
        - [Int] _safeMint #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _transfer #
        - [Int] _setTokenURI #
        - [Int] _setBaseURI #
        - [Prv] _checkOnERC721Received #
        - [Int] _approve #
        - [Int] _beforeTokenTransfer #
    
     +  Pausable (Ownable)
        - [Pub] _pause #
           - modifiers: onlyOwner,whenNotPaused
        - [Pub] _unpause #
           - modifiers: onlyOwner,whenPaused
    
     +  ERC721Pausable (ERC721, Pausable)
        - [Int] _beforeTokenTransfer #
           - modifiers: whenNotPaused
    
     + [Int] IPieceCore 
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     +  PieceCore (Ownable, ERC721Pausable, IPieceCore, ReentrancyGuard)
        - [Pub]  #
           - modifiers: ERC721
        - [Ext] setContributorPieceId #
           - modifiers: onlyOwner
        - [Ext] updateAcceptContract #
           - modifiers: onlyOwner
        - [Ext] setAvailablePieces #
           - modifiers: onlyOwner
        - [Ext] isBlacklisted
        - [Ext] setBlackList #
           - modifiers: onlyOwner
        - [Ext] setPiecePrice #
           - modifiers: onlyOwner
        - [Ext] setTokenAddress #
           - modifiers: onlyOwner
        - [Ext] setPiecePackageAddress #
           - modifiers: onlyOwner
        - [Ext] setPiecePackageGen1Address #
           - modifiers: onlyOwner
        - [Ext] setMarketplaceAddress #
           - modifiers: onlyOwner
        - [Ext] setMekaDeployerAddress #
           - modifiers: onlyOwner
        - [Ext] updateIsBurn #
           - modifiers: onlyOwner
        - [Ext] updatePieceFactory #
           - modifiers: onlyOwner
        - [Ext] setTokenURI #
        - [Ext] withdrawBalance #
           - modifiers: onlyOwner
        - [Ext] withdrawBnb #
           - modifiers: onlyOwner
        - [Prv] _mintPiece #
        - [Ext] createPiece #
           - modifiers: onlyMekaDeploy,pieceFactory,whenNotPaused
        - [Ext] createSale #
           - modifiers: whenNotPaused
        - [Ext] burnPiece #
           - modifiers: whenNotPaused
        - [Ext] getContributorPieces
        - [Pub] getPiece
        - [Ext] getAvailablePieces
        - [Pub] getBalance
        - [Ext] createPieceFromBundle #
           - modifiers: onlyBundle,pieceFactory,whenNotPaused
        - [Pub] transferFrom #
           - modifiers: whenNotPaused
        - [Prv] isContract
        - [Prv] random
    
    
    
    

    RobotCore Contract

    Bridge Contract Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
     
      + [Int] IBEP20 
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IMarketplace 
        - [Ext] createSale #
    
     +  Context 
        - [Pub]  #
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] isOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [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 #
    
     + [Lib] SafeMath 
        - [Int] add
        - [Int] sub
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] div
        - [Int] mod
        - [Int] mod
    
     + [Lib] Strings 
        - [Int] toString
    
     + [Lib] Address 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] functionDelegateCall #
        - [Int] functionDelegateCall #
        - [Int] verifyCallResult
    
     + [Int] IERC721Enumerable (IERC721)
        - [Ext] totalSupply
        - [Ext] tokenOfOwnerByIndex
        - [Ext] tokenOfOwner
        - [Ext] tokenByIndex
    
     + [Lib] EnumerableSet 
        - [Prv] _add #
        - [Prv] _remove #
        - [Prv] _contains
        - [Prv] _length
        - [Prv] _at
        - [Prv] _values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
        - [Int] add #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] values
    
     + [Lib] EnumerableMap 
        - [Prv] _set #
        - [Prv] _remove #
        - [Prv] _contains
        - [Prv] _length
        - [Prv] _at
        - [Prv] _tryGet
        - [Prv] _get
        - [Prv] _get
        - [Int] set #
        - [Int] remove #
        - [Int] contains
        - [Int] length
        - [Int] at
        - [Int] tryGet
        - [Int] get
        - [Int] get
    
     + [Int] IERC721Receiver 
        - [Ext] onERC721Received #
    
     + [Int] IERC721Metadata (IERC721)
        - [Ext] name
        - [Ext] symbol
        - [Ext] tokenURI
    
     +  ERC165 (IERC165)
        - [Pub]  #
        - [Pub] supportsInterface
        - [Int] _registerInterface #
    
     +  ERC721 (Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable)
        - [Pub]  #
        - [Pub] balanceOf
        - [Pub] ownerOf
        - [Pub] name
        - [Pub] symbol
        - [Pub] tokenURI
        - [Pub] baseURI
        - [Pub] tokenOfOwnerByIndex
        - [Pub] tokenOfOwner
        - [Pub] totalSupply
        - [Pub] tokenByIndex
        - [Pub] approve #
        - [Pub] getApproved
        - [Pub] setApprovalForAll #
        - [Pub] isApprovedForAll
        - [Pub] transferFrom #
        - [Pub] safeTransferFrom #
        - [Pub] safeTransferFrom #
        - [Int] _safeTransfer #
        - [Int] _exists
        - [Int] _isApprovedOrOwner
        - [Int] _safeMint #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _transfer #
        - [Int] _setTokenURI #
        - [Int] _setBaseURI #
        - [Prv] _checkOnERC721Received #
        - [Int] _approve #
        - [Int] _beforeTokenTransfer #
    
     +  Pausable (Ownable)
        - [Pub] _pause #
           - modifiers: onlyOwner,whenNotPaused
        - [Pub] _unpause #
           - modifiers: onlyOwner,whenPaused
    
     +  ERC721Pausable (ERC721, Pausable)
        - [Int] _beforeTokenTransfer #
           - modifiers: whenNotPaused
    
     + [Int] IRobotCore 
    
     +  ReentrancyGuard 
        - [Pub]  #
    
     +  RobotCore (Ownable, ERC721Pausable, IRobotCore, ReentrancyGuard)
        - [Pub]  #
           - modifiers: ERC721
        - [Ext] updateAcceptContract #
           - modifiers: onlyOwner
        - [Ext] updateCanReplacePiece #
           - modifiers: onlyOwner
        - [Ext] isBlacklisted
        - [Ext] setBlackList #
           - modifiers: onlyOwner
        - [Ext] setPackageLimit #
           - modifiers: onlyOwner
        - [Ext] setBnbFee #
           - modifiers: onlyOwner
        - [Ext] setMarketplaceAddress #
           - modifiers: onlyOwner
        - [Ext] setRobotPackageAddress #
           - modifiers: onlyOwner
        - [Ext] setRobotPackageGen1Address #
           - modifiers: onlyOwner
        - [Ext] setMekaDeployerAddress #
           - modifiers: onlyOwner
        - [Ext] setRobotPrice #
           - modifiers: onlyOwner
        - [Ext] setTokenAddress #
           - modifiers: onlyOwner
        - [Ext] setTokenURI #
        - [Ext] updateIsBurn #
           - modifiers: onlyOwner
        - [Ext] updateRobotFactory #
           - modifiers: onlyOwner
        - [Ext] withdrawBalance #
           - modifiers: onlyOwner
        - [Ext] withdrawBnb #
           - modifiers: onlyOwner
        - [Prv] _mintRobot #
        - [Ext] attachPiece #
           - modifiers: onlyMekaDeploy,whenNotPaused
        - [Ext] createRobot #
           - modifiers: onlyMekaDeploy,robotFactory,whenNotPaused
        - [Ext] createSale ($)
           - modifiers: whenNotPaused
        - [Ext] burnRobot #
           - modifiers: whenNotPaused
        - [Ext] getRobot
        - [Pub] getBalance
        - [Ext] createRobotFromBundle #
           - modifiers: onlyBundle,robotFactory,whenNotPaused
        - [Pub] transferFrom #
           - modifiers: whenNotPaused
        - [Prv] isContract
    
    
     

    TokenTimelock Contract

    Bridge Contract Graph

    Multi-file Token

    												
    ($) = payable function
     # = non-constant function
     
     + [Int] IBEP20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     +  Context 
        - [Pub]  #
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] isOwner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [Lib] SafeMath 
        - [Int] add
        - [Int] sub
        - [Int] sub
        - [Int] mul
        - [Int] div
        - [Int] div
        - [Int] mod
        - [Int] mod
    
     +  TokenTimelock (Ownable)
        - [Pub]  #
        - [Ext] setTokenAddress #
           - modifiers: onlyOwner
        - [Pub] getBalance
        - [Pub] release #
           - modifiers: onlyBeneficiary
        - [Pub] releaseTo #
           - modifiers: onlyOwner
        - [Pub] addBeneficiary #
           - modifiers: onlyOwner
        - [Pub] getBeneficiary
        - [Pub] getAmountToLock
        - [Pub] getAmountToClaim
        - [Prv] executeRelease #
        - [Prv] calculateClaimable
        - [Prv] amountToRelease