Skip to content
$1,000,000 in security audit grants are live now, Apply here →

Security review · July 2024

OFT and OFT Adapter

for Orderly

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

5 resolved · 1 acknowledged

Scope

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

  1. H-01 High Layerzero Pathway will be Continuously Blocked DoS Resolved
    Location
    OFT.sol

    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.

  2. H-02 High _acceptNonce Should Not Be Called Logical Error Resolved
    Location
    Global

    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 _acceptNonce function reverts if the specified nonce is not max + 1. This will result in burning not working when ordered delivery is turned on.

    • nilifying: The _acceptNonce will let us nilify only the packet with nonce = max + 1. After nilifying the

    maxReceivedNonce will 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 maxReceivedNonce and the messaging will be blocked because acceptNonce will always revert from this moment on.

    Recommendation

    Do not call _acceptNonce when burning, nilifying, nor clearing. Furthermore, add a setter setMaxReceivedNonce to update the mapping as necessary and even consider passing a maxReceivedNonce argument 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.

  3. M-01 Medium No Storage Gaps In Upgradable Contracts Upgradability Resolved
    Location
    Global

    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.

  4. M-02 Medium Ordered Nonce Flag Should Only Be Set Once Logical Error Resolved
    Location
    Global

    Description

    The OrderOFT and OrderAdapter contracts are intilialized with orderedNonce flag enabled, although owner can turn this flag on and off as pleased using setOrderedNonce. When orderedNonce is set to false, messages can be executed in any order, increasing the maxReceivedNonce.

    If the orderedNonce is turned on back again, there will be issues with messages that were not executed with lower nonces, as the only acceptable nonce will be maxReceivedNonce + 1

    Recommendation

    Remove the owner function to set the orderedNonce flag. 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.

  5. L-01 Low Implementation Contracts Can Be Initialized By Anyone Upgradability Resolved
    Location
    Global

    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 lzEndpoint and owner on the implementation contract. While no direct risks were found, it is general good practice to prevent initialize from being called.

    Recommendation

    Use disableInitializer in a constructor. See OpenZeppelin’s guide for more details.

    Resolution

    Orderly Team: The issue was resolved in commit cdb53b6.

  6. L-02 Low Owner Can Revoke Ownership Logical Error Acknowledged
    Location
    Global

    Description

    All Ownable contracts 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.

Invariants 15

The review's fuzzing suite asserted 15 invariants. 15 held.

Every invariant tested
IDInvariantResult
OT-01Total Supply of ORDER should always be 1,000,000,000Held
OT-02Allowance Matches Approved AmountHeld
OT-03ERC20 Balance Changes By Amount For Sender And Receiver Upon TransferHeld
OT-04ERC20 Balance Remains The Same Upon Self-TransferHeld
OT-05ERC20 Total Supply Remains The Same Upon TransferHeld
OT-06Source Token Balance Should Decrease On SendHeld
OT-07Adapter Token Balance Should Increase On SendHeld
OT-08Adapter Token Total Supply Should Not Change On SendHeld
OT-09Source OFT Total Supply Should Decrease On SendHeld
OT-10Outbound Nonce Should Increase By 1 On SendHeld
OT-11Max Received Nonce Should Increase By 1 on lzReceiveHeld
OT-12Destination Token Balance Should Increase on lzReceiveHeld
OT-13Adapter Token Balance Should Decrease on lzReceiveHeld
OT-14Adapter Token Total Supply Should Not Change on lzReceiveHeld
OT-15Destination OFT Total Supply Should Increase on lzReceiveHeld

More from Orderly

All 8 reports
  1. Solana Vault, Sol-CC and EVM Updates

    53 findings1 critical · 6 high 53 findings: 1 critical, 6 high, 5 medium, 22 low, 19 informational
  2. Solana Vault

    41 findings1 high 41 findings: 1 high, 3 medium, 18 low, 19 informational
  3. Strategy Vault Updates

    30 findings1 high 30 findings: 1 high, 5 medium, 16 low, 8 informational
  4. 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.

Get a quote