Skip to main content

Overview

Message bridging enables smart contracts on different chains to communicate and trigger execution across chains. A contract on the source chain calls bridgeMessage with encoded function data, and the bridge executes that data on the destination contract when the message is claimed. Message Bridging Process Figure 1: Complete message bridging flow from L2 to L1

Message Model

What Message Bridging Supports

  • Contract-to-contract communication: Smart contracts can trigger function calls on other chains
  • Cross-chain state updates: Contracts can update state on destination chains
  • Trustless communication: Cryptographic verification of all cross-chain messages via Merkle proofs

Message Structure

Cross-chain messages contain:
  • Destination contract: Address of the contract to execute on the destination chain
  • Function data: Encoded function call data
  • Value: ETH value to send with the message (if any)
  • Gas limit: Maximum gas for execution on the destination chain
  • Metadata: Additional data for the message

Bridge Message Function

The bridgeMessage function initiates message transfers between chains.

Function Signature

function bridgeMessage(
    uint32 destinationNetwork,
    address destinationAddress,
    uint256 gasLimit,
    bytes calldata data
) external payable

Parameters

  • destinationNetwork: Network ID of the destination chain
  • destinationAddress: Address of the contract to execute on destination chain
  • gasLimit: Maximum gas for execution on destination chain
  • data: Encoded function call data

Process Steps

  1. Validation: Check destination network is not the source network
  2. Value Handling: Handle ETH value if provided
  3. Event Emission: Emit BridgeEvent with message details
  4. Tree Update: Add message to Local Exit Tree as leaf node

Example Usage

// Bridge a message to call a function on destination chain
bridgeMessage(
    1, // destinationNetwork (L2)
    0x..., // destinationAddress (contract address)
    100000, // gasLimit
    abi.encodeWithSignature("updateValue(uint256)", 123) // data
);

Claim Message Function

The claimMessage function claims and executes bridged messages on the destination chain.

Function Signature

function claimMessage(
    bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot,
    bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot,
    uint256 globalIndex,
    bytes32 mainnetExitRoot,
    bytes32 rollupExitRoot,
    uint32 originNetwork,
    address originAddress,
    uint32 destinationNetwork,
    address destinationAddress,
    uint256 gasLimit,
    bytes calldata data
) external

Parameters

  • smtProofLocalExitRoot: Merkle proof for Local Exit Root
  • smtProofRollupExitRoot: Merkle proof for Rollup Exit Root
  • globalIndex: Global index identifying the message
  • mainnetExitRoot: Mainnet Exit Root at time of message
  • rollupExitRoot: Rollup Exit Root at time of message
  • originNetwork: Network ID of source chain
  • originAddress: Address that sent the message
  • destinationNetwork: Network ID of destination chain
  • destinationAddress: Address of the contract to execute
  • gasLimit: Maximum gas for execution
  • data: Encoded function call data

Process Steps

  1. Validation: Verify destination network matches current chain
  2. Proof Verification: Verify Merkle proofs against Global Exit Root
  3. Duplicate Check: Ensure message hasn’t been claimed before
  4. Message Execution: Execute the message on destination contract
  5. Claim Record: Mark message as claimed

Message Execution

// Execute the message on destination contract
(bool success, bytes memory returnData) = destinationAddress.call{
    value: msg.value,
    gas: gasLimit
}(data);

require(success, "Message execution failed");
Important Notes:
  • Messages can only be executed if the destinationAddress is a smart contract that implements the IBridgeMessageReceiver interface
  • If the receiving address is an EOA, the call will result as a success, meaning that the amount of ether will be transferred correctly, but the message will not trigger any execution
  • If the native gas token is ETH, then transfer ETH to the destinationAddress and execute the message
  • If ETH is not the native gas token, then mint WETH to the destinationAddress and execute the message

IBridgeMessageReceiver Interface

For a contract to receive bridged messages, it must implement the IBridgeMessageReceiver interface:
interface IBridgeMessageReceiver {
    function onMessageReceived(
        address originAddress,
        uint32 originNetwork,
        bytes calldata data
    ) external payable;
}
Parameters:
  • originAddress: Address that sent the message on the source chain
  • originNetwork: Network ID of the source chain
  • data: The message data/metadata sent from source chain

Bridging Flows

L1 to L2 Message Bridging

L2 to L1 Message Bridging

L2 to L2 Message Bridging