Orderly engaged Guardian to review the security of its OFT and OFT adapter. From June 3rd to June 17th, a team of 6 auditors reviewed the source code in scope.
- Published
- Language
- Solidity
- Chains
- Ethereum, Arbitrum, Optimism, Base, Solana
- Sector
- Cross-chain
- 0 Critical
- 2 High
- 2 Medium
- 2 Low
- 0 Informational
Scope
-
gitlab.com/orderlynetwork/orderly-v2/oft-token
e8b7aad0b108dccdd381
Overview
Orderly engaged Guardian to review the security of its OFT and OFT adapter. From June 3rd to June 17th, a team of 6 auditors reviewed the source code in scope.
Findings 6
-
H-01 High Layerzero Pathway will be Continuously Blocked DoS Resolved
Description
Currently, the OFT contract allows anyone to set the address(0) as a token recipient on the destination chain. However, this is a transaction that will always revert because the OpenZeppelin's implementation does not allow minting to the 0 address. An attacker can leverage this to block the LayerZero pathway.
An example:
- The nonce on both chains is 5.
- An attacker successfully sends their minting tx and the nonce becomes 6.
- The transaction is received on the destination chain, but fails.
- Since the app uses ordered delivery, all subsequent transactions will be blocked until 6 is resolved.
As a result, an attacker can keep blocking the LayerZero pathway.
Recommendation
Don't allow sending cross-chain packages that mint to the address(0).
Resolution
Orderly Team: The issue was resolved in commit c2e1991.
-
H-02 High _acceptNonce Should Not Be Called Logical Error Resolved
Description
OrderOFT and OrderAdapter allow the owner to burn, nilify, skip and clear nonces. When doing so, a call to _acceptNonce is initiated.
This is problematic for:
- burning: The nonce to be burnt will always be less than the
maxReceivedNonce. However, in
ordered delivery the
_acceptNoncefunction reverts if the specified nonce is not max + 1. This will result in burning not working when ordered delivery is turned on.- nilifying: The
_acceptNoncewill let us nilify only the packet with nonce = max + 1. After nilifying the
maxReceivedNoncewill be set to the nilified nonce. Now even if the nilified package gets reverified, it will not be possible to execute it.- clearing: If there is a need to clear a nonce which is bigger than maxNonce + 1 , it will be impossible
because of the ordered nonce.
In addition, these actions can be initiated by a delegate address and not by the OFTApp directly. This will cause a discrepancy between the OrderOFT and LayerZero
maxReceivedNonceand the messaging will be blocked becauseacceptNoncewill always revert from this moment on.Recommendation
Do not call
_acceptNoncewhen burning, nilifying, nor clearing. Furthermore, add a settersetMaxReceivedNonceto update the mapping as necessary and even consider passing amaxReceivedNonceargument in each of the functions which can be used to update the mapping during the execution of the owner functions.This is because since there can be multiple in-flight packets and one of them is burned/nulled/cleared, and now the order enforcement will lead to DoS. Furthermore, a delegate can burn/nullify/clear outside the Oapp so the setter is absolutely necessary.
Resolution
Orderly Team: The issue was resolved in commit e32d7c0.
- burning: The nonce to be burnt will always be less than the
-
M-01 Medium No Storage Gaps In Upgradable Contracts Upgradability Resolved
Description
The system uses upgradable contracts. The following parent contracts don’t use storage gaps, which will result in a corrupted storage if a variable is added/removed:
OFT:
- OFTAdapterUpgradable
- OFTCoreUpgradable
- OFTUpgradable
- OAppCoreUpgradable
- OAppReceiverUpgradable
- OAppSenderUpgradable
- OAppUpgradable
Recommendation
Add storage gaps to the upgradable contracts.
Resolution
Orderly Team: The issue was resolved in commit 8dae135.
Guardian Team: Storage gaps and used storage slots should add up to 50 which is not the case for most of the current contracts.
-
M-02 Medium Ordered Nonce Flag Should Only Be Set Once Logical Error Resolved
Description
The
OrderOFTandOrderAdaptercontracts are intilialized withorderedNonceflag enabled, although owner can turn this flag on and off as pleased usingsetOrderedNonce. WhenorderedNonceis set to false, messages can be executed in any order, increasing themaxReceivedNonce.If the
orderedNonceis turned on back again, there will be issues with messages that were not executed with lower nonces, as the only acceptable nonce will bemaxReceivedNonce + 1Recommendation
Remove the owner function to set the
orderedNonceflag. Alternatively, only allow to turn it off and never be able to turn it back on again.Resolution
Orderly Team: The issue was resolved in commit e32d7c0.
-
L-01 Low Implementation Contracts Can Be Initialized By Anyone Upgradability Resolved
Description
OrderOFT, OrderAdapter are implementation contracts designed to be called through a proxy contract. However, the initialize function can be directly called by anyone.
This would allow a malicious actor to set storage variables such as
lzEndpointandowneron the implementation contract. While no direct risks were found, it is general good practice to preventinitializefrom being called.Recommendation
Use
disableInitializerin a constructor. See OpenZeppelin’s guide for more details.Resolution
Orderly Team: The issue was resolved in commit cdb53b6.
-
L-02 Low Owner Can Revoke Ownership Logical Error Acknowledged
Description
All
Ownablecontracts allow the owner to renounce their ownership. This can leave the contracts in an unexpected state and hinder the functioning of the protocol.Recommendation
Consider utilizing
Ownable2Step.Resolution
Orderly Team: This operation will be carefully checked.
No findings match.
Invariants 15
The review's fuzzing suite asserted 15 invariants. 15 held.
Every invariant tested
| ID | Invariant | Result |
|---|---|---|
OT-01 | Total Supply of ORDER should always be 1,000,000,000 | Held |
OT-02 | Allowance Matches Approved Amount | Held |
OT-03 | ERC20 Balance Changes By Amount For Sender And Receiver Upon Transfer | Held |
OT-04 | ERC20 Balance Remains The Same Upon Self-Transfer | Held |
OT-05 | ERC20 Total Supply Remains The Same Upon Transfer | Held |
OT-06 | Source Token Balance Should Decrease On Send | Held |
OT-07 | Adapter Token Balance Should Increase On Send | Held |
OT-08 | Adapter Token Total Supply Should Not Change On Send | Held |
OT-09 | Source OFT Total Supply Should Decrease On Send | Held |
OT-10 | Outbound Nonce Should Increase By 1 On Send | Held |
OT-11 | Max Received Nonce Should Increase By 1 on lzReceive | Held |
OT-12 | Destination Token Balance Should Increase on lzReceive | Held |
OT-13 | Adapter Token Balance Should Decrease on lzReceive | Held |
OT-14 | Adapter Token Total Supply Should Not Change on lzReceive | Held |
OT-15 | Destination OFT Total Supply Should Increase on lzReceive | Held |
More from Orderly
All 8 reports-
Solana Vault, Sol-CC and EVM Updates
53 findings1 critical · 6 high 53 findings: 1 critical, 6 high, 5 medium, 22 low, 19 informational -
Solana Vault
41 findings1 high 41 findings: 1 high, 3 medium, 18 low, 19 informational -
Strategy Vault Updates
30 findings1 high 30 findings: 1 high, 5 medium, 16 low, 8 informational -
Solana Staking
35 findings1 critical · 1 high 35 findings: 1 critical, 1 high, 4 medium, 29 low
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
