Skip to content

Interop message passing explainer #1268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 22, 2025
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 79 additions & 35 deletions pages/stack/interop/message-passing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,61 +6,105 @@ description: Learn about cross-chain message passing in the Superchain.

import { Callout, Steps } from 'nextra/components'

# Interop message passing overview

<Callout>
Interop is currently in active development and not yet ready for production use. The information provided here may change. Check back regularly for the most up-to-date information.
</Callout>
import { InteropCallout } from '@/components/WipCallout'

This guide provides an overview of cross-chain message passing in the Superchain.
<InteropCallout />

## Overview
# Interop message passing overview

The Superchain uses a pull-based event system for cross-chain communication. Messages are sent through the `L2ToL2CrossDomainMessenger` contract, which provides a secure and standardized way to pass information between chains.
The low level [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) contract provides for basic executing message functionality, it verifies whether an initiating message is available or not.
However, this contract does not check what is the destination of a message, whether it has already been processed, etc.
The [`L2ToL2CrossDomainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) contracts sits on top of `CrossL2Inbox` and provides the full functionality expected of a cross domain messenger.

## How it works
A cross-chain message in the Superchain is two transactions: an *intiating message* on the source chain and an *executing mesage* on the destination chain.
For high level interop messages, both messages use `L2ToL2CrossDomainMessenger` on their respective chains.

The following diagram illustrates how messages flow between chains through the `L2ToL2CrossDomainMessenger` contract, which acts as a bridge for cross-chain communication. When a contract on the source chain initiates a message, it's processed through several stages before reaching its destination, ensuring secure and reliable message delivery.
## Initiating message

```mermaid

sequenceDiagram
participant Source as Source Chain
participant Messenger as L2ToL2CrossDomainMessenger
participant Dest as Destination Chain
participant app as Application
box rgba(0,0,0,0.1) Source Chain
participant srcContract as Source Contract
participant srcXdom as L2ToL2CrossDomainMessenger
participant log as Event Log
end
app->>srcContract: 1. Send a message
srcContract->>srcXdom: 2. Call contract A<br/>in chainId B<br/>with calldata C
note over srcXdom: 3. Sanity checks
srcXdom->>log: 4. Log event SentMessage

Note over Source,Dest: Message Creation
Source->>Messenger: Emit message event
Note over Source,Dest: Message Serialization
Messenger-->>Messenger: Convert to standard format
Note over Source,Dest: Identifier Creation
Messenger-->>Messenger: Generate unique ID
Note over Source,Dest: Message Execution
Messenger->>Dest: Process message
```

Cross-chain messaging involves four main phases:
1. The application sends a transaction to a contract on the source chain.

2. The contract calls [`L2ToL2CrossDomainMessenger.SendMessage`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L127-L154).
The call requires these parameters:

- `_destination`, the chain ID of the destination blockchain.
- `_target`, the address of the contract on that blockchain.
- `_message`, the actual message.
This message is provided to `_target` as calldata, which means it includes a function selector and the parameters for that function call.

3. `L2ToL2CrossDomainMessenger` on the source chain verifies the message is legitimate:
- The destination chain is one to which this chain can send messages.
- The destination chain is *not* the source chain.
- The target is neither `CrossL2Inbox` nor `L2ToL2CrossDomainMessenger`.

4. `L2ToL2CrossDomainMessenger` emits a log entry.
In addition to the parameters, the log entry also includes:

- `_nonce`, a [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) value to ensure the message is only executed once.

1. **Message Creation**: The source chain contract emits an event containing the message data and destination information. This event serves as the initiating message that will be relayed across chains.
- `_sender`, the contract that sent the cross domain message.

2. **Message Serialization**: The messenger contract converts the event data into a standardized format that can be consistently processed across different chains in the Superchain.

3. **Identifier Creation**: A unique identifier is generated for the message, containing information about its `origin`, `timestamp`, and other `metadata`. This identifier helps track and verify the message.
## Executing message

4. **Message Execution**: The destination chain receives and processes the message, executing any associated actions or state changes specified in the original message.
```mermaid

sequenceDiagram
participant app as Application
box rgba(0,0,0,0.1) Source Chain
participant log as Event Log
end
participant super as OP-Supervisor<br/>(destination chain<br/>node)
box rgba(0,0,0,0.1) Destination Chain
participant dstXdom as L2ToL2CrossDomainMessenger
participant Xinbox as CrossL2Inbox
participant dstContract as Destination Contract
end
log->>super: 1. Initiating message log event
app->>dstXdom: 2. Send an executing message
dstXdom->>Xinbox: 3. Verify the initiating message is real
note over dstXdom: 4. Sanity checks
dstXdom->>dstContract: 5. Call with provided calldata
```

1. Before the executing message is processed, the log event of the initiating message has to get to OP-Proposer on the destination chain.

For detailed implementation steps and code examples, see our [message passing implementation guide](https://supersim.pages.dev/guides/interop/viem).
2. The application (or a contract calling on the application's behalf) calls [`L2ToL2CrossDomainMessenger.SendMessage.relayMessage`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol#L156-L216).
This call includes the message that was sent (`_sendMessage`), as well as the [fields required to find that message (`_id`)](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/interfaces/L2/ICrossL2Inbox.sol#L4-L10).

## Common Use Cases
3. `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message really was sent from the source.

* Simple messages between identical contracts
* Complex multi-contract interactions
* Cross-chain state synchronization
* Token transfers and bridging
4. `L2ToL2CrossDomainMessenger` on the destination chain verifies the message is legitimate:

- The origin (of the log entry) is `L2ToL2CrossDomainMessenger` on the other side.
- The destination chain ID is correct.
- The target is neither `CrossL2Inbox` nor `L2ToL2CrossDomainMessenger`.
- This message has not been relayed before.
This is the reason we need the nonce value, to enable us to send multiple messages that would be otherwise identical.

5. If everything checks out, `L2ToL2CrossDomainMessenger` calls the destination contract with the calldata provided in the message.

For a practical example, see our [cross-chain ping pong tutorial](https://supersim.pages.dev/guides/interop/cross-chain-contract-calls-pingpong).

## Next steps

* Read about the [anatomy of a cross-chain message](/stack/interop/explainer#how-messages-get-from-one-chain-to-the-other)
* Try [Supersim](supersim) for testing cross-chain messages locally
- Read how [messages get from one blockchain to another (`CrossL2Inbox`)](explainer#how-messages-get-from-one-chain-to-the-other).
- Try [Supersim](tools/supersim) for testing cross-chain messages locally
* Learn about [manually relaying messages](https://supersim.pages.dev/guides/interop/viem?#viem-to-send-and-relay-interop-messages)


{/* After the tutorial for L2ToL2CrossDomainMessenger is written, need to add a link here */}