ApolloRebase - Smart Contract Audit Report

Summary

ApolloRebase Audit Report ApolloRebase ($APR) is a new rebase token developed for the Binance Smart Chain that provides automatic liquidity adds and pays holders dividends in BUSD. We audited ApolloRebase's token contract by using code that was provided to us by the team, as it is not yet deployed to the mainnet.

Overview of the Contract:
  • The total supply of the token is set to one quadrillion $APR [1,000,000,000,000,000]. The deployer will be granted these tokens upon contract creation.
  • No mint or burn functions are present; though the circulating supply can be reduced by sending tokens to the 0x..dead address, if desired.
  • As the project has not been deployed to the mainnet, our team did not have a token holder distribution to analyze.
  • The contract is developed to function as a "Negative-Rebase" token. The team has the ability to activate a 'rebase' mechanism that will automatically adjust the token's circulating supply according to a rebase percentage determined by the team.
  • The intention of this mechanism is (in theory) to periodically rebase the circulating supply to continuously increase the price of an individual token (while reducing each holder's supply at the provided rate). When rebasing occurs, the total market cap for the token will not be directly effected in any way as a result of this mechanism.
  • The rebase function properly calls sync() on the PancakeSwap Pair contract to prevent theft-of-liquidity attacks which have occured with other rebase tokens.
  • Transfers of the token are initially disabled until the team indicates token distribution has been completed.

  • There is a "Marketing Fee", "Dev Fee", Liquidity Fee", and "Reflection Fee" on all transfers where the transferring address is not excluded from fees.
  • The fees that are taxed on transactions are stored in the contract address balance. Once a threshold value of $APR (specified by the team) is met, the tokens are swapped for WBNB for the purpose of being distributed to the 'Dev Fee Receiver', 'Marketing Fee Receiver', Dividend Distributor Contract, and to support the automatic liquidity adding mechanism.
  • The portion that is allocated toward automatic liquidity adds will have half of the tokens swapped for WBNB, and will pair the received WBNB with the other half of the tokens, which are then added as liquidity to the pair.
  • The LP tokens received through this process are stored in the "Liquidity Fee Receiver". This address is controlled by the team and we recommend that the LP tokens are locked each time they are acquired.
  • The portion of the tokens allocated to the "Marketing Fee" and "Dev Fee" are swapped for WBNB that is instantly sent to team-controlled "Marketing Fee Receiver" and "Dev Fee Receiver" addresses.
  • The final portion of the tokens that are allocated to the "Reflection Fee" are swapped for WBNB that is instantly sent to to the Dividend Distributor Contract by use of the deposit function. The WBNB that is received by the contract will automatically swap the WBNB for BUSD which is subsequently stored in the contract address until dividends are distributed.

  • A user must hold an amount of $APR tokens (specified by the team) to be eligible for BUSD dividends.
  • 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.
  • Alternatively, a user can manually claim dividends as an individual.
  • There is a wait-time of 2700 seconds (45 minutes) between claiming dividend rewards.
  • Claimed dividends are sent to the user's wallet address.

  • Some gas optimizations can be achieved through marking functions external instead of public. There are also some global variables that could be declared constant.
  • There are six functions that used calculations where multiplication was being applied to the result of a divison. This can potentially result in calculations being less-precise. Dividing usually leads to integer truncation which is then subsequently multiplied. We recommend multiplying before dividing in calculations to reduce precision-loss as much as possible.
  • The contract utilizes the SafeMath library to prevent overflows along with following the BEP20 standard.

  • Ownership Controls:
    The ApolloRebase team has 3 roles that can be assigned to maintain control various role-restricted functions within the ecosystem. The following roles are: "Owner", "Master", and "Authorized" addresses.

  • The 'Master' can update the rebase percentage to any amount ranging from 0 - 10%, at any time.

  • The owner can set a new address as 'Master' at any time.
  • The owner can update the rebase percentage to any amount at any time, and must exercise caution when doing so.
  • The owner can intiate the rebase mechanism at any time, as long as the contract is not currently swapping.
  • The owner can enable or disable trading at any time. This will prevent all transfers unless the sender or recipient is an ‘Authorized’ address.
  • The owner can update the ‘sell multiplier’ value to any amount, at any time. Given that fees are capped at a total of 33%, if the sell multiplier is greater than 300 (x3), then any transfers involving tokens being sold to the DEX will effectively absorbed by the contract's fees. The team should exercise caution when setting this multiplier to ensure that holders are not locked out of selling.
  • The owner can manually set the "launched At" block to any value at any time. We strongly recommend that this function is only used once by providing the correct block, to avoid setting all non-selling transfer fees to 99%.
  • The owner can enable/disable the use of a blacklist, as well as add/remove addresses from it at any time. Addresses that are added to the blacklist will not be able to participate in token transfers.
  • The owner can set and update a cooldown time that must elapse in between transfers when the same address is buying tokens from the DEX.
  • The owner can set and update a 'maximum wallet amount' at any time. The maximum wallet amount will prevent transfers from occurring if the recipient's amount of owned $APR tokens will exceed the threshold that is set by the team.
  • The owner can set and update a 'maximum transaction percent' at any time, which will impose a limit to the number of tokens that can be transferred during any given transaction. The team will need to evaluate these limits regularly as rebases occur, as it will need to be recalculated to maintain the desired effect.
  • WARNING: The owner can initiate $APR token airdrops that are funded by any address that the owner specifies. The airdrop value can be set to either a fixed or a custom amount of $APR tokens to be sent to each recipient address included in the airdrop. We strongly recommend that the team changes the airdrops to be funded by the msg.sender.
  • The owner can transfer any BEP20 Token held in the contract address to themself at any time.
  • The owner can add (or remove) any addresses to the "Authorized" role at any time. We recommend limited the number of addresses with this role to prevent potential misuse.

  • Authorized addresses can set each fee percentage to any amount at any time as long as the sum of the fees does not exceed 33%.
  • Authorized addresses can update the "Liquidity Fee Receiver", "Marketing Fee Receiver", and "Dev Fee Receiver" addresses at any time.
  • Authorized addresses can exclude addresses from fees, cooldowns, and the "maximum transaction percent" at any time.
  • Authorized addresses can exclude any address from dividends at any time.
  • Authorized addresses can enable and disable swapping; and update the contract token balance threshold for swapping at any time.
  • Authorized addresses can update the value used to determine if the liquidity pool is "over-liquified" at any time. When it is determined that the pool is over-liquified, the a portion of the funds that would be used to add liquidity are distributed are absorbed by the other 3 funds (Marketing, Dev, and Dividends).
  • Authorized addresses can update the maximum amount of gas used for processing to a value between 0 and 899999 at any time. We do not recommend setting a value below 200000.
  • Authorized addresses can update the amount of time must elapse between claiming dividends to any amount of time. Authorized addresses can also update the minimum rewards payout that a holder must have in order to be able to claim. We recommend the team exercises caution when setting these values, to avoid locking out holders from claiming entirely.
  • Authorized addresses can transfer any BNB that is held in the contract address balance to either themself or the "Marketing Fee Receive" at any time.

Audit Findings Summary
  • No threats from outside attackers were identified.
  • The owner has the ability to transfer any amount of any holder's tokens to themself at any time.
  • Please ensure trust in the team prior to investing, as they have substantial control in the ecosystem.
  • We recommend that the team minimized the number of "Authorized" addresses, and limits the use of role-restricted functions.
  • Further, ensure trust in the team as they have control of the tokens/WBNB accumulated from fees, and have various means of locking holders out of transfers and dividends.
  • Date: October 21st, 2021

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Token/Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/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

BEP20 Token Graph

Multi-file Token

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

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

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

 + [Lib] SafeMathInt 
    - [Int] mul
    - [Int] div
    - [Int] sub
    - [Int] add
    - [Int] abs

 + [Int] IBEP20 
    - [Ext] totalSupply
    - [Ext] decimals
    - [Ext] symbol
    - [Ext] name
    - [Ext] getOwner
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] transferFrom #

 +  Auth 
    - [Pub]  #
    - [Pub] authorize #
       - modifiers: onlyOwner
    - [Pub] unauthorize #
       - modifiers: onlyOwner
    - [Pub] isOwner
    - [Pub] isAuthorized
    - [Pub] transferOwnership #
       - modifiers: onlyOwner

 + [Int] IDEXFactory 
    - [Ext] createPair #

 + [Int] InterfaceLP 
    - [Ext] sync #

 + [Int] IDEXRouter 
    - [Ext] factory
    - [Ext] WETH
    - [Ext] addLiquidity #
    - [Ext] addLiquidityETH ($)
    - [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
    - [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
    - [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #

 + [Int] IDividendDistributor 
    - [Ext] setDistributionCriteria #
    - [Ext] setShare #
    - [Ext] deposit ($)
    - [Ext] process #

 +  DividendDistributor (IDividendDistributor)
    - [Pub]  #
    - [Ext] setDistributionCriteria #
       - modifiers: onlyToken
    - [Ext] setShare #
       - modifiers: onlyToken
    - [Ext] deposit ($)
       - modifiers: onlyToken
    - [Ext] process #
       - modifiers: onlyToken
    - [Int] shouldDistribute
    - [Int] distributeDividend #
    - [Ext] claimDividend #
    - [Pub] getUnpaidEarnings
    - [Int] getCumulativeDividends
    - [Int] addShareholder #
    - [Int] removeShareholder #

 +  APOLLOREBASE (IBEP20, Auth)
    - [Pub] rebase_percentage_master #
       - modifiers: onlyMaster
    - [Pub] rebase_percentage_owner #
       - modifiers: onlyOwner
    - [Pub] rebase #
       - modifiers: onlyOwner
    - [Pub]  #
       - modifiers: Auth
    - [Ext]  ($)
    - [Ext] totalSupply
    - [Ext] decimals
    - [Ext] symbol
    - [Ext] name
    - [Ext] getOwner
    - [Pub] balanceOf
    - [Ext] allowance
    - [Pub] approve #
    - [Ext] approveMax #
    - [Ext] transfer #
    - [Ext] transferFrom #
    - [Int] _transferFrom #
    - [Int] _basicTransfer #
    - [Int] checkTxLimit
    - [Int] shouldTakeFee
    - [Int] takeFee #
    - [Int] shouldSwapBack
    - [Ext] clearStuckBalance #
       - modifiers: authorized
    - [Ext] clearStuckBalance_sender #
       - modifiers: authorized
    - [Ext] set_sell_multiplier #
       - modifiers: onlyOwner
    - [Pub] tradingStatus #
       - modifiers: onlyOwner
    - [Pub] launchStatus #
       - modifiers: onlyOwner
    - [Pub] enable_blacklist #
       - modifiers: onlyOwner
    - [Pub] manage_blacklist #
       - modifiers: onlyOwner
    - [Pub] cooldownEnabled #
       - modifiers: onlyOwner
    - [Int] swapBack #
       - modifiers: swapping
    - [Ext] setIsDividendExempt #
       - modifiers: authorized
    - [Ext] setIsFeeExempt #
       - modifiers: authorized
    - [Ext] setIsTxLimitExempt #
       - modifiers: authorized
    - [Ext] setIsTimelockExempt #
       - modifiers: authorized
    - [Ext] setFees #
       - modifiers: authorized
    - [Ext] setFeeReceivers #
       - modifiers: authorized
    - [Ext] setSwapBackSettings #
       - modifiers: authorized
    - [Ext] setTargetLiquidity #
       - modifiers: authorized
    - [Ext] manualSync #
    - [Ext] setLP #
       - modifiers: onlyOwner
    - [Ext] setMaster #
       - modifiers: onlyOwner
    - [Ext] isNotInSwap
    - [Ext] checkSwapThreshold
    - [Ext] setDistributionCriteria #
       - modifiers: authorized
    - [Ext] setDistributorSettings #
       - modifiers: authorized
    - [Pub] rescueToken #
       - modifiers: onlyOwner
    - [Pub] getCirculatingSupply
    - [Pub] getLiquidityBacking
    - [Pub] isOverLiquified
    - [Ext] checkMaxWalletToken
    - [Ext] checkMaxTxAmount
    - [Ext] setMaxWalletPercent_base1000 #
       - modifiers: onlyOwner
    - [Ext] setMaxTxPercent_base1000 #
       - modifiers: onlyOwner
    - [Ext] multiTransfer #
       - modifiers: onlyOwner
    - [Ext] multiTransfer_fixed #
       - modifiers: onlyOwner