-
Notifications
You must be signed in to change notification settings - Fork 306
How to use general message passing #1032
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
Changes from 2 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
86b2b0f
Added contents for general message passing on OP Stack
krofax e95498f
Cleaned the code
krofax 483c5a6
Update pages/stack/interop/message-passing.mdx
krofax 8b21235
Update pages/stack/interop/message-passing.mdx
krofax b470e82
fix conflict
krofax ad62629
fix conflict
krofax 9ed4706
Updated the contents
krofax 2df4786
fix lint issues
krofax 89e9fb8
update title
krofax ce9b836
Update pages/stack/interop/_meta.json
krofax 37de46e
fix merge conflict
krofax 21d3139
update meta.json
krofax 5fe83b5
Merge branch 'main' into message-passing
krofax File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,261 @@ | ||
| --- | ||
| title: 'Message Passing with Interop' | ||
| lang: en-US | ||
| description: 'Learn how to implement cross-chain message passing using interop messaging.' | ||
| --- | ||
|
|
||
| import { Steps } from 'nextra/components' | ||
|
|
||
| # Message passing with Interop | ||
|
|
||
| This guide explains how to implement cross-chain message passing using interop messaging. | ||
| You'll learn the core concepts and implementation details independent of specific tooling. | ||
|
|
||
| ## Message passing concepts | ||
|
|
||
| Before diving into implementation, it's crucial to understand the core concepts of interop message passing: | ||
|
|
||
| ### Message structure | ||
|
|
||
| A message is a broadcast payload emitted from an identified source. It consists of: | ||
|
|
||
| * **Message Payload**: Raw bytes representing a Log, created by concatenating topics and data | ||
| * **Unique Identifier**: A structure that points to a specific log emission | ||
| * **Execution Context**: Information about where and how the message should be processed | ||
|
|
||
| ### Message payload construction | ||
|
|
||
| ```typescript | ||
| // Message payload is constructed by concatenating: | ||
| // 1. All event topics (each 32 bytes) | ||
| // 2. The event data | ||
| messagePayload = eventTopics.concat(eventData) | ||
| ``` | ||
|
|
||
| ### Message identifier components | ||
|
|
||
| ```solidity | ||
| struct Identifier { | ||
| address origin; // Contract that emitted the log | ||
| uint256 blockNumber; // Block number of emission | ||
| uint256 logIndex; // Position in block's logs array | ||
| uint256 timestamp; // Emission timestamp | ||
| uint256 chainId; // Chain identifier where message originated | ||
| } | ||
| ``` | ||
|
|
||
| ## How It works | ||
|
|
||
| ### Message lifecycle | ||
|
|
||
| The cross-chain messaging process follows a specific lifecycle: | ||
|
|
||
| 1. **Message Creation**: Events on source chain become initiating messages | ||
| 2. **Message Serialization**: Converting log data into a standardized format | ||
| 3. **Identifier Creation**: Generating unique identifiers for message tracking | ||
| 4. **Message Execution**: Processing messages on destination chain | ||
|
|
||
| ### Message processing flow | ||
|
|
||
| 1. **Source chain**: | ||
| * Event emission triggers message creation | ||
| * System generates unique identifier | ||
| * Message is serialized and prepared for transmission | ||
|
|
||
| 2. **Cross-Chain transit**: | ||
| * Message payload is prepared for relay | ||
| * System validates message structure | ||
| * Cross-chain proof is generated | ||
|
|
||
| 3. **Destination chain**: | ||
| * Message receipt and validation | ||
| * Execution of message content | ||
| * Verification of successful processing | ||
|
|
||
| ## Implementation guide | ||
|
|
||
| <Steps> | ||
| ### Prepare message sending | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The [CrossChainMessenger](https://github.com/ethereum-optimism/optimism/blob/92ed64e171c6eb9c6a080c626640e8836f0653cc/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) contract serves as the primary interface for cross-chain communication. | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| It initializes the connection to the L2 messenger contract and provides the base functionality for sending messages across chains. | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Key components: | ||
|
|
||
| * L2\_MESSENGER: The address of the L2 cross-domain messenger contract | ||
| * sendCrossChainMessage: Function to initiate cross-chain message sending | ||
|
|
||
| ```solidity | ||
| contract CrossChainMessenger { | ||
| address public immutable L2_MESSENGER = 0x4200000000000000000000000000000000000023; | ||
| function sendCrossChainMessage( | ||
| address _target, // Destination contract address | ||
| bytes memory _message, // Message content to be sent | ||
| uint32 _gasLimit // Gas limit for execution on destination | ||
| ) external { | ||
| IL2CrossDomainMessenger(L2_MESSENGER).sendMessage( | ||
| _target, | ||
| _message, | ||
| _gasLimit | ||
| ); | ||
| } | ||
| } | ||
| ``` | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Send the message | ||
|
|
||
| This function handles the actual transmission of your message to the destination chain. It manages: | ||
|
|
||
| * Contract interaction with the messenger | ||
| * Gas limit settings for the transaction | ||
| * Error handling during transmission | ||
| * Returns the transaction hash for tracking | ||
|
|
||
| ```typescript | ||
| async function sendMessage( | ||
| messenger: address, // Address of the messenger contract | ||
| target: address, // Destination contract address | ||
| message: bytes, // Message content to be transmitted | ||
| gasLimit: number // Execution gas limit | ||
| ): Promise<string> { | ||
| // Send the message with appropriate gas settings | ||
| const tx = await contract.sendMessage( | ||
| target, | ||
| message, | ||
| gasLimit, | ||
| { gasLimit: 200000 } // Transaction gas limit for sending | ||
| ); | ||
|
|
||
| return tx.hash; | ||
| } | ||
| ``` | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Create message identifier | ||
|
|
||
| Creates a unique identifier for tracking your message across chains. This function: | ||
|
|
||
| * Retrieves transaction details | ||
| * Locates the specific message event | ||
| * Constructs the identifier structure with: | ||
| * Origin address | ||
| * Block information | ||
| * Chain details | ||
| * Timing data | ||
|
|
||
| ```typescript | ||
| async function createMessageIdentifier( | ||
| txHash: string, // Transaction hash of the sent message | ||
| provider: Provider // Network provider for accessing chain data | ||
| ): Promise<Identifier> { | ||
| // Get transaction and block information | ||
| const receipt = await provider.getTransactionReceipt(txHash); | ||
| const block = await provider.getBlock(receipt.blockNumber); | ||
|
|
||
| // Find the message sent event | ||
| const sentEvent = receipt.logs.find(log => | ||
| log.address === L2_MESSENGER_ADDRESS && | ||
| log.topics[0] === SENT_MESSAGE_EVENT_SIGNATURE | ||
| ); | ||
|
|
||
| if (!sentEvent) throw new Error("Message event not found"); | ||
|
|
||
| // Construct and return the identifier | ||
| return { | ||
| origin: L2_MESSENGER_ADDRESS, | ||
| blockNumber: receipt.blockNumber, | ||
| logIndex: sentEvent.logIndex, | ||
| timestamp: block.timestamp, | ||
| chainId: provider.network.chainId | ||
| }; | ||
| } | ||
| ``` | ||
|
|
||
| ### Construct message payload | ||
|
|
||
| Assembles the complete message payload for transmission. This function: | ||
|
|
||
| * Concatenates event topics and data | ||
| * Formats the payload for cross-chain transmission | ||
| * Ensures proper byte alignment | ||
| * Maintains data integrity | ||
|
|
||
| ```typescript | ||
| function constructMessagePayload( | ||
| topics: string[], // Event topics to include | ||
| data: string // Additional message data | ||
| ): string { | ||
| // Combine topics and data into a single payload | ||
| return ethers.utils.hexConcat([ | ||
| ...topics, | ||
| data | ||
| ]); | ||
| } | ||
| ``` | ||
|
|
||
| ### Relay the message | ||
|
|
||
| Executes the message on the destination chain. This function: | ||
|
|
||
| * Creates a messenger contract instance | ||
| * Sends the relay transaction | ||
| * Handles gas estimation | ||
| * Manages transaction confirmation | ||
| * Returns the transaction hash | ||
|
|
||
| ```typescript | ||
| async function relayMessage( | ||
| identifier: Identifier, // Message identifier from source chain | ||
| payload: string, // Constructed message payload | ||
| provider: Provider // Network provider for destination chain | ||
| ): Promise<string> { | ||
| // Initialize messenger contract | ||
| const messenger = new Contract( | ||
| L2_MESSENGER_ADDRESS, | ||
| L2_MESSENGER_ABI, | ||
| provider.getSigner() | ||
| ); | ||
|
|
||
| // Send relay transaction with appropriate gas limit | ||
| const tx = await messenger.relayMessage( | ||
| identifier, | ||
| payload, | ||
| { gasLimit: 500000 } | ||
| ); | ||
|
|
||
| return tx.hash; | ||
| } | ||
| ``` | ||
|
|
||
| ### Verify message receipt | ||
|
|
||
| Confirms that your message was successfully processed on the destination chain. This function: | ||
|
|
||
| * Retrieves the transaction receipt | ||
| * Checks for the relay event | ||
| * Verifies processing status | ||
| * Returns success/failure status | ||
|
|
||
| ```typescript | ||
| async function verifyMessageRelayed( | ||
| txHash: string, // Transaction hash of the relay transaction | ||
| provider: Provider // Network provider for destination chain | ||
| ): Promise<boolean> { | ||
| // Get transaction receipt | ||
| const receipt = await provider.getTransactionReceipt(txHash); | ||
|
|
||
| // Check for successful relay event | ||
| return receipt.logs.some(log => | ||
| log.address === L2_MESSENGER_ADDRESS && | ||
| log.topics[0] === RELAYED_MESSAGE_EVENT_SIGNATURE | ||
| ); | ||
| } | ||
| ``` | ||
| </Steps> | ||
|
|
||
| ## Next steps | ||
|
|
||
| * More questions? Read our guide on the anatomy of a [cross-chain message](cross-chain-message) | ||
| * Use [Supersim](supersim), a local dev environment that simulates Superchain interop for testing applications against a local version of the Superchain. | ||
| * Use [viem bindings/actions](https://supersim.pages.dev/guides/interop/relay-using-viem.html)the guide will show you how to use viem bindings/actions to fetch identifiers and relay messages. | ||
krofax marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| * Read how to manually [relay interop messages](https://supersim.pages.dev/guides/interop/manually-relaying-interop-messages-cast) with cast and `L2ToL2CrossDomainMessenger` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,7 @@ computependingblock | |
| confs | ||
| corsdomain | ||
| counterfactually | ||
| Crosschain | ||
| crosschain | ||
| Crossmint | ||
| daserver | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.