NetMind

QuantstampRepository at commit d52de61

Quantstamp reviewed NetMind on 4 Aug 2024: 25 findings, 0 critical; 10 marked fixed, 14 acknowledged, 1 open.

No open critical findings
Open the reportOpen NetMind’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings25

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High023
Medium053
Low174
High`AccountManage` Can Be Initialized With No Required SignersFixed

Currently, `AccountManage.init()` does not assign a `signNum` for the contract, meaning that after initialization, the `signNum` has a zero value. This means that `withdrawComputingFee()` can be invoked without any signatures necessary, allowing any address to withdraw the accumulated `providerFeeSum` amount of NMT tokens from this contract. During the audit, we notified the team of their live contract with a `signNum` of zero with ~18 NMT at stake for withdrawal by any party. As of 12 pm ET on July 12th, the `signNum` has not been updated and remains at a zero value.

HighIncorrect Token RefundedFixed

The function `FinanceToken.purchaseNMTWithToken()` intends to return any excess `_paymentToken` to the caller, but `nmtToken` is always returned instead. There is no need to refund any payment as only the `useAmount` is transferred from the caller, not the full `_paymentAmount`.

HighSignature ReplayFixed

The functions `distribute()` and `agentDistribute()` are susceptible to signature replay since a nonce is not included in the digest. After either function is called, anyone can reuse the calldata, which consists of the authorized account signatures, to replay the distribute transaction. The transaction can be replayed continuously until the payment has no remaining funds or the `expir` time is reached.

MediumMalicious Manager Can Pass Any Proposal and Drain FundsFixed

The `vote(uint256 id)` function checks if a manager has already voted on a proposal using the `voteRecord` mapping. However, the voting record is not updated once a manager has voted. This allows a malicious manager to repeatedly vote on the same proposal, potentially reaching the threshold required to pass the proposal. Additionally, a malicious manager can propose any malicious proposal and ensure it passes, allowing them to drain funds from the contract.

MediumPotential Loss Due to Unrefunded Excess when Purchasing NMTFixed

Both the `purchaseNMTWithETH()` and `purchaseNMTWithToken()` functions may lead to unintended retention of excess ETH or tokens due to integer division during the calculation of `_purchaseNMTQuantity`. When `msg.value * finance.paymentPrice / 10**18` (for ETH) or `_paymentAmount * finance.paymentPrice / 10**decimals` (for tokens) results in a value that does not use the full `msg.value` or `_paymentAmount`, the remainder is not refunded to the user. Therefore, users can lose the excess ETH or tokens without receiving corresponding NMT tokens.

MediumPrecision LossFixed

In the function `swapToken()`, USDC is swapped to NMT tokens through a DEX router. In the following calculation, precision loss occurs to the amount of NMT tokens received as division is executed before multiplication: ``` 181 | amounts[1] = amounts[1] / 100000000000 * 100000000000; ``` Since the `Purchase` contract does not contain any functionality to withdraw NMT tokens, the tokens lost to precision loss will be trapped in the contract.

LowGeneral Proposal Execution Allows Unauthorized Node Additions and RemovalsFixed

The `_actuator()` function handles various proposal types, including adding nodes (`_typeIndex == 2`) and removing nodes (`_typeIndex == 3`). However, for general proposals (`_typeIndex == 6`), there is no guard preventing the execution of `addNodeAddr` or `removeNodeAddr` functions within the data payload of `excContractPropose`. This could allow unauthorized additions or removals of nodes through general proposals.

LowIncorrect Proposers in `_obtainProposalMsg()` Due to Dynamic Node CountFixed

The `_obtainProposalMsg()` function constructs a `QueryProposalMsgData` object by iterating over proposal IDs and their corresponding proposers. However, the function assumes a fixed number of nodes (`_nodeNum`) to allocate space for all proposers. This assumption can lead to incorrect data retrieval and potential overflow if the number of nodes has changed over time. If the number of nodes has changed since the proposals were created, the function may map proposers incorrectly. If `_nodeNum` is larger than the number of proposers for a given proposal, the function will write past the allocated space and lead to incorrect proposers returned by `_obtainProposalMsg()`.

LowTrapped NMT Tokens in Fund ContractsFixed

<br> 1. The `CommunityFund` contract can only release up to `1650e22` NMT tokens over its lifetime due to the logic in `calcRelease()`. Therefore, once the sum of all `CommunityFund` contract releases (tracked by the state variable `withdraw`) reaches `1650e22`, any remaining NMT would be trapped in the contract. Specifically, transaction execution will revert in the `vote()` function at the following check: ``` 267 | uint256 _allAmount = calcRelease(_time); 268 | require(_proposalMsg.amount <= _allAmount - withdraw, "withdraw error"); ``` 1. The `StrategicFund` contract can only release up to `750e22` NMT tokens over its lifetime due to the logic in `calcRelease()`. Therefore, once the sum of all `StrategicFund` contract releases (tracked by the state variable `withdrawSum`) reaches `750e22`, any remaining NMT would be trapped in the contract. Specifically, transaction execution will revert in the `vote()` function at the following check: ``` 263 | uint256 _allAmount = calcRelease(_time); 264 | require(_proposalMsg.amount <= _allAmount - withdrawSum, "withdraw error"); ``` 1. The `TechnologyFund` contract can only release up to `1000e22` NMT tokens over its lifetime due to the logic in `calcRelease()`. Therefore, once the sum of all `TechnologyFund` contract releases (tracked by the state variable `withdrawSum`) reaches `1000e22`, any remaining NMT would be trapped in the contract. Specifically, transaction execution will revert in the `vote()` function at the following check: ``` 265 | uint256 _allAmount = calcRelease(_time); 266 | require(_proposalMsg.amount <= _allAmount - withdrawSum, "withdraw error"); ```

LowUninitialized State VariablesFixed

In the `FixedLock` contract, the code in the `init()` function is commented out, and the function does not initialize any of the contract's state variables. Therefore, if the `FixedLock` contract is set as the implementation contract for a new proxy, the following state variables will remain unset without any way to update them: 1. `startTime` 2. `endTime` 3. `releaseStart` 4. `releaseEnd` 5. `releaseDuration` 6. `rewardPropotion` 7. `rewardDelay`

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (45)

  • https://github.com/NetMind-AI/netmind-contract/contracts/FixedLock.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/TechnologyFund.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Governor_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Purchase_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/PriceService_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/LiqudityFundsManage.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Governor.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/FixedLock_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/RewardPool.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Pledge.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Snapshoot_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/CrossChain.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Pledge_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Payment_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/NetMindToken_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/CommunityFund.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Ledger.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Snapshoot.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Airdrop.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/FiatoSettle_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Ledger_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Reward_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/TrainingTask_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/FinanceToken_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/LongTermPledge_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Purchase.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/AccountManage_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/AccountManage.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/LongTermPledge.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/StrategicFund_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/TechnologyFund_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/RewardContract.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/LiquidityFundsManage_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/FinanceToken.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/TrainingTask.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Payment.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/StrategicFund.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/FiatoSettle.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/CrossChain_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Conf.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/NetMindToken.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/CommunityFund_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/proxy/Conf_proxy.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4
  • https://github.com/NetMind-AI/netmind-contract/contracts/Management.sol at commit d52de6181f400d0b68a496fd5df875a5f47d9ec4

Part of NetMind’s security record

NetMind
Audits1 audit by 1 firmLast audit Aug 2024, by Quantstamp.
Critical findingsNo open critical findingsIn 1 report.
Open NetMind’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us