Nomad Docs
  • Nomad 101
    • Funds Recovery
    • Introduction
    • Our Mission
    • Getting Started
  • The Nomad Protocol
    • Overview
    • Cross-chain Messaging
      • Lifecycle of a Message
    • Verification Mechanisms
      • Background on Verification
      • Native Verification
      • External Verification
      • Optimistic Verification
      • Comparing Mechanisms
    • Security
      • Root of Trust
        • Fraud
          • Optimistic Timeout Period
          • Fraud Recovery
        • App-Governed Root of Trust
        • Liveness Assumptions
      • Attack Vectors
        • Key Compromise
        • Economic Attacks
        • Smart Contract Bugs
      • Long-Term Security
        • Permissionless Watchers
        • Financial Controls
        • Cross-Domain MEV
    • Smart Contracts
      • Home
      • Replica
      • XAppConnectionManager
    • Off-chain Agents
      • Updater
      • Watchers
      • Relayer
      • Processor
  • Token Bridge
    • Overview
    • How to Bridge
      • Using Etherscan
      • Nomad Bridge App
      • Testnet Bridge App
    • Asset Issuers
      • Custom Representations
    • Deployed Tokens
      • Mainnet
      • Testnet
    • Smart Contracts
      • BridgeRouter
      • TokenRegistry
      • BridgeToken
      • BridgeMessage
    • Architecture
    • FAQ
  • Governance Bridge
    • Overview
    • Zodiac: Nomad Module
    • Smart Contracts
      • NomadModule
    • Architecture
  • Developers
    • Quickstart
      • Send Messages
      • Receive Messages
    • Environments
      • Domain (Chain) IDs
    • Application Developers
      • Building xApps
      • SDK
        • Contracts SDK
        • Typescript SDK
      • Examples
        • Ping Pong
        • Example Bridge GUI
        • xApp Example
      • Advanced
        • Router Pattern
    • Node Operators
      • Running Agents Guide
        • Troubleshooting
      • Running a Watcher
      • Agent Operations
      • Agent Gas Values
      • The Keymaster
    • Core Developers
      • Upgrade Setup
      • Deploying Contracts
        • Development
        • Production
  • Operational Security
    • Audits
    • Bug Bounty
    • Governance
    • Contracts
    • Agent Operations
  • Resources
    • Awesome Interoperability
    • Brand Kit
    • FAQ
    • Glossary
    • GitHub
    • Discord
    • Twitter
    • Website
Powered by GitBook
On this page
  • 1. User Initiates Action on Origin Chain
  • 2. xApp Dispatch Logic Executes on Origin Chain
  • 3. Core Contract Logic Executes on Origin Chain
  • 4. Updater Signs an Update on the Origin Chain
  • 5. Update is Relayed to the Replica on the Destination Chain
  • 6. Message is Proven and Processed on the Destination Chain
  • 7. xApp Handle Logic Executes on Destination Chain
  1. The Nomad Protocol
  2. Cross-chain Messaging

Lifecycle of a Message

PreviousCross-chain MessagingNextVerification Mechanisms

Last updated 2 years ago

In this document, we'll walk through an end-to-end example of sending a cross-chain message using Nomad.

Cross-chain message lifecycle

Let's use an example of a user, Alice, who wants to send 1000 USDC from her account on Ethereum to the same one on Moonbeam, using the Nomad Token Bridge application.

While this example will focus on the ERC-20 token bridging use case, the core logic on how messages get sent in the Nomad protocol is identical for all use cases.

1. User Initiates Action on Origin Chain

2. xApp Dispatch Logic Executes on Origin Chain

The BridgeRouter contract, triggered by Alice's transaction, will begin executing its business logic (as encoded by the app developer). In this case, it will:

  • Perform basic validation (eg. _amount > 0)

  • Check whether the token to be sent is local or remote (USDC is local)

  • Accordingly escrow or burn the amount to be sent (USDC will be escrowed)

After the business logic is executed, the BridgeRouter contract will call dispatch on the Home contract, enqueuing the message to be sent.

3. Core Contract Logic Executes on Origin Chain

The new message is inserted as a leaf, and then merkelized to generate a new Merkle root, which is stored in the Home's queue. Finally, a Dispatch event is emitted, which signals to all relevant parties (ie. the Updater) that a new root has been generated.

4. Updater Signs an Update on the Origin Chain

This function emits an update event which signals to Relayers that a new update has occurred.

5. Update is Relayed to the Replica on the Destination Chain

Note two things:

  1. While this function has the same name update, it has completely different logic in a Replica contract.

A Relayer (which is trustless and permissionless), will call update passing in the _oldRoot, _newRoot, and the _signature which the Updater generated. This will "kick off" the dispute window for the new root, after which messages can be proven and processed.

6. Message is Proven and Processed on the Destination Chain

To prove a message, anyone can call prove on the Replica contract, passing in a leaf corresponding to the message, merkle path and index of the leaf to prove inclusion in the new root.

If this succeeds, the message will be processed, meaning it will be forwarded to the corresponding application router on the destination chain.

7. xApp Handle Logic Executes on Destination Chain

Once handle is called on the Moonbeam BridgeRouter, the BridgeRouter will execute application business logic on its side to complete the bridging process for Alice. In this case, it will mint 1000 Nomad USDC (or madUSDC) to Alice's address on the Moonbeam side.

Note that the BridgeRouter contract is isomorphic, meaning has the same code deployed on both chains. As long as dispatch and handle are implemented, they will be able to communicate with each other, with messages brokered by Nomad's messaging passing layer.

Voila! We have successfully bridged tokens and sent a message via Nomad.

The first step is Alice uses some interface (either the Token Bridge GUI or Etherscan) to construct a transaction to be sent to the BridgeRouter contract .

is an example of a xApp contract that follows . It exists as the entry point for users like Alice to interact with on the origin chain.

In this case, Alice's transaction will call the on the BridgeRouter.

Format the message to be sent, adhering to the contract

Once has been called on the Ethereum Home contract, the application router contract's job is done. This is where the Nomad protocol's work begins.

formats and hashes the message, and inserts it into its Merkle tree. The Merkle tree in the Home contract is the core data structure in Nomad, and contains all the messages to be sent from that Home.

As new roots are generated, the Updater calls on the Ethereum Home contract, committing to the current root and the new root with their digital signature. This signature acts as an attestation on the accumulator root, which can now be relayed to a destination chain.

Once an update has been made on the Home, anyone may call update on any to effectively relay the new root to the destination chain.

An update on the Ethereum Home may be relayed to any number of Replicas corresponding to this Home, per . In this example, we will only cover the Moonbeam Replica.

After elapses, individual messages (ie. Alice's transaction to bridge 1000 USDC) can be proved against the new root.

In this case, a Processor (which is also trustless and permissionless) will prove inclusion of Alice's message in the new root, and then call process on the Replica. The Replica will then forward the message to the BridgeRouter contract on Moonbeam, and invoke .

Astute readers may notice that we assumed that Nomad's optimistic dispute window elapsed without fraud being flagged. To learn more about how fraud detection, flagging and recovery works in Nomad, please check out in the Security section.

deployed on Ethereum
The BridgeRouter contract
the Router pattern
send function
BridgeMessage
dispatch
The Home contract
the update function
Replica contract
the dispute window
its handle function
the Fraud documentation
the broadcast channel model