Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

L2 to L1 messaging

Table of Contents

Current approaches

While L2 -> L1 messaging can be built on top of the state root that the EXECUTE precompile already exposes, some projects expose a shallower interface to make it easier to provide inclusion proofs. We first discuss how existing projects implement L2 -> L1 messaging, to better understand how similar mechanisms can be implemented in native rollups.

OP stack

[spec] The piece of data that is used on the L1 side of the L2->L1 messaging bridge is a "block output root, which is defined as:

struct BlockOutput {
  bytes32 version;
  bytes32 stateRoot;
  bytes32 messagePasserStorageRoot;
  bytes32 blockHash;
}

Inclusion proofs are verified against the messagePasserStorageRoot instead of the stateRoot, which represents the storage root of the L2ToL1MessagePasser contract on L2. On the L2 side, the L2ToL1MessagePasser contract takes a message, hashes it, and stores it in a mapping.

Linea

[docs] Linea uses a custom merkle tree of messages which is then provided as an input during settlement and verified as part of the validity proof. On the L2 side, an MessageSent event from the L2->L1 message.

Taiko

[docs] Taiko uses the same mechanism as L1->L2 messaging with a SignalService. The protocol is general enough to support both providing proofs againt a contract storage root or against a state root, by also providing an account proof.

Orbit stack

WIP.

Proposed design

At this point it's not clear whether it is possible to easily expose a custom data structure from L2 to L1. The EXECUTE precompile naturally exposes the state root, and the block_output can also expose the receipts_trie in some form, for example by exposing its root.

In principle, EIP-7685: General purpose execution layer requests could be used, but this requires overloading its semantic from EL->CL to L2->L1 requests, and adding a new type of request that also "pollutes" the L1 execution environment.

On the other hand, it is expected that statelessness will help in reducing the cost of providing inclusion proofs directly against a state root, which might remove the need to provide a shallower interface.