Single Messages - Single messages have a single target address, target chainId
, and data payload. The vast majority of cross-chain messages today are single messages.
Example:
function dispatchMessage(uint256 toChainId, address to, bytes calldata data) external payable returns (bytes32 messageId);
Batched Messages - Atomic batches of messages can be used for functionality that requires calling multiple targets. By nature of being atomic, either the whole batch executes or reverts. An atomic batch necessarily has a single target chainId
and many target addresses and data payloads. Non-atomic batches are not covered by this category and are better thought of as individual single messages.
Example:
struct Message {
address to;
bytes data;
}
function dispatchMessageBatch(uint256 toChainId, Message[] calldata messages) external payable returns (bytes32 messageId);
Single Destination Messages - See Single Messages.
Broadcast Messages - Broadcast messages allow identical data payload(s) to be sent to multiple destination chains. This is useful for things like broadcasting app state to cross-chain deployments. The target addresses may differ per chain since a cross-chain app’s deployments may have different addresses on each chain. Cases where the data payload differs per chain are better thought of as individual single messages.
Example:
function broadcastMessage(uint256[] toChainIds, address[] targets, bytes calldata data) external payable returns (bytes32[] messageIds);
Self-relayed messages - Self-relayed messages are assumed to be executed by the message sender or a party that is unconcerned with being griefed by the message sender. Any of the message types above should be assumed to be self-relayed or can be modified with the parameters below for a relayed setup.
Relayed messages - Relayed messages are messages that are executed by a third party relayer. Transactions submitted to an L1 or rollup can be thought of as relayed messages as well in some cases. Relayed messages require extra data that is used to prevent griefing attacks against the relayer, sequencer, or block producer and guarantee proper execution for the message sender. Relayed messages should include a gasLimit
with each message. A maxFee
or something similar should also be included in most cases to prevent over-payment. Chains may require custom fee and gas limit parameters such as Ethereum’s, maxFee
and priorityFee
or the “multi-dimensional gas” setup seen in some rollups.
Example:
struct RelayedMessage {
address to;
uint256 gasLimit;
bytes data;
}
function dispatchRelayedMessage(
uint256 toChainId,
address to,
uint256 maxFee,
uint256 gasLimit,
bytes calldata data
) external payable returns (bytes32 messageId);
function dispatchRelayedMessageBatch(
uint256 toChainId,
uint256 maxFee,
RelayedMessage[] calldata messages
) external payable returns (bytes32 messageId);
function broadcastRelayedMessage(
uint256[] toChainIds,
address[] targets,
uint256[] maxFees,
uint256 gasLimit,
bytes calldata data
) external payable returns (bytes32 messageId);
Other Cases
- Sending tokens or gas tokens along with the message
- Specifying a fee refund address
- Messages generated by contracts internally without any external
dispatch
interface