Skip to content

Instantly share code, notes, and snippets.

@cwhinfrey
Last active April 9, 2024 16:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cwhinfrey/623fba0ecd08faac2e9a8ad4c1889f6a to your computer and use it in GitHub Desktop.
Save cwhinfrey/623fba0ecd08faac2e9a8ad4c1889f6a to your computer and use it in GitHub Desktop.
An Incomplete Taxonomy of Cross-Chain Messages

An Incomplete Taxonomy of Cross-Chain Messages

Single or Batched

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 or Broadcast

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

Relayed or Self-Relayed

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment