Unordered Delivery
By default, the LayerZero protocol uses unordered delivery, where transactions can be executed out of order if all transactions prior have been verified. If transactions1 and 2 have not been verified, then transaction 3 cannot be executed until the previous nonces have been verified.
Once nonces 1, 2, 3 have been verified:
- If nonce
2failed to execute (due to some gas or user logic related issue), nonce3can still proceed and execute.
Ordered Delivery
Developers can configure the OApp contract to use ordered delivery.1, 2, 3, and so on, each packet must be executed in that exact, sequential order:
- If nonce
2fails for any reason, it will block all subsequent transactions with higher nonces from being executed until nonce2is resolved.
In these cases, strict nonce enforcement can be used to provide consistency, fairness, and censorship-resistance to maintain system integrity.
Enabling Ordered Delivery
To implement strict nonce enforcement, you need to implement the following:- a mapping to track the maximum received nonce.
- override
_acceptNonceandnextNonce. - add
ExecutorOrderedExecutionOptionin_optionswhen calling_lzSend. - a governance function to keep the nonce mapping between the protocol and application in sync when skipping nonces.
ExecutorOrderedExecutionOption in your _lzSend call:
Keeping Nonces In Sync
When skipping nonces at the protocol level, such as callingendpoint.skip, your OApp’s local mapping must be incremented as well. If the local receivedNonce mapping falls behind the protocol’s stored nonce, subsequent messages will revert with an invalid nonce error.
A governance helper could look like:
nextNonce returns the correct value and prevents ordered messages from being blocked.
Implement strict nonce enforcement via function override: