MIND Token
Smart Contract Audit Report
Audit Summary
BiggerMINDS is building a new ERC-20 token with automatic liquidity adds and a reward system based on Nodes.
For this audit, we reviewed the project team's Mind and NODERewardManagement contract at 0x9867cc2419Fb317e986A648E02cF7C35aa87a336 on Avalanche.
Audit Findings
Please ensure trust in the team prior to investing as they have substantial control in the ecosystem.
Date: February 11th, 2022.
Updated: February 14th, 2022 to reflect the contract's mainnet deployment and to update token allocation.Finding #1 - NODERewardManagement - High (Resolved)
Description: The _transferNode() function removes the Nodes from the sender's list of Nodes and replaces the slot in the array with the last Node in the list. The Node being transferred is added to the end of the recipient's array of Nodes. However, as the contract uses binary search to locate specific Nodes, the Nodes must be added to the list sorted in order of creation time.
Risk/Impact: The Nodes are not being added to the list with respect to order of creation time, so the binary search will fail every time.
Recommendation: Ensure that the Nodes are sorted in order of creation time.
Resolution: The team has opted to use linear search rather than binary search, which does not rely on the Nodes being in sorted order.Finding #2 - MIND - Informational (Resolved)
Description: Several functions are declared public, but are never called internally.Recommendation: These functions should be declared external for additional gas savings on each call.NODERewardManagement: _getNodeNumberOf(address) Mind: updateUniswapV2Router, setAutomatedMarketMakerPair, cashoutReward, compound, changeSwapLiquify, getNodeNumberOf, getRewardAmountOf, getRewardAmount, changeNodePrice, getNodePrice, changeRewardPerNode, getRewardPerNode, changeClaimTime, getClaimTime, changeAutoDistri, getAutoDistri, changeGasDistri, getGasDistri, getDistriCount, getNodesNames, getNodesCreatime, getNodesRewards, getNodesLastClaims, distributeRewards, publiDistriRewards, getTotalStakedReward, getTotalCreatedNodes
Resolution: The team has implemented the above recommendation.Finding #3 - NODERewardManagement - Informational (Resolved)
Description: ThelastDistributionCount
state variable can never be modified, but is not declared constant.
Recommendation: This state variable can be declared constant for additional gas savings on each call.
Resolution: The team has implemented the above recommendation.
Contracts Overview
Mind Contract:NODERewardManagement Contract:
- The total supply of the token is set to 250 million $MIND.
- No mint or burn functions exist, though the circulating supply can be decreased by sending tokens to the 0x..dead address.
- At the time of writing this report, there are 435 total token holdres. The token allocation is as follows:
- 54.4% of the total supply is stored in the Treasury Pool wallet.
- 24% of the total supply is stored in the Distribution Pool wallet.
- 13.5% of the total supply is stored in a single wallet.
- 8% of the total supply is stored in the Marketing Pool wallet.
- 0.015% of the total supply is in JoeSwap liquidity.
- Of that liquidity, 82.66% is stored in an unverified contract, 8.7% is stored in the Null Address, and 8.4% is stored in a single wallet.
- Blacklisted addresses are not are not permitted to participate in transfers.
- Users who are included in fees must own a Node in the NODERewardManagement contract in order to perform a sell transaction.
- There is a fee charged on transfers in which the sender is selling tokens to Uniswap; this fee does not apply to senders who are excluded from fees.
- The tokens collected through the sell fee are transferred to the Cashout pool wallet controlled by the team.
- Anyone can use this contract to create a new Node in the NODERewardManagement contract.
- Users must pay the node price determined by the project team.
- The tokens collected through node sales are stored in the contract.
- During Node purchases, once a threshold value of tokens in the contract is met, a portion is swapped for AVAX and transferred to the expense pool controlled by the team.
- Another portion is swapped for AVAX and transferred to the Distribution pool controlled by the team.
- Another portion is retained as tokens and transferred to the Distribution pool.
- Another portion is used to fund JoeSwap liquidity; half of the tokens allocated for liquidity are sold for AVAX, paired with the remaining half of the tokens, and added as liquidity to the AVAX pair.
- Another portion is swapped for AVAX and transferred to the marketing pool wallet.
- Any remaining tokens are swapped for AVAX and stored in the contract balance.
- Anyone can use this contract to claim their Node rewards; users can choose to claim all rewards from all Nodes in a single transaction, claim only a specific amount of rewards across one or more Nodes, or claim only the rewards from a specific Node.
- Rewards are calculated within the NODERewardManagement contract and supplied from the Distribution pool wallet.
- Users can also choose to compound their all or a portion of their Node rewards, which creates a new Node for the user at execution time.
- Users can use this contract to rename their Node to any string between 3 and 32 bytes.
- Anyone can transfer their Node to any address at any time.
- Anyone can trigger the reward distribution for all users' Nodes at any time.
- Blacklisted addresses, the Expense pool address, and the Distribution pool address are not allowed to create Nodes or claim Node rewards at any time.
- The owner can set the NODERewardManagement contract address to any address at any time.
- The owner can set the Uniswap Router and Pair addresses at any time.
- The owner can set the threshold value required for swaps to any value at any time.
- The owner can set the Expense pool, Distribution pool, Marketing pool, and Cashout pool addresses to any address at any time.
- The owner can set the sell fee to any value at any time.
- The owner can set the liquidity, expense, marketing, and reward fund allocations to any value at any time.
- The owner can add or remove any user from the blacklist at any time.
- The owner can exclude any address from fees at any time.
- The owner can withdraw any ETH from the contract at any time.
- The owner can disable the automatic liquidity adds at any time.
- The owner can use this contract to changes several properties on the NODERewardManagement contract including the node price, reward-per-node rate, wait time between claims, and toggle auto distribution.
- The owner can also use this contract to automatically distribute rewards on the NODERewardManagement contract.
- The contract complies with the ERC-20 standard.
- As the contract is implemented with Solidity v0.8.0, they are safe from any possible overflows/underflows.
- This contract is used to manage the Node rewards for the $MIND token; no token transfers occur within this contract.
- All functions in this contract can only be accessed by the Mind contract or the "gate keeper"; the gate keeper address is set as the deployer's address on initialization.
- It is intended that the functionality of this contract will only be triggered by the token contract in appropriate circumstances, but as the owner also has access to each of the functions, it is possible that the data can be updated without performing any token transfers.
- The owner or token contract can use this contract to Create a node at any time.
- Upon creating a Node, if auto-distribution is enabled, the function will process the list of Node holders in order to distribute rewards to as many as is permitted.
- Once rewards are distributed, they will need to be claimed.
- The owner or token contract can reset any Node's available rewards at any time.
- The contract contains the appropriate functions so that the token contract may correctly update the Node data as needed.
- The owner can change the node price at any time.
- The owner can change the reward-per-node rate at any time.
- The owner can change the wait time between reward claims at any time.
- The owner can change the amount of gas allocated to reward distributions at any time.
- The token contract or owner can manually trigger the function to distribute rewards at any time.
- As the contract is implemented with Solidity v0.8.0, they are safe from any possible overflows/underflows.
Audit Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Jump/Storage Write | N/A | PASS |
Centralization of Control |
| WARNING |
Compiler Issues | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Ether/Token Theft | N/A | PASS |
Flash Loans | N/A | PASS |
Front Running | N/A | PASS |
Improper Events | N/A | PASS |
Improper Authorization Scheme | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Oracle Issues | N/A | PASS |
Outdated Compiler Version | N/A | PASS |
Race Conditions | N/A | PASS |
Reentrancy | N/A | PASS |
Signature Issues | N/A | PASS |
Unbounded Loops | N/A | PASS |
Unused Code | N/A | PASS |
Overall Contract Safety | PASS |
Inheritence Chart
Function Graph
Functions Overview
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] SafeMathUint
- [Int] toInt256Safe
+ [Lib] SafeMathInt
- [Int] mul
- [Int] div
- [Int] sub
- [Int] add
- [Int] abs
- [Int] toUint256Safe
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] IterableMapping
- [Pub] get
- [Pub] getIndexOfKey
- [Pub] getKeyAtIndex
- [Pub] size
- [Pub] set #
- [Pub] remove #
+ [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] IJoeRouter01
- [Ext] factory
- [Ext] WAVAX
- [Ext] addLiquidity #
- [Ext] addLiquidityAVAX ($)
- [Ext] removeLiquidity #
- [Ext] removeLiquidityAVAX #
- [Ext] removeLiquidityWithPermit #
- [Ext] removeLiquidityAVAXWithPermit #
- [Ext] swapExactTokensForTokens #
- [Ext] swapTokensForExactTokens #
- [Ext] swapExactAVAXForTokens ($)
- [Ext] swapTokensForExactAVAX #
- [Ext] swapExactTokensForAVAX #
- [Ext] swapAVAXForExactTokens ($)
- [Ext] quote
- [Ext] getAmountOut
- [Ext] getAmountIn
- [Ext] getAmountsOut
- [Ext] getAmountsIn
+ [Int] IJoeRouter02 (IJoeRouter01)
- [Ext] removeLiquidityAVAXSupportingFeeOnTransferTokens #
- [Ext] removeLiquidityAVAXWithPermitSupportingFeeOnTransferTokens #
- [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
- [Ext] swapExactAVAXForTokensSupportingFeeOnTransferTokens ($)
- [Ext] swapExactTokensForAVAXSupportingFeeOnTransferTokens #
+ [Int] IUniswapV2Pair
- [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] IJoeFactory
- [Ext] feeTo
- [Ext] feeToSetter
- [Ext] migrator
- [Ext] getPair
- [Ext] allPairs
- [Ext] allPairsLength
- [Ext] createPair #
- [Ext] setFeeTo #
- [Ext] setFeeToSetter #
- [Ext] setMigrator #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC20Metadata (IERC20)
- [Ext] name
- [Ext] symbol
- [Ext] decimals
+ 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 #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ PaymentSplitter (Context)
- [Pub] ($)
- [Ext] ($)
- [Pub] totalShares
- [Pub] totalReleased
- [Pub] totalReleased
- [Pub] shares
- [Pub] released
- [Pub] released
- [Pub] payee
- [Pub] release #
- [Pub] release #
- [Prv] _pendingPayment
- [Prv] _addPayee #
+ NODERewardManagement
- [Pub] #
- [Ext] setToken #
- modifiers: onlySentry
- [Prv] distributeRewards #
- [Ext] createNode #
- modifiers: onlySentry
- [Prv] isNameAvailable
- [Int] _burn #
- [Prv] _getNodeByName
- [Prv] _getNodeWithCreatime
- [Prv] binary_search
- [Ext] _cashoutNodeReward #
- modifiers: onlySentry
- [Ext] _cashoutAllNodesReward #
- modifiers: onlySentry
- [Prv] claimable
- [Ext] _getRewardAmountOf
- [Ext] _getRewardAmountOf
- [Ext] _getNodeRewardAmountOf
- [Ext] _getNodesNames
- [Ext] _getNodesCreationTime
- [Ext] _getNodesRewardAvailable
- [Ext] _getNodesLastClaimTime
- [Int] uint2str
- [Ext] _changeNodePrice #
- modifiers: onlySentry
- [Ext] _changeRewardPerNode #
- modifiers: onlySentry
- [Ext] _changeClaimTime #
- modifiers: onlySentry
- [Ext] _changeAutoDistri #
- modifiers: onlySentry
- [Ext] _changeGasDistri #
- modifiers: onlySentry
- [Pub] _getNodeNumberOf
- [Prv] isNodeOwner
- [Ext] _isNodeOwner
- [Ext] _distributeRewards #
- modifiers: onlySentry
- [Ext] _transferNode #
- modifiers: onlySentry
+ Mind (ERC20, Ownable, PaymentSplitter)
- [Pub] #
- modifiers: ERC20,PaymentSplitter
- [Ext] setNodeManagement #
- modifiers: onlyOwner
- [Pub] updateUniswapV2Router #
- modifiers: onlyOwner
- [Ext] updateSwapTokensAmount #
- modifiers: onlyOwner
- [Ext] updateExpenseWall #
- modifiers: onlyOwner
- [Ext] updateRewardsWall #
- modifiers: onlyOwner
- [Ext] updateMarketingWall #
- modifiers: onlyOwner
- [Ext] updateCashoutWall #
- modifiers: onlyOwner
- [Ext] updateRewardsFee #
- modifiers: onlyOwner
- [Ext] updateLiquiditFee #
- modifiers: onlyOwner
- [Ext] updateFuturFee #
- modifiers: onlyOwner
- [Ext] updateMarketingFee #
- modifiers: onlyOwner
- [Ext] updateSellFee #
- modifiers: onlyOwner
- [Ext] updateRwSwapFee #
- modifiers: onlyOwner
- [Pub] setAutomatedMarketMakerPair #
- modifiers: onlyOwner
- [Ext] blacklistMalicious #
- modifiers: onlyOwner
- [Ext] setExcludedFromFee #
- modifiers: onlyOwner
- [Prv] _setAutomatedMarketMakerPair #
- [Pub] transfer #
- [Pub] transferFrom #
- [Int] _transfer #
- [Prv] swapAndSendToFee #
- [Prv] swapAndLiquify #
- [Prv] swapTokensForEth #
- [Prv] addLiquidity #
- [Pub] createNodeWithTokens #
- [Pub] cashoutReward #
- [Pub] cashoutAll #
- [Pub] compound #
- [Pub] boostReward #
- modifiers: onlyOwner
- [Pub] changeSwapLiquify #
- modifiers: onlyOwner
- [Pub] getNodeNumberOf
- [Pub] getRewardAmountOf
- modifiers: onlyOwner
- [Pub] getRewardAmount
- [Pub] changeNodePrice #
- modifiers: onlyOwner
- [Pub] getNodePrice
- [Pub] changeRewardPerNode #
- modifiers: onlyOwner
- [Pub] getRewardPerNode
- [Pub] changeClaimTime #
- modifiers: onlyOwner
- [Pub] getClaimTime
- [Pub] changeAutoDistri #
- modifiers: onlyOwner
- [Pub] getAutoDistri
- [Pub] changeGasDistri #
- modifiers: onlyOwner
- [Pub] getGasDistri
- [Pub] getDistriCount
- [Pub] getNodesNames
- [Pub] getNodesCreatime
- [Pub] getNodesRewards
- [Pub] getNodesLastClaims
- [Ext] transferNode #
- [Pub] distributeRewards #
- modifiers: onlyOwner
- [Pub] publiDistriRewards #
- [Pub] getTotalStakedReward
- [Pub] getTotalCreatedNodes