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
  • Interface
  • Hello World
  • Example Usage
  • Advanced Examples
  • FAQs
  1. Developers
  2. Quickstart

Receive Messages

The on-chain API for receiving cross-chain messages

Receive messages from other chains by implementing the handle() method in your cross-chain application.

Interface

The handle method passes a cross-chain message to the application.

  • _origin is a Nomad domain. List of domains here

  • _nonce is unique for each message within a (origin domain, destination domain) tuple. Many apps won't need to use this field, but it can be used to ensure uniqueness of a message.

  • _sender is the address that sent the message on the origin domain

  • _message contains the contents of the cross-chain message

/*
 * @notice Receive a message from a sender on the origin domain 
 * @param _origin Domain of the origin chain
 * @param _nonce Unique nonce for the (origin, destination) tuple. 
 * @param _sender Address of sender on origin chain as bytes32
 * @param _message Raw bytes content of message
 */
 function handle(
    uint32 _origin,
    uint32 _nonce,
    bytes32 _sender,
    bytes memory _message
) external;

Hello World

 import {TypeCasts} from "@nomad-xyz/contracts-core/libs/TypeCasts.sol";
 
 contract HelloWorld {
    // emitted when a Hello message is received   
    event Hello(uint32 origin, address sender, string memory message);
    
   /*
    * @notice Receive a Hello message from any sender :) 
    * @param _origin Domain of the origin chain
    * @param _sender Address of sender on origin chain as bytes32
    * @param _message Raw bytes content of message
    */
    function handle(
       uint32 _origin,
       uint32 _nonce,
       bytes32 _sender,
       bytes memory _message
    ) onlyReplica {
       address _sendr = TypeCasts.bytes32ToAddress(_sender);
       // emit the message so off-chain friends can see it
       emit Hello(_origin, _sendr, _message);
    }
}

Example Usage

contract PingPong {
    // registry of opponents on each chain
    mapping(uint32 => bytes32) public opponents;
    
    // emitted when a Ping volley is received
    event Ping(uint32 domain, bytes32 opponent, uint256 volleyNumber);
    // emitted when a Pong volley is received
    event Pong(uint32 domain, bytes32 opponent, uint256 volleyNumber);

    /**
     * @notice Start a PingPong match with the destination chain
     * by serving the ball.
     * @param _destination The domain to initiate the match with
     */
    function handle(
       uint32 _origin,
       uint32 _nonce,
       bytes32 _sender,
       bytes memory _message
    ) onlyReplica {
        // validate the message comes from a known opponent
        require(opponents[_origin] == _sender, "not a registered opponent!");
        // decode the message contents using abi.decode
        bool _ping;
        uint256 _volley;
        (_ping, _volley) = abi.decode(_message, (bool, uint256));
        // emit an event for your off-chain spectators
        if (ping) {
            emit Ping(_origin, _sender, _volley);
        } else {
            emit Pong(_origin, _sender, _volley);
        }
        // send a PingPong message back to your opponent!
        bytes memory _message = abi.encode(!_ping, _volley + 1);
        // dispatch your message across chains
        home.dispatch(_origin, _sender, _message);
    }
}

Advanced Examples

FAQs

Why ensure messages come from onlyReplica?

This ensures that the message is a real cross-chain message coming from the Nomad system, not an impostor!

PreviousSend MessagesNextEnvironments

Last updated 3 years ago

The example app we know and love - but make it cross-chain

Ready to get a little more advanced? Let's play PingPong across chains

BridgeRouter.sol

GovernanceRouter.sol

Gnosis NomadModule.sol

🤝
🏓
handle
handle
handle