OP Stack
Superchain interop message passing
Interop is currently in active development and not yet ready for production use. The information provided here may change frequently. We recommend checking back regularly for the most up-to-date information.

Interop message passing overview

💡

This is an explanation of how interop works. You can find a step by step tutorial here.

The low-level CrossL2Inbox (opens in a new tab) 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.

The L2ToL2CrossDomainMessenger (opens in a new tab) 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

  1. The application sends a transaction to a contract on the source chain.

  2. The contract calls L2ToL2CrossDomainMessenger.SendMessage (opens in a new tab). 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 (opens in a new tab) value to ensure the message is only executed once.

    • _sender: The contract that sent the cross domain message.

Executing message

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

  2. The application (or a contract calling on the application's behalf) calls L2ToL2CrossDomainMessenger.SendMessage.relayMessage (opens in a new tab). This call includes the message that was sent (_sendMessage), as well as the fields required to find that message (_id) (opens in a new tab).

  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:

    • 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