From c5b6ff66bb94a7f2b0e3633015c6d599382380ef Mon Sep 17 00:00:00 2001 From: Ori Pomerantz Date: Mon, 20 Jan 2025 20:12:31 -0600 Subject: [PATCH 1/4] First version --- pages/stack/interop/message-passing.mdx | 106 ++++++++++++++++-------- 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/pages/stack/interop/message-passing.mdx b/pages/stack/interop/message-passing.mdx index 8bcd46889..7cb2eda88 100644 --- a/pages/stack/interop/message-passing.mdx +++ b/pages/stack/interop/message-passing.mdx @@ -6,61 +6,95 @@ description: Learn about cross-chain message passing in the Superchain. import { Callout, Steps } from 'nextra/components' -# Interop message passing overview - - - 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. - +import { InteropCallout } from '@/components/WipCallout' -This guide provides an overview of cross-chain message passing in the Superchain. + -## 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. +# Interop message passing overview -## How it works +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. -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 L2ToL2Cross... + participant log as Event Log + end + box rgba(0,0,0,0.1) Destination Chain + participant dstXdom as L2ToL2Cross... + participant dstContract as Destination Contract + end + app->>srcContract: 1. Send a message + srcContract->>srcXdom: 2. Call contract A
in chainId B
with calldata C + srcXdom->>log: 3. 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. After a few sanity checks, `L2ToL2CrossDomainMessenger` emits a log entry. + In addition to the parameters, the log entry also includes: -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. + - `_nonce`, a [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) value to ensure the message is only executed once. -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. + - `_sender`, the contract that sent the cross domain message. -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. -4. **Message Execution**: The destination chain receives and processes the message, executing any associated actions or state changes specified in the original message. +## Executing message -For detailed implementation steps and code examples, see our [message passing implementation guide](https://supersim.pages.dev/guides/interop/viem). +```mermaid + +sequenceDiagram + participant app as Application + box rgba(0,0,0,0.1) Source Chain + participant srcContract as Source Contract + participant srcXdom as L2ToL2Cross... + participant log as Event Log + end + box rgba(0,0,0,0.1) Destination Chain + participant dstXdom as L2ToL2Cross... + participant dstContract as Destination Contract + end + app->>dstXdom: 1. Send an executing message + note over dstXdom: 2. Sanity checks + dstXdom->>dstContract: 3. Call with provided calldata. +``` -## Common Use Cases +1. 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). -* Simple messages between identical contracts -* Complex multi-contract interactions -* Cross-chain state synchronization -* Token transfers and bridging +2. `L2ToL2CrossDomainMessenger` on the destination chain verified the message is legitimate: + + - The origin (of the log entry) is `L2ToL2CrossDomainMessenger` on the other side. + - Verify the message really was sent from the source (using `CrossL2Inbox`). + - 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. + +3. 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 */} From b28bf5732b74d7e5d2c7b96ab761dfe9cc3d46ea Mon Sep 17 00:00:00 2001 From: Ori Pomerantz Date: Tue, 21 Jan 2025 10:16:18 -0600 Subject: [PATCH 2/4] @zainbacchus review comments --- pages/stack/interop/message-passing.mdx | 46 +++++++++++++++---------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/pages/stack/interop/message-passing.mdx b/pages/stack/interop/message-passing.mdx index 7cb2eda88..4314c5b5c 100644 --- a/pages/stack/interop/message-passing.mdx +++ b/pages/stack/interop/message-passing.mdx @@ -16,6 +16,9 @@ The low level [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blo 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. +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. + ## Initiating message ```mermaid @@ -24,16 +27,13 @@ sequenceDiagram participant app as Application box rgba(0,0,0,0.1) Source Chain participant srcContract as Source Contract - participant srcXdom as L2ToL2Cross... + participant srcXdom as L2ToL2CrossDomainMessenger participant log as Event Log end - box rgba(0,0,0,0.1) Destination Chain - participant dstXdom as L2ToL2Cross... - participant dstContract as Destination Contract - end app->>srcContract: 1. Send a message srcContract->>srcXdom: 2. Call contract A
in chainId B
with calldata C - srcXdom->>log: 3. Log event SentMessage + note over srcXdom: 3. Sanity checks + srcXdom->>log: 4. Log event SentMessage ``` @@ -47,7 +47,12 @@ sequenceDiagram - `_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. After a few sanity checks, `L2ToL2CrossDomainMessenger` emits a log entry. +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. @@ -62,32 +67,37 @@ sequenceDiagram sequenceDiagram participant app as Application box rgba(0,0,0,0.1) Source Chain - participant srcContract as Source Contract - participant srcXdom as L2ToL2Cross... participant log as Event Log - end + end + participant super as OP-Supervisor
(destination chain
node) box rgba(0,0,0,0.1) Destination Chain - participant dstXdom as L2ToL2Cross... + participant dstXdom as L2ToL2CrossDomainMessenger + participant Xinbox as CrossL2Inbox participant dstContract as Destination Contract end - app->>dstXdom: 1. Send an executing message - note over dstXdom: 2. Sanity checks - dstXdom->>dstContract: 3. Call with provided calldata. + 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. 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). +1. Before the executing message is processed, the log event of the initiating message has to get to OP-Proposer on the destination chain. + +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). -2. `L2ToL2CrossDomainMessenger` on the destination chain verified the message is legitimate: +3. `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message really was sent from the source. + +4. `L2ToL2CrossDomainMessenger` on the destination chain verifies the message is legitimate: - The origin (of the log entry) is `L2ToL2CrossDomainMessenger` on the other side. - - Verify the message really was sent from the source (using `CrossL2Inbox`). - 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. -3. If everything checks out, `L2ToL2CrossDomainMessenger` calls the destination contract with the calldata provided in the message. +5. If everything checks out, `L2ToL2CrossDomainMessenger` calls the destination contract with the calldata provided in the message. ## Next steps From 9f8fcf15f1ee8707601c70b4dd04bd244275a460 Mon Sep 17 00:00:00 2001 From: Ori Pomerantz Date: Tue, 21 Jan 2025 10:18:46 -0600 Subject: [PATCH 3/4] eslint --- pages/stack/interop/message-passing.mdx | 63 ++++++++++++------------- words.txt | 5 +- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/pages/stack/interop/message-passing.mdx b/pages/stack/interop/message-passing.mdx index 4314c5b5c..93881eda5 100644 --- a/pages/stack/interop/message-passing.mdx +++ b/pages/stack/interop/message-passing.mdx @@ -13,7 +13,7 @@ import { InteropCallout } from '@/components/WipCallout' # Interop message passing overview 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. +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. 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. @@ -37,28 +37,27 @@ sequenceDiagram ``` -1. The application sends a transaction to a contract on the source chain. +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: +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. + * `_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`. +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: +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. - - - `_sender`, the contract that sent the cross domain message. + * `_nonce`, a [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) value to ensure the message is only executed once. + * `_sender`, the contract that sent the cross domain message. ## Executing message @@ -82,29 +81,27 @@ sequenceDiagram 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. - -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). +1. Before the executing message is processed, the log event of the initiating message has to get to OP-Proposer on the destination chain. -3. `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message really was sent from the source. +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). -4. `L2ToL2CrossDomainMessenger` on the destination chain verifies the message is legitimate: +3. `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message really was sent from the source. - - 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. +4. `L2ToL2CrossDomainMessenger` on the destination chain verifies the message is legitimate: -5. If everything checks out, `L2ToL2CrossDomainMessenger` calls the destination contract with the calldata provided in the message. + * 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. ## Next steps -- 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) - +* 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 */} diff --git a/words.txt b/words.txt index fc73c26e8..3445dc81c 100644 --- a/words.txt +++ b/words.txt @@ -154,7 +154,7 @@ Inator inator INFLUXDBV influxdbv -interchain +intiating IPCDISABLE ipcdisable ipcfile @@ -186,6 +186,7 @@ MEMPROFILERATE memprofilerate Merkle merkle +mesage MFHI MFLO Minato @@ -289,6 +290,7 @@ pricelimit productionize productionized Protip +providng Proxied Proxyd proxyd @@ -360,7 +362,6 @@ Superchain superchain Superchain's Superchainerc -superchainerc Superchains Superscan Supersim From 95310e040dacb310ff0b1d68ebabd6cdc885d6e1 Mon Sep 17 00:00:00 2001 From: Ori Pomerantz Date: Wed, 22 Jan 2025 09:24:14 -0600 Subject: [PATCH 4/4] @krofax suggestions Co-authored-by: Blessing Krofegha --- pages/stack/interop/message-passing.mdx | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pages/stack/interop/message-passing.mdx b/pages/stack/interop/message-passing.mdx index 93881eda5..7d25f156e 100644 --- a/pages/stack/interop/message-passing.mdx +++ b/pages/stack/interop/message-passing.mdx @@ -12,12 +12,11 @@ import { InteropCallout } from '@/components/WipCallout' # Interop message passing overview -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. +The low-level [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) contract handles basic message execution. It verifies whether an initiating message exists but does not check the message's destination, processing status, or other attributes. -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 [`L2ToL2CrossDomainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) contract extends `CrossL2Inbox` by providing complete cross-domain messaging functionality. + +For high-level interoperability, both messages use the `L2ToL2CrossDomainMessenger` contract on their respective chains. ## Initiating message @@ -42,9 +41,9 @@ sequenceDiagram 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. + * `_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: @@ -55,9 +54,9 @@ sequenceDiagram 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. + * `_nonce`: A [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) value to ensure the message is only executed once. - * `_sender`, the contract that sent the cross domain message. + * `_sender`: The contract that sent the cross domain message. ## Executing message @@ -81,12 +80,12 @@ sequenceDiagram 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. +1. Before the executing message is processed, the log event of the initiating message has to get to `op-proposer` on the destination chain. 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). -3. `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message really was sent from the source. +3. The `L2ToL2CrossDomainMessenger` uses `CrossL2Inbox` to verify the message was sent from the source. 4. `L2ToL2CrossDomainMessenger` on the destination chain verifies the message is legitimate: