On this page
Transfer lifecycle
An Omniassets transfer has separate source and destination states. A confirmed source transaction means the token was locked or burned and the LayerZero message was submitted. It does not yet prove destination delivery.
1. Source settlement
The source transaction is atomic:
- an original ERC-20 is transferred into the Vault and its actual received amount is recorded; or
- an Omniasset is burned from the sender;
- the protocol fee is collected;
- the LayerZero message is submitted;
BridgeMessageSentemits its GUID.
If this transaction reverts, no transfer started.
2. Message verification
LayerZero verifies the configured pathway and delivers the message to the destination Router. The Router accepts calls only from the local LayerZero endpoint and only for an active configured peer.
The GUID is the primary correlation key across chains.
3. Destination settlement
The destination Router executes the payload once:
- on the original chain, the Vault unlocks the original ERC-20;
- on another chain, the Registry deploys the Omniasset if needed and the core mints it.
A successful execution marks the GUID consumed and emits BridgeMessageReceived.
Failed destination execution
If a trusted transfer message reaches the Router but settlement reverts, the Router stores the message under its GUID and emits MessageFailed. The LayerZero channel is not blocked by that application failure.
Read the cached state through the core contract:
function failedMessages(bytes32 guid)
external
view
returns (
bool exists,
uint32 srcEid,
bytes32 sender,
uint64 nonce,
bytes message,
bytes32 messageHash,
bytes32 reasonHash,
uint256 failedAt
);Do not submit the original transfer again. Choose one recovery path for the existing GUID.
Retry
Anyone can retry a cached destination message:
function retryFailedMessage(bytes32 guid) external;A successful retry performs the original destination settlement, deletes the cached failure, marks the GUID consumed, and emits FailedMessageRetried.
Retry when the failure was temporary or its cause has been fixed.
Restore
Anyone can pay to return the asset to the original source sender:
function quoteRestore(bytes32 guid, bytes options) external view returns (uint256);
function restoreFailedMessage(bytes32 guid, bytes options)
external
payable
returns (MessagingReceipt memory);Quote restore options with sufficient receive gas, then pay the exact LayerZero fee. Restore consumes the failed GUID and sends a new message back to the source chain. The restored recipient is fixed to the original sender; the caller cannot redirect it.
Terminal states
For client state, use:
| State | Evidence |
|---|---|
| Sent | Source receipt with BridgeMessageSent |
| Delivered | Destination BridgeMessageReceived |
| Failed | Destination Router MessageFailed and failedMessages(guid).exists |
| Retried | FailedMessageRetried, followed by destination settlement |
| Restoring | FailedMessageRestored with a new restore GUID |
| Restored | Restore GUID delivered on the original source chain |
See Events for exact signatures and Errors for source reverts.