Quantstamp reviewed Nomad on 11 May 2022: 40 findings, 0 critical; 10 marked fixed, 24 acknowledged, 6 open.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 1 |
| Medium | 2 | 0 | 4 |
| Low | 4 | 24 | 5 |
The `prove`, `process`, and `proveAndProcess` methods can be called even if the `Replica` contract is on `Failed` state. Therefore, if governance does not deal with the replica immediately (replace replica in the corresponding `XAppConnectionManager` or remove fraudulent roots via the `setConfirmation` method), fraudulent roots might have enough time to be confirmed, thereby letting fraudulent messages to be proven and processed.
Whenever fraud is detected in the `Home` or `Replica` contracts, they will be moved to a `Failed` state (via the `doubleUpdate` or `improperUpdate` methods). However, once a contract moves to that state, it's not possible to return it to `Active`. The only way out is to upgrade the contracts' code or deploy new instances.
According to the [Nomad documentation](https://docs.nomad.xyz/#replica), the replica has to ensure that messages are delivered in order. However, that's not the case. As long as a message has been marked as `PROVEN`, the processor is free to call the `process` method in the replica in any order it wants. This is a problem because a malicious processor or malicious third-party (the `process` method is not protected, so anyone could call it) could force the replica to process their messages in a way that is beneficial to them (front-run).
The `optimisticSeconds` parameter is not validated, so it could be set to 0 or a minimal amount. This would allow updates to be accepted in a very short time, thereby not leaving the replica with enough time to respond to fraud (this is also a problem in the `initialize` method).
During an upgrade of the contract, `PRE_FILL_FEE_NUMERATOR` could be set to a value greater than 10000. This behaviour would result in impacting the logic of the contract.
The contract makes use of the floating-point pragma ^0.6.11. Contracts should be deployed using the same compiler version. Locking the pragma helps ensure that contracts are not unintentionally deployed using another pragma, such as an obsolete version, that may introduce issues in the contract system.
The `preFill` method allows a liquidity provider (LP) to fill a transfer that hasn't been verified yet for a fee. This method ensures that only one liquidity provider can provide liquidity to a single transfer (`L230`). However, it does not verify if the transfer has already been processed by the `handle` method (`L107`). A malicious processor (or even a malicious miner) could wait to send the message that will trigger the `handle` method just before a `preFill` method call is done, thereby letting the recipient receive funds from both, the router and the liquidity provider. To make things worse, once the `send` method has been processed, another LP would be able to call `preFill` again for the same transaction.
The codebase is not using `SafeMath` in the arithmetic operations. Some places can potentially be overflow or underflow in edge cases.
In the `_applyPreFillFee` function, the `_amtAfterFee` is calculated using the following formula ``` (_amnt * PRE_FILL_FEE_NUMERATOR) / PRE_FILL_FEE_DENOMINATOR; ``` The issue here is that is if `_amt * PRE_FILL_NUMERATOR` is less than `PRE_FILL_FEE_DENOMATOR` the `_amtAfterFee` will be equal to 0.
The `process` method forwards messages to their destination and mark the messages as processed regardless of the outcome of the method. If dApps do not account for this, they might end up in invalid states. For example, the `BridgeRouter` is assuming that trades sent across the chain always work and has no functionality to recover if the `handle` method fails for any reason.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (66)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething 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