diff --git a/next.config.mjs b/next.config.mjs index 9f1975d6c..87c4fc034 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -9,7 +9,7 @@ const withNextra = nextra({ remarkPlugins: [ remarkCodeImport, ] - } + }, }) export default { @@ -17,4 +17,16 @@ export default { eslint: { ignoreDuringBuilds: true, }, + redirects: async () => [ + { + source: '/stack/interop/architecture', + destination: '/stack/interop/explainer#interoperability-architecture', + permanent: false, + }, + { + source: '/stack/interop/cross-chain-message', + destination: '/stack/interop/explainer#how-messages-get-from-one-chain-to-the-other', + permanent: false, + }, + ], } diff --git a/pages/stack/interop/_meta.json b/pages/stack/interop/_meta.json index 469dc5cda..47dd45d5f 100644 --- a/pages/stack/interop/_meta.json +++ b/pages/stack/interop/_meta.json @@ -1,10 +1,10 @@ { "explainer": "Interop explainer", - "architecture": "Architecture", + "predeploy": "Interop predeploys", "devnet": "Interop devnet", "supersim": "Supersim Multichain Development Environment", - "cross-chain-message": "Anatomy of cross-chain message", "message-passing": "Interop message passing", "op-supervisor": "OP Supervisor", - "assets": "Assets" -} \ No newline at end of file + "assets": "Assets", + "security": "Cross-chain security" +} diff --git a/pages/stack/interop/architecture.mdx b/pages/stack/interop/architecture.mdx deleted file mode 100644 index c7ce7da45..000000000 --- a/pages/stack/interop/architecture.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: Interoperability architecture -lang: en-US -description: How it works. ---- - -import { Callout } from 'nextra/components' -import Image from 'next/image' - -import { InteropCallout } from '@/components/WipCallout' - - - -# Interoperability architecture - -An OP Stack node consists of two pieces of software: a consensus client (e.g. op-node) and an execution client, which is responsible for processing user transactions and constructing blocks. Interoperability among OP Stack chains is enabled via a new service called -[*OP Supervisor*](/stack/interop/op-supervisor). Every node operator is expected to run this service in addition to the [rollup node](/builders/node-operators/architecture#rollup-node) and [execution client](/builders/node-operators/architecture#execution-client). - -```mermaid - -graph LR - - classDef chain fill:#FFE - classDef transparent fill:none, stroke:none - - subgraph chain1[OP Stack chain #1] - node1[OP Node] - super1[OP-Supervisor] - geth1[Execution Engine] - node1<-->super1<-->geth1<-->node1 - end - subgraph X[ ] - chain2[OP Stack chain #2] - chain3[OP Stack chain #3] - l1node[L1 Consensus Layer] - end - - chain2-->|log events|super1 - chain3-->|log events|super1 - l1node-->|block status|super1 - - class chain1,chain2,chain3 chain - class X transparent -``` - -OP-Supervisor holds a database of all the log events of all the chains in the interoperability cluster. -Every event can potentially initiate a cross domain message, and it is the job of OP-Supervisor to validate that the log event really happened on the source chain. -Additionally, OP-Supervisor reads information from L1's consensus layer to determine the transaction safety of L2 blocks. - -## How messages get from one chain to the other - -To understand *why* we need this additional service, it is useful to know how interop messages get from one blockchain to another. - -```mermaid - -sequenceDiagram - participant app as Application - participant src as Source Chain - box rgba(0,0,0,0.1) Destination Chain - participant dst-sup as OP-Supervisor - participant dst-geth as Execution Engine - end - app->>src: Transaction - src->>dst-sup: Log Event - note over src,dst-sup: Log Event = Initializing Message - app->>dst-geth: Transaction - dst-geth->>dst-geth: Call to CrossL2Inbox to execute or verify a message. - dst-geth->>dst-sup: Did you receive this initiating message? - dst-sup->>dst-geth: Yes - note left of dst-geth: Call is successful - dst-geth->>dst-geth: CrossL2Inbox emits ExecutingMessage. - note over dst-geth: Executing Message -``` - -Cross domain messages require two transactions. -The first transaction creates an *initiating message* on the source chain. -The second transaction creates an *executing message* on the destination chain. -This executing message could result in a contract function being executed on the destination chain. - -The initiating message is simply a log event. -Any log event on any chain that interoperates with the destination can initiate a cross domain message. - -The transaction that receives the message on the destination chain calls a contract called [`CrossL2Inbox`](https://specs.optimism.io/interop/predeploys.html#crossl2inbox). -This call can be at the top level, directly from the externally owned account, or come through a smart contract. -The call to `CrossL2Inbox`, also known as the *executing message*, needs to [identify the initiating message uniquely](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L35-L42), using the chain ID of the source chain, the block number, and the index of the log event within that block, as well as a few other fields as a sanity check. - -`CrossL2Inbox` can either [validate the message exists](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L171-L185), or [call a contract if the message exists](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L171-L185). - -[For more information, see the cross-chain messages anatomy page](./cross-chain-message). - -## Safety levels - -```mermaid - -flowchart LR - classDef finalized fill:#CCC - classDef safe fill:#8F8 - classDef unsafe fill:#F89 - subgraph I[Blocks with Initiating Messages] - style I fill:none - subgraph A[Chain A] - A0[Block n] - A1[Block n+100] - A2[Block n+105] - class A0 finalized - class A1 safe - class A2 unsafe - end - subgraph B[Chain B] - B0[Block m] - B1[Block m+3] - class B0,B1 safe - end - end - subgraph C[Chain C] - C0[Block with executing messages] - class C0 unsafe - end - A0 --> C0 - A1 --> C0 - A2 --> C0 - B0 --> C0 - B1 --> C0 -``` - -Interop expands the scope of trust for unsafe blocks, blocks that are shared through [the gossip protocol](/builders/chain-operators/architecture#sequencer). -To trust that an unsafe block is valid and is going to become safe and then finalized, you need to trust not only the sequencer that produces it, but also all the other sequencers that produce other blocks that are still unsafe, but that include initiating messages that are executed in that block. - -However, this is only for *unsafe* blocks, and only if the sequencer allows messages from unsafe blocks to be processed. -A block is only considered promotable to *safe*, and therefore ready to be written to L1, when all the blocks on which it depends are safe. - -For example, in the image below, most blocks are safe. -Block `n` in chain `A` is even finalized, and immune from reorgs. -However, block `n+105` in chain `A` is unsafe, it (or a block on which it depends) is not written to L1. -Because the new block depends upon it, it is also unsafe. - -## Next steps - -* Want to learn more? - Read our guide on the anatomy of a [cross-chain message](./cross-chain-message) or check out this - [interop design video walk-thru](https://www.youtube.com/watch?v=FKc5RgjtGes). -* Ready to get started? Use [Supersim](./supersim), a local dev environment that simulates interop for testing applications against a local version of the Superchain. -* For more info about how OP Stack interoperability works under the hood, - [check out the specs](https://specs.optimism.io/interop/overview.html). diff --git a/pages/stack/interop/cross-chain-message.mdx b/pages/stack/interop/cross-chain-message.mdx deleted file mode 100644 index 509c618f0..000000000 --- a/pages/stack/interop/cross-chain-message.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Anatomy of a cross-chain message -lang: en-US -description: Learn how cross-chain messaging works with OP Stack interoperability. ---- - -import { Callout } from 'nextra/components' -import Image from 'next/image' - -# Anatomy of a cross-chain message - -A cross-chain message refers to any communication sent using Superchain interop. This includes messages sent between different chains within an interop cluster, as well as messages sent on a single chain for interoperable. This functionality enables asset transfers that utilize the [SuperchainERC20](superchain-erc20) token standard. - -## How it works - -To send a cross-chain message on the Superchain using [Superchain interoperability](explainer), these two aspects must be in place: - -1. Each interoperable chain runs a verifying node for each chain in the interoperable set. -2. Each cross-chain message has an **initiating transaction** on the source chain and a **finalizing transaction** on the destination chain. - * **First/initiating transaction:** is submitted to the source chain and emits an event that can be consumed on a destination chain. - * **Second/finalizing transaction:** is submitted to a destination chain, where the block builder should only include it if certain that the first transaction was included in the source chain. The block builder can use OP-Supervisor to determine the integrity of the initiating message. Anyone can submit the second transaction. - - There is no strict requirement that the executing message is ever submitted. See the specs for details on tracing the [executing message event](https://specs.optimism.io/interop/predeploys.html#executingmessage-event). - - -
- -Anatomy of Cross-Chain Message with Interop - -In the example above, `0x123` sends 1 OP from OP Mainnet to Base, but this applies to any asset using the SuperchainERC20 token standard. - -## Next steps - -* More questions? Check out the FAQ section in the [Superchain Interop Explainer](explainer#faqs) or check out this [Superchain interop design video walk-thru](https://www.youtube.com/watch?v=FKc5RgjtGes). -* Ready to get started? Use [Supersim](supersim), a local dev environment that simulates Superchain interop for testing applications against a local version of the Superchain. -* For more info about how Superchain interoperability works under the hood, [check out the specs](https://specs.optimism.io/interop/overview.html). diff --git a/pages/stack/interop/explainer.mdx b/pages/stack/interop/explainer.mdx index f1e7522f0..4de32d7fd 100644 --- a/pages/stack/interop/explainer.mdx +++ b/pages/stack/interop/explainer.mdx @@ -13,120 +13,224 @@ import { InteropCallout } from '@/components/WipCallout' # Interoperability explainer -The Oracle problem states that a blockchain can only be certain about information generated by that chain. But what about information that happens outside that blockchain, how do you verify what happens somewhere else? - -Interoperability is the ability for a blockchain to securely read the state of another blockchain. -Native OP Stack interoperability provides the ability to read messages and transfer assets across chains in the Superchain (without having to go through L1) via low-latency, secure message passing. This results in the following benefits: -* 1-block latency asset movement that is both maximally capital efficient and non-fragmenting -* improved user experience for developers on the Superchain -* secure transfer of ETH and ERC-20s across L2s -* horizontally scalable applications - -In a practical sense, this allows users to securely and easily move ETH and tokens from one OP Stack chain to another by leveraging OP governed blockspace security. -## Secure message passing -Superchain interop includes both the protocol layer message passing and the Superchain ERC20 token specification. - -* **Message passing protocol:** the initial + finalizing/executing [message](cross-chain-message) that fire events to be consumed by the chains in the [dependency set](https://specs.optimism.io/interop/dependency-set.html) -* **SuperchainERC20 token specification**: the [SuperchainERC20](superchain-erc20) turns message passing into asset transfer between chains in the interop set. Learn more about how the SuperchainERC20 token standard enables asset interoperability in the Superchain [here](/stack/interop/assets/superchain-erc20) - -This means ETH and ERC-20s can seamlessly and securely move across L2s, and intent-based protocols (i.e., bridges) can build better experiences on top of the message passing protocol. - -## Low latency -Interoperability allows for horizontally scalable blockchains, a key feature of the Superchain. With Superchain interop, latency can be 1-block (~2 seconds) by optimistically accepting cross-chain messages. +## Why do we need interoperability? + +It is easy for a blockchain to be certain about information it generates itself. +Information that comes from other sources is harder to provide in a safe, decentralized, and uncensorable manner (this is called [The Oracle Problem](https://chain.link/education-hub/oracle-problem)). +The next major scalability improvement to the OP Stack is to enable a network of chains to feel like a single blockchain. +This goal requires low-latency, seamless message passing and asset bridging. + +*Interoperability* is a set of protocols and services that lets OP Stack blockchains read each others' state. +Interoperability provides the following benefits: + +- 1-block latency asset movement, removing the problem of capital fragmentation leading to better capital efficiency. +- Improved experience for both users and developers. +- Secure transfer of assets, such as ETH and ERC-20 tokens, across L2s. +- Horizontal scalability for applications that need it. + +## Interoperability architecture + +A pre-interop OP Stack node consists of two pieces of software: a consensus client (e.g. op-node) and an execution client, which is responsible for processing user transactions and constructing blocks (e.g. op-geth). +Interoperability among OP Stack chains is enabled via a new service called [*OP Supervisor*](/stack/interop/op-supervisor). +Every node operator is expected to run this service in addition to the [rollup node](/builders/node-operators/architecture#rollup-node) and [execution client](/builders/node-operators/architecture#execution-client). + +```mermaid + +graph LR + + classDef chain fill:#FFE + classDef transparent fill:none, stroke:none + + subgraph chain1[OP Stack chain #1] + node1[OP Node] + super1[OP-Supervisor] + geth1[Execution Engine] + node1<-->super1<-->geth1<-->node1 + end + subgraph X[ ] + chain2[OP Stack chain #2] + chain3[OP Stack chain #3] + l1node[L1 Consensus Layer] + end + + chain2-->|log events|super1 + chain3-->|log events|super1 + l1node-->|block status|super1 + + class chain1,chain2,chain3 chain + class X transparent +``` + +OP-Supervisor holds a database of all the log events of all the chains in the interoperability cluster. +Every event can potentially initiate a cross-domain message, and it is the job of OP-Supervisor to validate that the log event really happened on the source chain. +Additionally, OP-Supervisor reads information from L1's consensus layer to determine the transaction safety of L2 blocks. + +## How messages get from one chain to the other + +To understand *why* we need this additional service, it is useful to know how interop messages get from one OP Stack chain to another. + +```mermaid + +sequenceDiagram + participant app as Application + participant src as Source Chain + box rgba(0,0,0,0.1) Destination Chain + participant dst-sup as OP-Supervisor + participant dst-geth as Execution Engine + end + app->>src: Transaction + src->>dst-sup: Log Event + note over src,dst-sup: Log Event = Initializing Message + app->>dst-geth: Transaction + dst-geth->>dst-geth: Call to CrossL2Inbox to execute or verify a message. + dst-geth->>dst-sup: Did you receive this initiating message? + dst-sup->>dst-geth: Yes + note left of dst-geth: Call is successful + dst-geth->>dst-geth: CrossL2Inbox emits ExecutingMessage. + note over dst-geth: Executing Message +``` + +Cross-domain messages require two transactions. +The first transaction creates an *initiating message* on the source chain. +The second transaction creates an *executing message* on the destination chain. +This executing message could result in a contract function being executed on the destination chain. + +The initiating message is simply a log event. +Any log event on any chain that inteoperates with the destination can initiate a cross-domain message. + +The transaction that receives the message on the destination chain calls a contract called [`CrossL2Inbox`](https://specs.optimism.io/interop/predeploys.html#crossl2inbox). +This call can be at the top level, directly from the externally owned account, or come through a smart contract. +The call to `CrossL2Inbox`, also known as the *executing message*, needs to [identify the initiating message uniquely](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L35-L42), using the chain ID of the source chain, the block number, and the index of the log event within that block, as well as a few other fields as a sanity check. + +`CrossL2Inbox` can either [validate the message exists](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L171-L185), or [call a contract if the message exists](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L171-L185). + +[For more information, see the cross-chain messages anatomy page](./cross-chain-message). + +## Block safety levels + +```mermaid + +flowchart LR + classDef finalized fill:#CCC + classDef safe fill:#8F8 + classDef unsafe fill:#F89 + subgraph I[Blocks with Initiating Messages] + style I fill:none + subgraph A[Chain A] + A0[Block n] + A1[Block n+100] + A2[Block n+105] + class A0 finalized + class A1 safe + class A2 unsafe + end + subgraph B[Chain B] + B0[Block m] + B1[Block m+3] + class B0,B1 safe + end + end + subgraph C[Chain C] + C0[Block with executing messages] + class C0 unsafe + end + A0 --> C0 + A1 --> C0 + A2 --> C0 + B0 --> C0 + B1 --> C0 +``` + +Interop expands the scope of trust for unsafe blocks (blocks that are shared through [the gossip protocol](/builders/chain-operators/architecture#sequencer)). +If a sequencer chooses to accept unsafe messages, the sequencer must trust the sequencer that produces the inbound message as well as any referenced unsafe messages produced from sequencers in the transitive dependency set. + +
+ +What is the transitive dependency set? + +The transitive dependency set of a blockchain is all the chains on which it depends, and all the chains that depend on them, and so on. +For example, in the illustration above, the dependency set of chain A is just chain B. +However, the *transitive* dependency set includes chain B, the chains that depend on it (C and D) and the chains that depend on them (E). +If there was a chain that depended on E, that chain would be part of the transitive dependency set too. + +```mermaid + +flowchart LR + A[Chain A] <--> B[Chain B] + B <--> C[Chain C] + B <--> D[Chain D] + D <--> E[Chain E] + F[Chain F] <--> G[Chain G] +``` + +For example, there could be a block in chain D that depends on an initiating message in chain E> +If the block with that initiating message is still unsafe (not written to L1), then the block in chain D is also usafe, even if it has been written to L1. +As a result, a block in chain B that depends on the chain D block can also be unsafe, as can a block in chain A that depends on the block in chain B. + +
+ +Notably this trust assumption is only for *unsafe* blocks, and *only* if the sequencer allows messages from unsafe blocks to be processed. + +In interop, [the traditional safe level](https://docs.optimism.io/stack/transactions/transaction-finality#steps-to-finality) of is divided into two types of safety. +A block is *local safe* once it is written to L1. +But it is only *cross safe* when in addition to the block itself all of the blocks on which it depends (directly or indirectly) are written to L1, including the dependencies of previous blocks in the same chain. + +For example, in the image above, most blocks are safe. +Block `n` in chain `A` is even finalized, and immune from reorgs. +However, block `n+105` in chain `A` is unsafe, it (or a block on which it depends) is not written to L1. +Because the new block depends upon it, it can be either unsafe or local safe, but it cannot be cross safe. ## Interop clusters -The interop protocol works via a dependency set which is configured on a per-chain basis. The dependency set defines the set of chains that a chain will accept incoming messages from. - -This gives the OP Stack an unopinionated and flexible foundation, so chain operators can choose which chains their chains depend on, and it is not a requirement that chains are in each other's dependency set. - -## Superchain interop cluster -The Superchain builds on top of the interop protocol and implements a single mesh network with complete dependencies. In this model, each blockchain in the Superchain interop cluster would have direct connections to every other blockchain, creating a fully connected mesh network. Compared to a hub and spoke model, this provides the highest level of interoperability, as any blockchain can transact directly with any other. - -Each blockchain in the Superchain interop cluster shares the same security model to mitigate the weakest-link scenario. As outlined in the [Standard Rollup Charter](https://gov.optimism.io/t/season-6-standard-rollup-charter-ratification/8135#p-36758-governing-policies-11), these chains share the same L1 `ProxyAdmin` Owner. Any changes to the Superchain interop cluster must follow the standard Protocol Upgrade vote procedure—the established governance process for Superchain modifications. - - -## New predeploys - -The following predeploys have been added to enable interoperability. Predeployed smart contracts exist at predetermined addresses in the genesis state. They are similar to precompiles but instead run directly in the EVM instead of running native code outside the EVM. - -### CrossL2Inbox -The `CrossL2Inbox` is the system predeploy for cross chain messaging. Anyone can trigger the execution or validation of cross chain messages, on behalf of any user. +The interop protocol works via a dependency set which is configured on a per-chain basis. +The dependency set defines the set of chains that can send and receive messages with a specific chain. -* **Address:** `0x4200000000000000000000000000000000000022` -* **Specs:** [CrossL2Inbox](https://specs.optimism.io/interop/predeploys.html#crossl2inbox) +```mermaid -### L2ToL2CrossDomainMessenger +flowchart LR + A[Chain A] <--> B[Chain B] + A[Chain A] <--> C[Chain C] + A[Chain A] <--> D[Chain D] + A[Chain A] <--> E[Chain E] + B <--> C + D <--> E -The `L2ToL2CrossDomainMessenger` is a higher level abstraction on top of the `CrossL2Inbox` that provides general message passing, utilized for secure transfers ERC20 tokens between L2 chains. Messages sent through the `L2ToL2CrossDomainMessenger` on the source chain receive both replay protection and domain binding, ie the executing transaction can only be valid on a single chain. +``` -* **Address:** `0x4200000000000000000000000000000000000023` -* **Specs:** [L2ToL2CrossDomainMessenger](https://specs.optimism.io/interop/predeploys.html#l2tol2crossdomainmessenger) +For example, in the illustration above, the dependency set of chain B is chains A and C. +To move an asset from chain E to chain B, it is necessary to move the asset from chain E to chain A, and then from chain A to chain C, because there is no direct dependency between B and E. -### OptimismSuperchainERC20Factory +### Superchain interop cluster -The `OptimismSuperchainERC20Factory` creates ERC20 contracts that implement the SuperchainERC20 standard, grants mint-burn rights to the `L2StandardBridge` (`OptimismSuperchainERC20`), and includes a remoteToken variable. These ERC20s are called `OptimismSuperchainERC20` and can be converted back and forth with `OptimismMintableERC20` tokens. The goal of the `OptimismSuperchainERC20` is to extend functionalities of the `OptimismMintableERC20` so that they are interop compatible. +The Superchain builds on top of the interop protocol and implements a single mesh network with complete dependencies. +In this model, each blockchain in the Superchain interop cluster would have direct connections to every other blockchain, creating a fully connected mesh network. +This model provides the highest level of interoperability, as any blockchain can transact directly with any other. -* **Address:** `0x4200000000000000000000000000000000000026` -* **Specs:** [OptimismSuperchainERC20Factory](https://specs.optimism.io/interop/predeploys.html#optimismsuperchainerc20factory) +```mermaid +flowchart LR + A[Chain A] <--> B[Chain B] <--> C[Chain C] <--> D[Chain D] <--> E[Chain E] <--> A + A <--> C <--> E <--> B <--> D <--> A +``` -### BeaconContract -The `BeaconContract` predeploy gets called by the `OptimismSuperchainERC20` BeaconProxies deployed by the SuperchainERC20Factory. The Beacon Contract implements the interface defined in [EIP-1967](https://eips.ethereum.org/EIPS/eip-1967). +Each blockchain in the Superchain interop cluster shares the same security model to mitigate the weakest-link scenario. As outlined in the [Standard Rollup Charter](https://gov.optimism.io/t/season-6-standard-rollup-charter-ratification/8135#p-36758-governing-policies-11), these chains share the same L1 `ProxyAdmin` Owner. Any changes to the Superchain interop cluster must follow the standard Protocol Upgrade vote procedure—the established governance process for Superchain modifications. -* **Address:** `0x4200000000000000000000000000000000000027` -* **Specs:** [BeaconContract](https://specs.optimism.io/interop/predeploys.html#beaconcontract) -### SuperchainERC20Bridge +{/* +## Interop assets -The `SuperchainERC20Bridge` is an abstraction on top of the `L2toL2CrossDomainMessenger` that facilitates token bridging using interop. It has mint and burn rights over `SuperchainERC20` tokens, as described in the [token bridging spec](https://specs.optimism.io/interop/token-bridging.html). +Superchain interop includes both the protocol layer message passing and the Superchain ERC20 token specification. -* **Address:** `0x4200000000000000000000000000000000000028` -* **Specs:** [SuperchainERC20Bridge](https://specs.optimism.io/interop/predeploys.html#superchainerc20bridge) -## Considerations -Chain operators will need to run additional infrastructure to be part of the interoperable set. -* The Superchain-backend service, [`op-supervisor`](op-supervisor), will be a requirement for running an OP Stack chain that has interop enabled. -`op-supervisor` is responsible for validating all cross-chain messages and will need to have an RPC configured for each chain in the dependency set. -* In the future, to reduce infrastructure costs, `op-supervisor` will rely on the P2P network and cryptographic schemes for validating cross-chain messages. +* **Message passing protocol:** the initial + finalizing/executing [message](cross-chain-message) that fire events to be consumed by the chains in the [dependency set](https://specs.optimism.io/interop/dependency-set.html) +* ****: the [SuperchainERC20](superchain-erc20) turns message passing into asset transfer between chains in the interop set. Learn more about how the SuperchainERC20 token standard enables asset interoperability in the Superchain [here](/stack/interop/assets/superchain-erc20) - -For additional considerations, join the [Interop discussion](https://github.com/ethereum-optimism/specs/discussions/128) in our specs repo. - +This means ETH and ERC-20s can seamlessly and securely move across L2s, and intent-based protocols (i.e., bridges) can build better experiences on top of the message passing protocol. +*/} ## Next steps -* Want to learn more? Read our guide on the anatomy of a [cross-chain message](cross-chain-message) or check out this [interop design video walk-thru](https://www.youtube.com/watch?v=FKc5RgjtGes). -* Ready to get started? Use [Supersim](supersim), a local dev environment that simulates interop for testing applications against a local version of the Superchain. -* For more info about how OP Stack interoperability works under the hood, [check out the specs](https://specs.optimism.io/interop/overview.html). - -## FAQs - -### What is the latency/security tradeoff? -If a sequencer does not want to trust another sequencer at all, they can choose to only accept executing messages where the initiating message has been finalized with L1 levels of security. This demonstrates the difference in latency vs speed. The L2 data must be submitted to L1 and then the L1 block containing the transaction with the L2 data must be finalized. It takes about 15 minutes for an L1 block to finalize, and higher throughput OP Stack chains like Base and OP Mainnet submit a batch about every 5 minutes. This means that it could take about 20 minutes for an L2 transaction to be considered final and be able to be trustlessly consumed by another chain. At lower latencies, the sequencer accepting the executing message takes on some amount of equivocation risk. It could be possible to build a bonding system to add economic security to prevent equivocation, but that is not in the scope of the first release. - -See this [dune dashboard](https://dune.com/oplabspbc/op-stack-chains-l1-activity#submission-frequency) to see how often OP Stack chains submit batches. - -
- -Safe and Unsafe Security Diagram - -### What is stopping a sequencer from censoring a cross-chain message? -There is nothing stopping a sequencer from censoring a transaction when it is sent directly to the sequencer. This does not mean the network has no censorship resistance, users can always send a deposit transaction for censorship resistance as strong as L1 guarantees. The tradeoff here is the latency, instead of being confirmed in ~2 seconds, the transaction can be confirmed at the rate of L1 block production. It may be possible to adopt something like [EIP-7547](https://eips.ethereum.org/EIPS/eip-7547) in the future to enable low latency censorship resistance. - -### What is the weakest link scenario? -Without shared security, there is a risk that interacting chains could enter a conflicting state due to cross-chain interactions. If a weaker chain in the network is attacked or experiences a reorganization, it could change its state independently. This would leave the entire interop cluster in an inconsistent state, as the security of interactions across chains is only as strong as the weakest chain. - -### Are callback style transactions possible? -If two blocks are being built at the same time with shared knowledge of their contents, it is possible to build blocks where a transaction calls to another chain, does compute and then a transaction calls back with the results. This requires no protocol level changes, it just requires more sophisticated block builder infrastructure. - -### What is stopping a shared sequencer from including just the executing message and not the initiating message? -The protocol enforces the fact that all executing messages are valid. It does this by reorganizing out executing messages that have invalid initiating messages. Running software that does not enforce this would be non-standard behavior and would leave yourself at risk of accepting an invalid executing message and therefore running on a forked chain. - -### What is the trust/verification model? Do sequencers that opt into this interop system have to trust each other fully? -Sequencers only have to trust each other, if they are accepting executing messages where the initiating message is unsafe. This is because the sequencer's ability to equivocate on unsafe data, i.e., batch submit something different from what they gossip over the p2p network. Once data is submitted to L1, it is considered final relative to the L2 and therefore there is no longer an equivocation risk. - -### Is interop different between chains with non-fungible blockspace? -Chains that have non-fungible blockspace are chains that have different features - it could be that they use Plasma for data availability, a custom gas paying token or have a large execution gas limit. As long as the chain can be fault proven, it can work with Superchain interoperability. At the application layer, it is important for chains to have legibility into the type of chain that the message originated from. This ensures that applications do not accept messages from chains they consider not secure enough. See this [discussion](https://github.com/ethereum-optimism/specs/issues/121) for additional thoughts. +* Want to learn more? Read our guide on the anatomy of a [cross-chain message](cross-chain-message) or check out this [interop design video walk-thru](https://www.youtube.com/watch?v=FKc5RgjtGes). +* Ready to get started? Use [Supersim](supersim), a local dev environment that simulates interop for testing applications against a local version of the Superchain. +* For more info about how OP Stack interoperability works under the hood, [check out the specs](https://specs.optimism.io/interop/overview.html). -When it comes to chains that have different gas limits that are interoperable, it creates a set of transactions that can execute on one chain but not the other. This happens when the transaction consumes more than the gas limit of the smaller chain but less than of the bigger chain. At 2024 usages levels, these sorts of transactions are very rare. In the future, it may be the case that these transactions become more common, it will be up to the chain operators to ensure quality of service for their users. diff --git a/pages/stack/interop/predeploy.mdx b/pages/stack/interop/predeploy.mdx new file mode 100644 index 000000000..d89f3b4ee --- /dev/null +++ b/pages/stack/interop/predeploy.mdx @@ -0,0 +1,65 @@ +--- +title: Interoperability predeploys +lang: en-US +description: How it works. +--- + +import { Callout } from 'nextra/components' +import Image from 'next/image' + +import { InteropCallout } from '@/components/WipCallout' + + + +# Interoperability predeploys + +The following predeploys have been added to enable interoperability. +*Predeployed smart contracts* exist at predetermined addresses, coming from the genesis state. +They're similar to [precompiles](https://www.evm.codes/precompiled) but run directly in the EVM instead of running as native code. + +## CrossL2Inbox + +The `CrossL2Inbox` is the system predeploy for cross chain messaging. +Anyone can trigger the execution or validation of cross chain messages, on behalf of any user. + +- **Address:** `0x4200000000000000000000000000000000000022` +- **Specs:** [`CrossL2Inbox`](https://specs.optimism.io/interop/predeploys.html#crossl2inbox) +- **Source code:** [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) + +## L2ToL2CrossDomainMessenger + +The `L2ToL2CrossDomainMessenger` is a higher level abstraction on top of the `CrossL2Inbox` that provides general message passing. +It's utilized for secure ERC20 token transfers between L2 chains. +Messages sent through the `L2ToL2CrossDomainMessenger` on the source chain receive both replay protection and domain binding (the executing transaction can only be valid on a single chain). + +- **Address:** `0x4200000000000000000000000000000000000023` +- **Specs:** [`L2ToL2CrossDomainMessenger`](https://specs.optimism.io/interop/predeploys.html#l2tol2crossdomainmessenger) +- **Source code:** [`L2ToL2CrossDomainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) + +{/* +## OptimismSuperchainERC20Factory + +`OptimismSuperchainERC20Factory` creates ERC20 contracts that implement the SuperchainERC20 standard, grants mint-burn rights to the `L2StandardBridge`, and includes a remoteToken variable. These ERC20s are called `OptimismSuperchainERC20` and can be converted back and forth with `OptimismMintableERC20` tokens. The goal of the `OptimismSuperchainERC20` is to extend functionalities of the `OptimismMintableERC20` so that they are interop compatible. + +- **Address:** `0x4200000000000000000000000000000000000026` +- **Specs:** [`OptimismSuperchainERC20Factory`](https://specs.optimism.io/interop/predeploys.html#optimismsuperchainerc20factory) +- **Source code:** [`OptimismSuperchainERC20Factory`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol) + +## OptimismSuperchainERC20Beacon + +To enable upgrades, `OptimismSuperchainERC20` contracts use [the `BeaconProxy` pattern](https://docs.openzeppelin.com/contracts/3.x/api/proxy#beacon). +This contract is the `Beacon` part, which provides the implementation address for those proxies. + +- **Address:** `0x4200000000000000000000000000000000000027` +- **Specs:** [`OptimismSuperchainERC20Beacon`](https://specs.optimism.io/interop/predeploys.html#beaconcontract) +- **Source code:** [`OptimismSuperchainERC20Beacon`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol) + +*/} + +## SuperchainTokenBridge + +The `SuperchainTokenBridge` is an abstraction on top of the `L2toL2CrossDomainMessenger` that facilitates token bridging using interop. It has mint and burn rights over `OptimismSuperchainERC20` tokens, as described in the [token bridging spec](https://specs.optimism.io/interop/token-bridging.html). + +- **Address:** `0x4200000000000000000000000000000000000028` +- **Specs:** [`SuperchainTokenBridge`](https://specs.optimism.io/interop/predeploys.html#superchainerc20bridge) +- **Source code:** [`SuperchainTokenBridge`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/SuperchainTokenBridge.sol) diff --git a/pages/stack/interop/security.mdx b/pages/stack/interop/security.mdx new file mode 100644 index 000000000..7dec4e67a --- /dev/null +++ b/pages/stack/interop/security.mdx @@ -0,0 +1,149 @@ +--- +title: Cross-chain security +lang: en-US +description: Security measures for safe interoperability +--- + +import { Callout } from 'nextra/components' +import Image from 'next/image' + +import { InteropCallout } from '@/components/WipCallout' + + + +# Security considerations + +## The trust model + +This interop vulnerability arises when an initiating message seems to exist, prompting the processing of the executing message. However, the initiating message ends up not actually appear in the canonical chain. +Excluding L1 reorgs, this can happen in two ways: + +- *Equivocation*. A sequencer publishes a block using the gossip protocol that is different from the one that eventually gets written to L1. + The problem happens when the gossip protocol block includes a log entry that is used as an initiating message, but the real block (the one written to L1) doesn't. + The way this is handled is that a block that depends on an unsafe block is, itself, unsafe. + It does not get treated as safe until all the blocks on which it depends (directly or indirectly) are also written to L1. + +- *Faulty information*. The sequencer operator can run a verifier node for every chain in the dependency set, in which case it can deduce the initiating messages from the safe transactions of every chain. + To save on resources, the sequencer can choose to query existing nodes of the source blockchain. + In that case, if the information provided to sequencer is incorrect, of course the blocks posted by the sequencer will be also incorrect. + + In this case, invalid blocks will be replaced with deposit only blocks by other verifiers. + +
+ + What are deposit only blocks? + + Normally the blocks that make it to the canonical blockchain are those posted to L1 by the sequencer. + However, when those blocks are missing or invalid (for example because they rely on an initiating message that is missing), they're replaced by *deposit only blocks*, blocks whose content can be calculated from L1 without relying on the sequencer. + + The way this works is that there are two types of user transactions in an OP Stack block: + + - Sequencer transactions, which go through the sequencer. + These transactions are extremely cheap, but in theory a sequencer could censor them. + - Deposit transactions, which users submit through L1. + These transactions have the cost of an L1 transaction, which is a lot higher, but they cannot be censored by the sequencer. + + A deposit only block only contains the deposit transactions and some internal transactions, not the sequencer transactions. + + For more information about this process, [see the technical specifications](https://specs.optimism.io/protocol/derivation.html#deriving-the-transaction-list). + +
+ + +## The latency/security tradeoff + +The initiating message comes from a block on a different blockchain. +If we accept initiating messages as soon as the block is available through the gossip protocol, we have minimal latency but at a security cost (because the source sequencer can send incorrect information through gossip). +Alternatively, we can wait until the source sequencer posts the block to L1. +In that case we can be more certain that the block is correct, but at the cost of higher latency. + +There are three different possibilities, at different levels of latency and security. + +### Unsafe initiating messages + +L2 blocks start as unsafe, meaning that there's no L1 evidence for them, and the sequencer for that blockchain can send out incorrect information. +Sending out incorrect information, for example that a certain transaction is included in a block when it isn't, is called *equivocation*. +A sequencer that builds blocks with interop can choose to accept messages from unsafe blocks (received through the gossip protocol), for minimal latency. + +However, because of equivocation risk, a block that is written to L1 (*local safe*) can only be considered truly safe (the techincal term is *cross safe*), for itself and the previous blocks in its blockchain are also written to L1. + +```mermaid + +sequenceDiagram + actor app as User + participant src as Source Chain + participant dst as Destination Chain + participant l1 as Ethereum Mainnet + src->>dst: Block src_n will have transaction txn_0 that emits log event evt_0 + note over src,dst: Initiating message + app->>dst: Transaction txn_1: If you have evt_0, call contract C with the data in evt_0. + note over app,dst: Executing message + note left of dst: Block dst_m will
have the results of
calling contract C
with the data in evt_0. + break + note over app,l1: time passes + end + src->>l1: Write block src_n without txn_0 (so no evt_0) + l1->>dst: This is the safe block src_n + note left of dst: No evt_0, so block dst_m is incorrect
and so is every subsequent block.
All those blocks are replaced with
deposit only blocks. +``` + +### Safe initiating messages + +Alternatively, a sequencer can be configured to only accept executing messages once the initiating message is in a cross safe block. +A cross safe block is one that is written to L1, and whose dependecies (direct or indirect, including dependencies of previous blocks in the same chain) are all written to L1. + +When a block is cross safe, the source sequencer cannot equivocate, and the state will only need to be recalculated if there's an [L1 reorg](https://www.alchemy.com/overviews/what-is-a-reorg#what-happens-to-reorgs-after-the-merge). +The cost of this enhanced security that it would take longer for a message to pass from one blockchain to the other. +Higher throughput OP Stack chains like Base and OP Mainnet submit a batch about every 5 minutes, so on average it takes about 2.5 minutes for an initiating message to become safe. + +You can use [this dune dashboard](https://dune.com/oplabspbc/op-stack-chains-l1-activity#submission-frequency) to see how often OP Stack chains submit batches. + +```mermaid + +sequenceDiagram + actor app as User + participant src as Source Chain + participant dst as Destination Chain + participant l1 as Ethereum Mainnet + src->>dst: Block src_n will have transaction txn_0 that emits log event evt_0 + note over src,dst: Initiating message + app->>dst: Transaction txn_1: If you have evt_0, call contract C with the data in evt_0. + note over app,dst: Executing message + note over dst: Block src_n is not safe yet,
txn_1 fails + break + note over app,l1: time passes + end + src->>l1: Write block src_n with txn_0 + l1->>dst: This is the safe block src_n + app->>dst: Transaction txn_2: If you have evt_0, call contract C with the data in evt_0. + note over app,dst: Executing message + note over dst: Now I have evt_0,
so txn_2 is successful + +``` + +### Finalized initiating messages + +A sequencer can also be configured to reject all executing messages until the initiating message is *finalized*, meaning it's irrevocably on L1 and immune to reorgs. +Currently, this adds [about 15 minutes](https://ethereum.org/en/roadmap/single-slot-finality/) to the message latency. + +
+ +Safe and Unsafe Security Diagram + + + +Even if a sequencer accepts unsafe initiating messages, the blocks it constructs that rely on them are considered unsafe until the blocks with those initiating messages are written to L1 and become safe. + + + + +{/* +## What is stopping a sequencer from censoring a cross-chain message? +There is nothing stopping a sequencer from censoring a transaction when it is sent directly to the sequencer. This does not mean the network has no censorship resistance, users can always send a deposit transaction for censorship resistance as strong as L1 guarantees. The tradeoff here is the latency, instead of being confirmed in ~2 seconds, the transaction can be confirmed at the rate of L1 block production. It may be possible to adopt something like [EIP-7547](https://eips.ethereum.org/EIPS/eip-7547) in the future to enable low latency censorship resistance. + + + +## What is stopping a shared sequencer from including just the executing message and not the initiating message? +The protocol enforces the fact that all executing messages are valid. It does this by reorganizing out executing messages that have invalid initiating messages. Running software that does not enforce this would be non-standard behavior and would leave yourself at risk of accepting an invalid executing message and therefore running on a forked chain. + +*/} \ No newline at end of file