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.Recommendation: We recommend declaring these functions external for additional gas savings on each call.setFees, setBuybackAddress, changeMarketingAddress, changeDevelopmentAddress, changePSIAddress, changeLiquidityAddress, changeMinTokensBeforeSwap, changeSellLimit
Contracts Overview
Ownership Controls:
- 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.
- 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 Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Centralization of Control | WARNING | |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
Function Graph
Inheritance Chart
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