Raw and LayerZero chain IDs' validation
Description
The VaultCrossChainManagerUpgradeable, LedgerCrossChainManagerUpgradeable, and CrossChainRelayUpgradeable contracts are responsible for creating an Orderly cross-chain message and sending it to another chain using the LayerZero protocol. The LedgerCrossChainManagerUpgradeable contract is deployed to the main chain, the VaultCrossChainManagerUpgradeable contract resides on the other chains, and CrossChainRelayUpgradeable is on both the main chain and the other chains. All of these contracts store the value of the current raw chainId
in which they are located.
The CrossChainRelayUpgradeable contract stores two mappings: _lzChainIdMapping
and _chainIdMapping
. The first maps the LayerZero chain ID to the raw chain ID; the second maps the opposite (i.e., the raw chain ID to the LayerZero chain ID). The VaultCrossChainManagerUpgradeable contract stores the raw ledgerChainId
because it should only interact with ledgerChainId
chain.
The issue is that all of these values are not constant and can be changed by the contract owner.
At the same time, the LayerZero protocol also has its own chain IDs. Each LayerZero message stores the values of the source chain ID and the destination chain ID.
The LzAppUpgradeable contract in the lzReceive
function validates that the LayerZero _srcChainId
from which a message was received is trusted. In the _lzSend
function, it also verifies that the LayerZero _dstChainId
to which the message will be sent is trusted as well.
The VaultCrossChainManagerUpgradeable contract verifies that the raw destination chainId
of the message is identical to the current chainId
. However, the LedgerCrossChainManagerUpgradeable contract does not validate whether the destination chainId
of the withdraw message is trusted or not.
Due to this rather complex part of the protocol, in VaultCrossChainManagerUpgradeable there is no guarantee that the message came from the main chain, even if the message
field is set to the value of the main chain ID. This is mainly because these parts are checked separately and raw IDs may change in the meanwhile.
Impact
The existence and verification of local identifiers introduces unnecessary complexity into the system, while not guaranteeing security. Using and validating LayerZero protocol chain IDs is a more reliable way to ensure that messages were sent from a reliable source and were not substituted or changed. Also, these chain IDs are immutable in the LayerZero protocol, so users will be sure that the interaction between the chains occurs in a strictly defined way.
Recommendations
Use chain IDs identical to the Endpoint contract on the current chain and validate the chain ID's values provided by the Endpoint contract to lzReceive
function.
Remediation
The issue is acknowledged by Orderly Network and has not been remediated due to the low impact, because the current protection provided by LayerZero protocol, which guarantees that messages are received only from trusted chains, is sufficient.