Skip to main content

Mailbox

The Hyperlane Mailbox smart contracts expose an on-chain API for sending and receiving interchain messages. There is a Mailbox contract deployed on every chain Hyperlane supports.

The network of Mailboxes facilitates the connective tissue between blockchains that developers leverage to create interchain applications, and add interchain functionality to their existing applications.

  • To send interchain messages, call the dispatch function.
  • To receive interchain messages, implement the handle function.

Interface

The IMailbox interface exposes two state-mutating functions; dispatch() and process(), which are used to send and receive messages, respectively.

IMailbox Interface
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;

import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol";
import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol";

interface IMailbox {
// ============ Events ============
/**
* @notice Emitted when a new message is dispatched via Hyperlane
* @param sender The address that dispatched the message
* @param destination The destination domain of the message
* @param recipient The message recipient address on `destination`
* @param message Raw bytes of message
*/
event Dispatch(
address indexed sender,
uint32 indexed destination,
bytes32 indexed recipient,
bytes message
);

/**
* @notice Emitted when a new message is dispatched via Hyperlane
* @param messageId The unique message identifier
*/
event DispatchId(bytes32 indexed messageId);

/**
* @notice Emitted when a Hyperlane message is processed
* @param messageId The unique message identifier
*/
event ProcessId(bytes32 indexed messageId);

/**
* @notice Emitted when a Hyperlane message is delivered
* @param origin The origin domain of the message
* @param sender The message sender address on `origin`
* @param recipient The address that handled the message
*/
event Process(
uint32 indexed origin,
bytes32 indexed sender,
address indexed recipient
);

function localDomain() external view returns (uint32);

function delivered(bytes32 messageId) external view returns (bool);

function defaultIsm() external view returns (IInterchainSecurityModule);

function defaultHook() external view returns (IPostDispatchHook);

function requiredHook() external view returns (IPostDispatchHook);

function latestDispatchedId() external view returns (bytes32);

function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody
) external payable returns (bytes32 messageId);

function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody
) external view returns (uint256 fee);

function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata body,
bytes calldata defaultHookMetadata
) external payable returns (bytes32 messageId);

function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody,
bytes calldata defaultHookMetadata
) external view returns (uint256 fee);

function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata body,
bytes calldata customHookMetadata,
IPostDispatchHook customHook
) external payable returns (bytes32 messageId);

function quoteDispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody,
bytes calldata customHookMetadata,
IPostDispatchHook customHook
) external view returns (uint256 fee);

function process(
bytes calldata metadata,
bytes calldata message
) external payable;

function recipientIsm(
address recipient
) external view returns (IInterchainSecurityModule module);
}

Message Headers

The Mailbox prepends message bodies with a header containing the following fields:

FieldDescription
versionThe version of the Mailbox contract
nonceA unique identifier for each message sent from a given Mailbox
originThe domain of the origin chain
senderThe address of the sender on the origin chain
destinationThe domain of the destination chain
recipientThe address of the recipient on the destination chain

See the Message library for more information on the message encoding.

Uniqueness

The nonce is a monotonically increasing integer for each message sent from a given Mailbox. It is incremented each time a message is dispatched to serve as a separator for otherwise identical messages.

function delivered(bytes32 messageId) external view returns (bool);

The messageId is a globally unique message identifier, returned from the dispatch call, computed as the keccak256 hash of the message (with headers).

Replay Protection

The Mailbox maintains a mapping of already delivered messageId values to prevent replay attacks. If a message is received with a messageId that has already been delivered, the message is rejected.

function defaultIsm() external view returns (IInterchainSecurityModule);

Dispatch

To send interchain messages, developers call Mailbox.dispatch().

This function takes as parameters the message contents, the destination chain ID, and the recipient address. Each message get inserted as a leaf into an incremental merkle tree stored by the Mailbox.

Hyperlane's proof of stake protocol uses this merkle tree to verify fraud proofs.

Process

To deliver interchain messages, the relayer calls Mailbox.process().

This function takes as parameters the message to deliver as well as arbitrary metadata that can be specified by the relayer.

The Mailbox will pass the message and metadata to the recipient's interchain security module for verification. If the ISM successfully verifies the message, the Mailbox delivers the message to the recipient by calling recipient.handle().

info

See Message.solfor more details on Hyperlane message encoding