MetaBots - Smart Contract Audit Report

Audit Summary

MetaBots is a new ERC-20 token that features automatic liquidity adds and pays out dividends to holders.

We reviewed the MetaBots and MetaBotsDividendTracker contracts at commit 23138fbcd3216f184e6f3193375ceeb8f6668e65 on the team's Github repository.

Audit Findings

Please ensure trust in the team as they have substantial control in the ecosystem.
Date: February 2nd, 2022.

Finding #1 - MetaBots - Informational

Description: Several functions are declared public, but are never called internally.
			
setFees, setBuybackAddress, changeMarketingAddress, changeDevelopmentAddress, changePSIAddress, changeLiquidityAddress, changeMinTokensBeforeSwap, changeSellLimit
Recommendation: We recommend declaring these functions external for additional gas savings on each call.

Contracts Overview

  • The total supply of the token is set to 1 billion [1,000,000,000].
  • No mint functions are accessible beyond deployment.
  • Any user can burn their own tokens to reduce the total supply.
  • There was no token allocation for our team to analyze as the contract has yet to be deployed to the mainnet.

  • There is a tax fee on all transfers via Uniswap where neither the sender nor the recipient is excluded from fees.
  • The fee charged on transfers is stored in the contract and once the threshold number of tokens (determined by the owner) is met, a swap will occur for the purpose of funding Uniswap liquidity.
  • Liquidity-adds are funded by selling a portion of the tokens collected as fees (after the threshold value of tokens is met), then pairing the received ETH with the token, and adding it as liquidity to the ETH pair.
  • The LP tokens received through this process are sent to the Liquidity wallet set by the team. We recommend that the team lock these newly acquired LP tokens.
  • The tokens collected from the PSI fee are swapped for $PSI and are distributed as dividends in the MetaBotsDividendTracker contract.
  • The tokens collected from the Marketing Fee and Development fee are swapped for ETH and sent to the team's Marketing wallet and Development wallet respectively.
  • The remaining tokens are swapped for ETH and sent to the team's Buyback wallet.

  • The contract enforces a sell limit when selling tokens to Uniswap for all users except for the MetaBots contract address and team's Liquidity wallet. The number of tokens that a user can sell within 24 hours cannot exceed 5% of the current token balance of the Liquidity pool.
  • Users who attempt to sell within 24 hours of their last recorded sell time will face an extended wait time based on the amount of time that has passed and the number of tokens that the user is trying to sell relative to the number of tokens that they have already sold within 24 hours.
  • Any user can call the multiTransfer() function to airdrop tokens to any number of addresses. A for loop is used to transfer funds for the airdrop; The team must ensure the maximum number of addresses that can be involved in a single airdrop is no more than 350 to prevent this loop from hitting the block gas limit.
  • The contract is upgradeable, meaning the team can swap out the current contract for a new one at any time.
  • The contract implements the EIP-2612 standard in order to support permits which allows for approvals to be made via signatures.
  • The contract implements the EIP-1363 standard in order to support transfer-and-call and approve-and-call functionality.
  • As the contract is implemented with Solidity v0.8.x it is protected from overflows/underflows.

  • A user must hold the minimum amount (determined by the owner) of the parent token to be eligible for dividends. The parent token will be set by the owner in the MetaBotsDividendTracker contract upon deployment.
  • Once dividends are distributed, they will need to be claimed; claiming happens automatically on each transfer.
  • Dividend rewards can also be claimed manually by kicking off the claim cycle, which will process all eligible token holders.
  • There is a wait-time (set by the owner) between claiming dividend rewards.
  • Claimed dividends are sent to the user's wallet address.
Ownership Controls:
  • The owner can set the PSI fee, Liquidity fee, Buyback fee, Development fee, and Marketing fee, to any percentages as long as the total fee percentages combined do not exceed 20%.
  • The owner can exclude any address from transfer fees and dividends at any time.
  • The owner can update the dividend reward token to any address at any time.
  • The owner can enable/disable the automatic token swapping functionality as well as manually trigger it at any time.
  • The owner can update the threshold number of tokens that triggers the token swapping functionality to any value at any time.
  • The owner can update the sell limit to any percentage between 1% and 100% at any time.
  • The owner can enable/disable the sell limit restriction at any time.
  • The owner can pause/unpause all trading with Uniswap at any time.
  • The owner can withdraw any ETH or tokens (except for the dividend token) from the MetaBotsDividendTracker contract address at any time.
  • The owner can update the token address that is distributed to the MetaBotsDividendTracker contract as dividends.
  • The owner can update the maximum amount of gas used for processing to a value between 200,000 and 500,000 at any time.
  • The owner can update the amount of time a user must wait between claiming dividends to a value between 1 and 24 hours (in seconds).
  • The owner can update the team's Marketing wallet, Development Wallet, Liquidity wallet, and Buyback wallet to any addresses at any time.
  • The owner can update the Dividend Tracker, Automated Market Maker Pair, and Uniswap Router addresses at any time.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of Control
  • The owner can set total fees on transfers via Uniswap up to 20%.
  • The team can upgrade the token contract at any time.
  • The LP tokens generated through automatic liquidity adds are sent to the Liquidity wallet controlled by the team.
  • The owner can pause all transfers via Uniswap at any time.
  • WARNING
    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
    Logical IssuesN/APASS
    Multiple SendsN/APASS
    OraclesN/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

    BEP20 Token Graph

    Inheritance Chart

    Multi-file Token

    Functions Overview

    												
    ($) = payable function
     # = non-constant function
    
     + [Lib] AddressUpgradeable 
        - [Int] isContract
        - [Int] sendValue #
        - [Int] functionCall #
        - [Int] functionCall #
        - [Int] functionCallWithValue #
        - [Int] functionCallWithValue #
        - [Int] functionStaticCall
        - [Int] functionStaticCall
        - [Int] verifyCallResult
    
     +  Initializable 
        - [Prv] _isConstructor
    
     +  ContextUpgradeable (Initializable)
        - [Int] __Context_init #
           - modifiers: onlyInitializing
        - [Int] __Context_init_unchained #
           - modifiers: onlyInitializing
        - [Int] _msgSender
        - [Int] _msgData
    
     +  OwnableUpgradeable (Initializable, ContextUpgradeable)
        - [Int] __Ownable_init #
           - modifiers: onlyInitializing
        - [Int] __Ownable_init_unchained #
           - modifiers: onlyInitializing
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     + [Int] IERC20Upgradeable 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IERC20MetadataUpgradeable (IERC20Upgradeable)
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Ownable (Context)
        - [Pub]  #
        - [Pub] owner
        - [Pub] renounceOwnership #
           - modifiers: onlyOwner
        - [Pub] transferOwnership #
           - modifiers: onlyOwner
        - [Int] _transferOwnership #
    
     +  ERC20Upgradeable (Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable)
        - [Int] __ERC20_init #
           - modifiers: onlyInitializing
        - [Int] __ERC20_init_unchained #
           - modifiers: onlyInitializing
        - [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] _afterTokenTransfer #
    
     + [Int] IERC165Upgradeable 
        - [Ext] supportsInterface
    
     +  ERC165Upgradeable (Initializable, IERC165Upgradeable)
        - [Int] __ERC165_init #
           - modifiers: onlyInitializing
        - [Int] __ERC165_init_unchained #
           - modifiers: onlyInitializing
        - [Pub] supportsInterface
    
     + [Int] IERC1363 
        - [Ext] transferAndCall #
        - [Ext] transferAndCall #
        - [Ext] transferFromAndCall #
        - [Ext] transferFromAndCall #
        - [Ext] approveAndCall #
        - [Ext] approveAndCall #
    
     + [Int] IERC1363Receiver 
        - [Ext] onTransferReceived #
    
     + [Int] IERC1363Spender 
        - [Ext] onApprovalReceived #
    
     +  ERC1363Upgradeable (ERC165Upgradeable, ERC20Upgradeable, IERC1363)
        - [Pub] supportsInterface
        - [Pub] transferAndCall #
        - [Pub] transferAndCall #
        - [Pub] transferFromAndCall #
        - [Pub] transferFromAndCall #
        - [Pub] approveAndCall #
        - [Pub] approveAndCall #
        - [Int] _checkAndCallTransfer #
        - [Int] _checkAndCallApprove #
    
     + [Lib] ECDSAUpgradeable 
        - [Prv] _throwError
        - [Int] tryRecover
        - [Int] recover
        - [Int] tryRecover
        - [Int] recover
        - [Int] tryRecover
        - [Int] recover
        - [Int] toEthSignedMessageHash
        - [Int] toEthSignedMessageHash
        - [Int] toTypedDataHash
    
     +  EIP712Upgradeable (Initializable)
        - [Int] __EIP712_init #
           - modifiers: onlyInitializing
        - [Int] __EIP712_init_unchained #
           - modifiers: onlyInitializing
        - [Int] _domainSeparatorV4
        - [Prv] _buildDomainSeparator
        - [Int] _hashTypedDataV4
        - [Int] _EIP712NameHash
        - [Int] _EIP712VersionHash
    
     + [Lib] StringsUpgradeable 
        - [Int] toString
        - [Int] toHexString
        - [Int] toHexString
    
     + [Lib] CountersUpgradeable 
        - [Int] current
        - [Int] increment #
        - [Int] decrement #
        - [Int] reset #
    
     + [Int] IERC2612 
        - [Ext] DOMAIN_SEPARATOR
        - [Ext] nonces
        - [Ext] permit #
        - [Ext] transferWithPermit #
    
     +  ERC2612Upgradeable (ERC165Upgradeable, ERC20Upgradeable, EIP712Upgradeable, IERC2612)
        - [Int] __ERC2612_init #
           - modifiers: initializer
        - [Int] __ERC2612_init_unchained #
           - modifiers: initializer
        - [Pub] supportsInterface
        - [Pub] nonces
        - [Ext] DOMAIN_SEPARATOR
        - [Ext] permit #
        - [Ext] transferWithPermit #
        - [Int] verifyPermit #
        - [Int] verifyEIP712
        - [Int] verifyPersonalSign
        - [Int] _useNonce #
    
     + [Int] IERC20BurnableUpgradeable 
        - [Ext] burn #
        - [Ext] burnFrom #
    
     +  ERC20BurnableUpgradeable (ERC20Upgradeable, IERC20BurnableUpgradeable)
        - [Pub] burn #
        - [Pub] burnFrom #
    
     + [Lib] SafeERC20Upgradeable 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     + [Int] IERC20TokenRecoverUpgradeable 
        - [Ext] recoverERC20 #
        - [Ext] recoverETH #
    
     +  ERC20TokenRecoverUpgradeable (OwnableUpgradeable, IERC20TokenRecoverUpgradeable)
        - [Pub] recoverERC20 #
           - modifiers: onlyOwner
        - [Pub] recoverETH #
           - modifiers: onlyOwner
    
     + [Int] IDEXFactory 
        - [Ext] feeTo
        - [Ext] feeToSetter
        - [Ext] getPair
        - [Ext] allPairs
        - [Ext] allPairsLength
        - [Ext] createPair #
        - [Ext] setFeeTo #
        - [Ext] setFeeToSetter #
    
     + [Int] IDEXPair 
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transfer #
        - [Ext] transferFrom #
        - [Ext] DOMAIN_SEPARATOR
        - [Ext] PERMIT_TYPEHASH
        - [Ext] nonces
        - [Ext] permit #
        - [Ext] MINIMUM_LIQUIDITY
        - [Ext] factory
        - [Ext] token0
        - [Ext] token1
        - [Ext] getReserves
        - [Ext] price0CumulativeLast
        - [Ext] price1CumulativeLast
        - [Ext] kLast
        - [Ext] mint #
        - [Ext] burn #
        - [Ext] swap #
        - [Ext] skim #
        - [Ext] sync #
        - [Ext] initialize #
    
     + [Int] IERC20TokenRecover 
        - [Ext] recoverERC20 #
        - [Ext] recoverETH #
    
     + [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] SafeERC20 
        - [Int] safeTransfer #
        - [Int] safeTransferFrom #
        - [Int] safeApprove #
        - [Int] safeIncreaseAllowance #
        - [Int] safeDecreaseAllowance #
        - [Prv] _callOptionalReturn #
    
     +  ERC20TokenRecover (Ownable, IERC20TokenRecover)
        - [Pub] recoverERC20 #
           - modifiers: onlyOwner
        - [Pub] recoverETH #
           - modifiers: onlyOwner
    
     + [Int] IDEXRouter 
        - [Ext] factory
        - [Ext] WETH
        - [Ext] addLiquidity #
        - [Ext] addLiquidityETH ($)
        - [Ext] removeLiquidity #
        - [Ext] removeLiquidityETH #
        - [Ext] removeLiquidityWithPermit #
        - [Ext] removeLiquidityETHWithPermit #
        - [Ext] swapExactTokensForTokens #
        - [Ext] swapTokensForExactTokens #
        - [Ext] swapExactETHForTokens ($)
        - [Ext] swapTokensForExactETH #
        - [Ext] swapExactTokensForETH #
        - [Ext] swapETHForExactTokens ($)
        - [Ext] quote
        - [Ext] getAmountOut
        - [Ext] getAmountIn
        - [Ext] getAmountsOut
        - [Ext] getAmountsIn
        - [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
        - [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
        - [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
        - [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
        - [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
    
     + [Int] IERC20Metadata (IERC20)
        - [Ext] name
        - [Ext] symbol
        - [Ext] decimals
    
     + [Int] IBEP20 (IERC20Metadata)
        - [Ext] getOwner
    
     + [Int] IDividendPayingTokenInterface 
        - [Ext] dividendToken
        - [Ext] parentToken
        - [Ext] totalDividendsDistributed
        - [Ext] dividendOf
        - [Ext] withdrawDividend #
        - [Ext] distributeDividends #
    
     + [Int] IDividendPayingTokenOptionalInterface 
        - [Ext] withdrawableDividendOf
        - [Ext] withdrawnDividendOf
        - [Ext] accumulativeDividendOf
    
     + [Int] IDividendTracker (IBEP20, IDividendPayingTokenInterface, IDividendPayingTokenOptionalInterface)
        - [Ext] lastProcessedIndex
        - [Ext] excludedFromDividends
        - [Ext] lastClaimTimes
        - [Ext] claimWait
        - [Ext] minimumTokenBalanceForDividends
        - [Ext] excludeFromDividends #
        - [Ext] includeInDividends #
        - [Ext] updateClaimWait #
        - [Ext] updateMinTokenBalance #
        - [Ext] getLastProcessedIndex
        - [Ext] getNumberOfTokenHolders
        - [Ext] getAccount
        - [Ext] getAccountAtIndex
        - [Ext] ensureBalance #
        - [Ext] ensureBalanceForUsers #
        - [Ext] ensureBalanceForUser #
        - [Ext] setBalance #
        - [Ext] process #
        - [Ext] processAccount #
    
     +  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] _afterTokenTransfer #
    
     +  DividendPayingToken (Ownable, ERC20, IDividendPayingTokenInterface, IDividendPayingTokenOptionalInterface)
        - [Pub]  #
           - modifiers: ERC20
        - [Pub] distributeDividends #
           - modifiers: onlyOwnerOrParentToken
        - [Pub] withdrawDividend #
        - [Int] _withdrawDividendOfUser #
        - [Pub] dividendOf
        - [Pub] withdrawableDividendOf
        - [Pub] withdrawnDividendOf
        - [Pub] accumulativeDividendOf
        - [Int] _transfer #
        - [Int] _mint #
        - [Int] _burn #
        - [Int] _setBalance #
    
     +  MetaBots (OwnableUpgradeable, ERC20Upgradeable, ERC1363Upgradeable, ERC2612Upgradeable, ERC20BurnableUpgradeable, ERC20TokenRecoverUpgradeable)
        - [Ext]  ($)
        - [Pub] initialize #
           - modifiers: initializer
        - [Ext] initPSIDividendTracker #
           - modifiers: onlyOwner
        - [Ext] updatePSIDividendTracker #
           - modifiers: onlyOwner
        - [Pub] supportsInterface
        - [Pub] setFees #
           - modifiers: onlyOwner
        - [Pub] setBuybackAddress #
           - modifiers: onlyOwner
        - [Pub] changeMarketingAddress #
           - modifiers: onlyOwner
        - [Pub] changeDevelopmentAddress #
           - modifiers: onlyOwner
        - [Pub] changePSIAddress #
           - modifiers: onlyOwner
        - [Pub] changeLiquidityAddress #
           - modifiers: onlyOwner
        - [Pub] setFeeExcludedForAddress #
           - modifiers: onlyOwner
        - [Pub] excludeFromFeesAndDividends #
           - modifiers: onlyOwner
        - [Pub] changeMinTokensBeforeSwap #
           - modifiers: onlyOwner
        - [Ext] addNewRouter #
           - modifiers: onlyOwner
        - [Ext] setAutomatedMarketMakerPair #
           - modifiers: onlyOwner
        - [Prv] _setAutomatedMarketMakerPair #
        - [Ext] updateGasForProcessing #
           - modifiers: onlyOwner
        - [Ext] processDividendTracker #
        - [Ext] setSwapAndLiquifyEnabled #
           - modifiers: onlyOwner
        - [Pub] changeSellLimit #
           - modifiers: onlyOwner
        - [Ext] toggleSellAmountLimited #
           - modifiers: onlyOwner
        - [Ext] toggleTradingPaused #
           - modifiers: onlyOwner
        - [Ext] multiTransfer #
        - [Int] _transfer #
        - [Prv] checkSellLimit #
        - [Prv] _transferExcluded #
        - [Prv] _transferWithFees #
        - [Prv] _fixDividendTrackerBalancer #
        - [Ext] performSwapAndLiquify #
           - modifiers: onlyOwner
        - [Prv] swapAndLiquify #
           - modifiers: lockTheSwap
        - [Prv] swapTokensForEth #
        - [Prv] addLiquidity #
        - [Prv] swapAndSendDividends #
        - [Prv] swapETHForPSI #
    
     + [Lib] IterableMapping 
        - [Int] get
        - [Int] getIndexOfKey
        - [Int] getKeyAtIndex
        - [Int] size
        - [Int] set #
        - [Int] remove #
    
     +  MetaBotsDividendTracker (Ownable, DividendPayingToken, ERC20TokenRecover, IDividendTracker)
        - [Pub]  #
           - modifiers: DividendPayingToken
        - [Pub] getOwner
        - [Pub] recoverERC20 #
           - modifiers: onlyOwnerOrParentToken
        - [Int] _transfer
        - [Pub] withdrawDividend
        - [Ext] excludeFromDividends #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] includeInDividends #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] updateClaimWait #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] updateMinTokenBalance #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] getLastProcessedIndex
        - [Ext] getNumberOfTokenHolders
        - [Pub] getAccount
        - [Ext] getAccountAtIndex
        - [Prv] canAutoClaim
        - [Ext] ensureBalance #
        - [Ext] ensureBalanceForUsers #
           - modifiers: onlyOwnerOrParentToken
        - [Prv] bytesToAddress
        - [Pub] ensureBalanceForUser #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] setBalance #
           - modifiers: onlyOwnerOrParentToken
        - [Ext] process #
        - [Pub] processAccount #
           - modifiers: onlyOwnerOrParentToken