# Superchain Shared Sequencer V2 **TLDR;** Below is a short proposal for a simple shared-sequencer design that enables *synchronous cross-chain transactions* with a minimal diff to the current Optimism architecture. **Design Goals** * Enable seamless atomic mint/burn of assets within the superchain to enable a unified native asset layer for the Superchain * Minimal diff to the current Optimism architecture to reduce technical complexity ## Context Let $O_i$ and $B_i$ denote Optimism and Base transactions respectively. Currently, the Optimism and Base sequencer commit to an *ordering* of transactions: $$ S_O=[O_1, O_2, ..., O_N] \ \ \ \ \ S_B=[B_1, B_2, ..., B_M] $$ We want to enable *synchronous cross-chain transactions* between Optimism and Base. In other words, an arbitrary transaction $O_j \in S_O$ should have the power to conditionally include a transaction $B_j$ in $S_B$ if and only if $O_j$ succeeded. Specifically, it should satisfy the following properties: - If $O_j$ executes succesfully, $B_j$ gets included in $S_B$ - If $O_j$ reverts, $B_j$ does not get included in $S_B$ - $O_j$ and $B_j$ should happen at the same "time" Note that given an arbitrary transaction $O_j$, it is not possible to know whether the transaction will execute successfully or that it will attempt to emit a cross-chain transaction without execution. **Thus, we believe that it is not possible to enable *synchronous cross-chain communication* without some form of execution at the sequencer level** (Espresso and Astria do not execute transactions, so they only enable *atomic inclusion* of transactions). ## A simple shared sequencer design <!-- <center> <img src="https://i.imgur.com/nNSdzVy.png" alt= “” width="300px" height="value"> </center> --> ![](https://i.imgur.com/EptPOav.png) Here is a simple proposal for a shared sequencer that would enable *synchronous cross-chain transactions* between Optimism and Base, **under a shared trust model.** Instead of routing their transactions to the rollup-specific sequencer, users will send their transactions to the shared sequencer. Upon receiving a transaction $T_j$, the shared sequencer will: - Observe the chain id and sequence $T_j$ to be included in $S_O$ or $S_B$ respectively Upon receiving a shared transaction $SS(T_j)$, the shared sequencer will: - Observe the chain id and request an execution trace for $T_j$ on the respective chain - If the execution trace denotes that the transaction sucessfully executed and requested a cross-chain transaction $T_{j+1}$ to be included, the sequencer will include $T_{j+1}$ into the requested chain. ## How do we make sure the sequencer was not malicious? To ensure that the sequencer was not malicious, assume a few smart contracts have been implemented on-chain for sending these cross-chain transactions. On the sending chain: ```solidity contract Burn { uint256 nonce = 0; MerkleTree burns; function burn() payable { uint256 user = msg.sender uint256 value = msg.value; bytes32 msgHash = keccak256(user, value, nonce++); burns.insert(msgHash); } } ``` On the receiving chain: ```solidity contract Mint { uint256 nonce = 0; MerkleTree mints; function receive(address user, uint256 value) { bytes32 msgHash = keccak256(user, value, nonce++); mints.insert(msgHash) ... opETH.mint(user, value) ... } } ``` Note that we implement mint-and-burn for simplicity, but it could be generalized to arbitrary messaging. Then, for every batch posted on L1, it suffices to prove that the `mint` and `burn` Merkle trees have the same root. This can be done using a fraud proof which would require more latency, a ZK proof, or a simple Merkle proof. The design space here is open. - If the roots do not match, either the sequencer is posting fradulent state roots OR the sequencer failed to include a cross-chain transaction. - If the roots do match, but it's not supposed to, then the execution fraud proof system will catch the incorrectly executed transactions. - Note that a Base full node must now run a Optimism full node as well and vice-versa. Certain transactions on Base should only be included if a transaction successfully executed on Optimism. **This is the price you pay for atomic composability.** This design is very similar to the existing Optimism sequencer/fraud proof design, but adds 1 extra condition to validate when posting state roots. The fundamental difference between this architecture and other proposals for shared/decentralized sequencers is the following: **Our model:** * enables atomic composability across all chains that are being sequenced (i.e. mint/burn for native assets across all members of the superchain) * sequencer has to run execution as well as sequencing, but the execution is sharded across the different chains * superchain specific architecture **Other shared sequencing models (e.g., Espresso or Astria)** * Only allows for atomic transaction inclusion, but not conditional inclusion based on whether a tx executes succesfully * sequencer doesn't have to run execution (execution is done lazily after sequencing is posted to L1) ## Open questions - How to handle L1 exit - Mostly seems to work out of the box, but some edge cases need to be handled. - How to ensure they get included at the same "time" - If we're okay with "time" being at the batch level, the current design works - If we want more granularity, we may need to add a global tx index <!-- ## Can we make the sequencers not have to trust each other? In the current proposal, the sequencers operator under a shared trust model--is there a way to avoid this? Let's construct a hypothetical way to do shared sequencing and see how it falls apart if we want the sequencers to not trust each other. Let $O_j$ be a transaction that wants to include a cross-chain transaction $B_j$. The user can wrap the transaction into a shared sequencer transaction $\text{SS}(O_j)$ before sending it to the Optimism sequencer. For a given $\text{SS}(O_j)$ transaction, the Optimism sequencer will: - Execute $O_j$ and watch for an event being emitted from a contract, instructing that the transaction wants to include a transaction on Base. - The Optimism sequencer will sign a promise $P_{O}(O_j, B_j)$ "I promise to include $O_j$ in $S_O$ and that it succesfully requests a transaction $B_j$ upon execution" The Base sequencer will: - Verify the signature on the promise $P_O(O_j, B_j)$ and include transaction $B_j$ into $S_B$ However, the problem is that the Optimism sequencer needs a promise from the Base sequencer that it will include the transaction. In the malicious case, the Optimism sequencer could simply act as if the Base sequencer never sent the message, so **it is difficult to attribute the failure of the shared transaction to a single sequencer.** -->