Skip to main content

Send a message

Contracts can send interchain messages by calling the dispatch function on the Mailbox.

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);
}

Dispatch

Calling this function dispatches a message to the destination domain and recipient.

warning

Hyperlane can only deliver messages to smart contracts that implement the handle function. See the receive a message documentation for more information.

Depending on the post-dispatch hook configuration, some payment may be required. See the quoteDispatch section for more information.

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

Recipient addresses are left-padded to bytes32 for compatibility with virtual machines that are addressed differently. The following utility is provided in the TypeCasts library for convenience.

// alignment preserving cast
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}

Examples

// send message from alfajores to bsctestnet TestRecipient
IMailbox mailbox = IMailbox("0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59");
bytes32 messageId = mailbox.dispatch{value: msg.value}(
97,
"0x0000000000000000000000006489d13AcAd3B8dce4c5B31f375DE4f9451E7b38",
bytes("Hello, world")
);

Quote Dispatch

Fees are often configured to cover IGP payments as well as protocol costs. These include transaction submission on the destination chain, security provisioning, and maintenance. To receive a quote for a corresponding dispatch call, you can query the quoteDispatch function.

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

The quoted fee must be passed as value to the dispatch call to ensure it does not revert.

Examples

// quote sending message from alfajores to bsctestnet TestRecipient
IMailbox mailbox = IMailbox("0xEf9F292fcEBC3848bF4bB92a96a04F9ECBb78E59");
uint32 destination = 97;
bytes32 recipient = "0x0000000000000000000000006489d13AcAd3B8dce4c5B31f375DE4f9451E7b38";
bytes memory body = bytes("Hello, world");
uint256 fee = mailbox.quoteDispatch(destination, recipient, body);
mailbox.dispatch{value: fee}(destination, recipient, body);
danger

Underpayment to dispatch will revert. If you are composing hooks together, overpayment may not be refunded to the message sender.

Post-Dispatch Hook Config

There are two hooks configured on a Mailbox

  • required: invoked for all dispatch calls with value that covers the required fee
  • default: invoked (unless overriden) with remaining value after required hook

Required Hook

To query the required hook configuration, you can call the requiredHook function.

function requiredHook() external view returns (IPostDispatchHook);

Default Hook

To query the default hook configuration, you can call the defaultHook function.

function defaultHook() external view returns (IPostDispatchHook);

To override the default hook with a custom hook in the dispatch call, see the Hooks Reference.