Quantic - Smart Contract Audit Report
Audit Summary
Quantic ($Quantic) is a new BEP-20 token that features automatic liquidity adds and pays holders dividends in BSC-USD.
For this audit, we reviewed the Quantic and DividendDistributor contracts using code provided to us by the project team.
Audit Findings
Please ensure trust in the team prior to investing as they have substantial control in the ecosystem.
Date: February 10th, 2022.
Updated: February 14th, 2022 to reflect updates to the contract that resolve Findings #1 and #2.Finding #1 - Quantic - Medium (Resolved)
Description: The owner can use either the multiTransfer() or multiTransfer_fixed() function to initiate token airdrops that are funded by any address that the owner specifies.Risk/Impact: The owner can use these two functions to transfer any user's tokens to another address without approval.function multiTransfer(address from, address[] calldata addresses, uint256[] calldata tokens) external onlyOwner { ... for(uint i=0; i < addresses.length; i++){ _basicTransfer(from,addresses[i],tokens[i]); } } function multiTransfer_fixed(address from, address[] calldata addresses, uint256 tokens) external onlyOwner { ... for(uint i=0; i < addresses.length; i++){ _basicTransfer(from,addresses[i],tokens); } }
Recommendation: We recommend removing the from parameter and using msg.sender to fund the airdrop instead.
Resolution: The team has implemented the above recommendation.Finding #2 - Quantic - Informational (Resolved)
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.rebase_percentage, tradingStatus, launchStatus, enable_blacklist, manage_blacklist, cooldownEnabled, isOverLiquified
Resolution: The team has declared these variables external.
Contracts Overview
Ownership Controls:
- The total supply of the token is set to 4 billion $Quantic [4,000,000,000].
- No mint or burn functions are present; though the circulating supply can be reduced by sending tokens to the 0x..dead address if desired.
- There was no token allocation for our team to analyze as the contract has yet to be deployed to the mainnet.
- The team can activate a rebase mechanism that will automatically adjust the token's circulating supply according to a rebase percentage determined by the team.
- This mechanism will rebase the circulating supply to increase or decrease the price of an individual token while increasing or decreasing each holder's balance at the provided rate. When rebasing occurs, the total market cap for the token will not be directly affected as a result of this mechanism.
- The rebase function properly calls sync() on the PancakeSwap Pair contract to prevent theft-of-liquidity attacks that have occurred with other rebase tokens.
- The team must manually enable trading in order for trading to take place on the platform. Only accounts that have been authorized by the owner can trade when trading is set to disabled.
- There is a tax fee on all transfers where neither the sender nor the recipient is excluded from fees.
- If the transaction is a sell trade, the tax fee is multiplied by a sell tax multiplier value determined by the team.
- The fees charged on transfers are 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 Pancakeswap 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 BNB with the token, and adding it as liquidity to the BNB pair.
- The LP tokens received through this process are sent to the Liquidity address set by the team. We recommend that the team lock these newly acquired LP tokens.
- The tokens collected from the Treasury Fee are swapped for BNB and sent to the team's Treasury wallet.
- The tokens collected from the Sustainability Fee are swapped for BNB and sent to the team's Sustainability wallet.
- The tokens collected from the Reflection Fee are swapped for BNB and sent to the Distributor contract where they are swapped for BSC-USD and distributed as rewards.
- The contract features a cooldown mechanism that prevents a user from buying tokens from Pancakeswap if the cooldown time (set by the team) since their last buy has not yet elapsed.
- The contract features an antisniper mechanism that is triggered when a user attempts to buy tokens before the set number of blocks (set by the team) has passed since the launch time of the contract. The account initiating the transfer will be taxed at a 99% rate.
- The contract utilizes the SafeMath library to protect against overflows/underflows along with following the BEP-20 standard.
- Any user that holds any amount of $Quantic tokens is eligible to claim dividends once the amount of dividends they are due reaches a minimum threshold value determined by the team.
- 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 assign one address to a Master role and multiple addresses to an Authorized role at any time.
- The Master address can initiate the rebase mechanism at any time, as long as the contract is not currently swapping.
- The owner can enable/disable trading at any time.
- The owner can update the sell multiplier when selling to Pancakeswap up to 20% at any time.
- The owner can manually set the launch time of the contract to any value at any time. We 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 transfer 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 transfers.
- The owner can update the cooldown period to any value at any time.
- The owner can set and update a maximum wallet amount that will prevent transfers from occurring if the recipient's token balance will exceed the value set by the team.
- The owner can set and update a maximum transaction amount at any time, which will impose a limit to the number of tokens that can be transferred during any given transaction.
- The owner can initiate $Quantic token airdrops to any users at any time.
- The owner can withdraw any BEP-20 tokens from the contract address at any time.
- Authorized addresses can set each fee percentage to any value as long as the total fee percentage combined does not exceed 20%.
- Authorized addresses can update the team's Liquidity wallet, Treasury wallet, and Sustainability wallet to any addresses at any time.
- Authorized addresses can exclude addresses from fees, the cooldown mechanism, and the maximum transaction amount at any time.
- Authorized addresses can exclude any address from dividends at any time.
- Authorized addresses can update the threshold number of tokens that triggers the token swapping functionality to any value at any time.
- Authorized addresses can disable the automatic swapping functionality at any time.
- Authorized addresses can update the maximum amount of gas used for processing to a value up to 900,000 at any time.
- Authorized addresses can update the amount of time that 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.
- Authorized addresses can transfer any BNB from the contract address balance to their own address or the Treasury wallet 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] 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 #
+ Quantic (IBEP20, Auth)
- [Pub] rebase_percentage #
- modifiers: onlyMaster
- [Pub] rebase #
- modifiers: onlyMaster
- [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] 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