From 3c1deaec5fafd70febc8cefd2e35d74dd7983edb Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 01:45:55 +0100 Subject: [PATCH 01/21] intial commit --- pages/stack/interop/_meta.json | 1 + pages/stack/interop/reading-logs.mdx | 193 +++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 pages/stack/interop/reading-logs.mdx diff --git a/pages/stack/interop/_meta.json b/pages/stack/interop/_meta.json index 2f9e36cbb..9a949b5e7 100644 --- a/pages/stack/interop/_meta.json +++ b/pages/stack/interop/_meta.json @@ -2,6 +2,7 @@ "explainer": "Superchain interop explainer", "predeploy": "Superchain interop predeploys", "message-passing": "Superchain interop message passing", + "reading-logs": "Superchain interop logs", "op-supervisor": "OP Supervisor", "superchain-weth": "Superchain ETH", "superchain-erc20": "SuperchainERC20", diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx new file mode 100644 index 000000000..0767e9220 --- /dev/null +++ b/pages/stack/interop/reading-logs.mdx @@ -0,0 +1,193 @@ +--- +title: Reading Logs in Superchain Interop +lang: en-US +description: Learn how to reference logs from one chain on another within the Superchain. +--- + +import { Callout } from 'nextra/components' +import { InteropCallout } from '@/components/WipCallout' + + + +# Reading logs in superchain interop + +Superchain interop enables developers to leverage current and historical logs from other blockchains within the Superchain interop cluster directly on their local chain. This feature allows for cross-chain log consumption with low latency in a trust-minimized way. + +## Overview + +While the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) enables sending messages across chains, the [`CrossL2Inbox#validateMessage`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L49) function allows smart contracts to verify and consume logs that were emitted on other chains within the Superchain ecosystem. + +This capability enables developers to: + +* Reference attestations or events from other chains +* Build cross-chain applications that react to events happening across the Superchain +* Create novel financial products that leverage data from multiple chains + +## Why use `CrossL2Inbox`? + +* **Lower latency**: Directly reference logs without waiting for cross-chain message confirmation. +* **Trust-minimized**: Uses cryptographic validation rather than relying on off-chain relayers. +* **Flexibility**: Can be used to validate events from another chain or even the same chain. + +## How it works + +### Architecture + +The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L33) contract, which serves as an oracle for logs from other chains in the Superchain: + +1. A smart contract on Chain A emits a log (event) +2. Your contract on Chain B calls `CrossL2Inbox#validateMessage` with the log's identifier +3. The `CrossL2Inbox` contract verifies the log's authenticity +4. Your contract can then use the validated log data + +### Key components + +* **Identifier**: A struct containing information about the log, including `chainId`, `origin` (contract address), and other log metadata +* **validateMessage**: Function that verifies a log's authenticity before allowing its use + +## Example: cross-chain attestation verification + +Let's walk through a practical example of verifying an Ethereum Attestation Service (EAS) attestation across chains. + +### Source chain: creating an attestation + +On the source chain (e.g., OP Mainnet), a user creates an attestation using EAS: + +```mermaid +sequenceDiagram + participant User + participant App as Application + participant EAS as EAS Contract + participant Log as Event Log + + User->>App: Request attestation + App->>EAS: createAttestation() + EAS->>Log: Emit AttestationCreated event + Note over Log: Event contains attestation data +``` + +### Destination chain: verifying the attestation + +On the destination chain (e.g., Base), a DeFi application wants to verify this attestation: + +```mermaid +sequenceDiagram + participant User + participant DeFi as DeFi Application + participant Verifier as AttestationVerifier + participant CrossL2 as CrossL2Inbox + participant OP as OP-Supervisor Node + + User->>DeFi: Request access using attestation + DeFi->>Verifier: verifyAttestation(id, attestationEvent) + Verifier->>CrossL2: validateMessage(id, keccak256(attestationEvent)) + CrossL2->>OP: Check if log exists + OP-->>CrossL2: Confirm log validity + CrossL2-->>Verifier: Return validation result + Verifier-->>DeFi: Return verification status + DeFi-->>User: Grant access based on attestation +``` + +### Sample code for attestation verification + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { ICrossL2Inbox, Identifier } from "interfaces/L2/ICrossL2Inbox.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +contract AttestationVerifier { + address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000014; + address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000EAS; // Example address + + // Event selector for AttestationCreated event + bytes32 constant ATTESTATION_CREATED_EVENT_SELECTOR = + 0x831531dabaca5375ba77364edc9627be5638660e8b613d921b86766021d3c165; // Example selector + + function verifyAttestation( + Identifier calldata _id, + bytes calldata _attestationEvent + ) external returns (bool) { + // Ensure the log came from the EAS contract + require(_id.origin == EAS_CONTRACT, "Not from EAS contract"); + + // Validate the message through CrossL2Inbox + ICrossL2Inbox(CROSS_L2_INBOX).validateMessage(_id, keccak256(_attestationEvent)); + + // Decode the attestation event data + // (implementation depends on EAS event structure) + + // Process the attestation + // For example, grant special permissions or better rates + + return true; + } +} +``` + +## Implementation guide + +To implement cross-chain log reading: + +```mermaid +flowchart TD + A[1. Identify log to consume] --> B[2. Create Identifier struct] + B --> C[3. Call validateMessage] + C --> D[4. Process validated log data] + + subgraph "Code Examples" + E["Identifier memory id = Identifier({ + chainId: sourceChainId, + origin: sourceContractAddress, + // Other identifier parameters + });"] + + F["ICrossL2Inbox(Predeploys.CROSS_L2_INBOX).validateMessage(id, keccak256(logData));"] + end + + B -.-> E + C -.-> F +``` + +## Important considerations + +* This feature works between chains within the same Superchain interop cluster +* The same functionality can be used on a single chain (for example, to maintain a consistent architecture) +* The `CrossL2Inbox` contract needs to be able to verify logs from the source chain +* Ensure your contract handles validation failures gracefully + +## Comparison with `L2ToL2CrossDomainMessenger` + +| Feature | L2ToL2CrossDomainMessenger | CrossL2Inbox#validateMessage | +| ---------- | -------------------------------- | ------------------------------------- | +| Purpose | Send messages between chains | Verify logs from other chains | +| Initiation | Active sending from source | Passive reading from destination | +| Use Case | Transfer tokens, trigger actions | Verify attestations, reference events | +| Flow | Push model | Pull model | + +## End-to-End flow comparison + +```mermaid +flowchart LR + subgraph "L2ToL2CrossDomainMessenger (Push Model)" + A[Source Contract] -->|sendMessage| B[Source L2ToL2CrossDomainMessenger] + B -->|emit event| C[Event Log] + C -.->|relayed by| D[Autorelayer] + D -->|relayMessage| E[Destination L2ToL2CrossDomainMessenger] + E -->|execute| F[Destination Contract] + end + + subgraph "CrossL2Inbox (Pull Model)" + G[Source Contract] -->|emit event| H[Event Log] + H -.->|monitored by| I[OP-Supervisor] + J[Destination Contract] -->|validateMessage| K[CrossL2Inbox] + K <--->|verify log| I + end +``` + +## Next steps + +* [Build a revolutionary app](/app-developers/get-started) that uses multiple blockchains within the Superchain +* Learn how to [pass messages between blockchains](/stack/interop/tutorials/message-passing) +* Deploy a [SuperchainERC20](/stack/interop/tutorials/deploy-superchain-erc20) to the Superchain From d22d0c86f89805fe80e11342a8635bc6a488bab3 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 01:51:58 +0100 Subject: [PATCH 02/21] add breadcrumbs --- pages/stack/interop.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/stack/interop.mdx b/pages/stack/interop.mdx index 58220489f..4dfbf523f 100644 --- a/pages/stack/interop.mdx +++ b/pages/stack/interop.mdx @@ -17,6 +17,8 @@ Documentation covering explainers and tutorials for using Superchain interop. } /> + } /> + } /> } /> From c271a6eda8002a5db95cc20fdc345c210dcf3edb Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 01:52:15 +0100 Subject: [PATCH 03/21] Auto-fix: Update breadcrumbs, spelling dictionary and other automated fixes --- pages/stack/interop.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop.mdx b/pages/stack/interop.mdx index 4dfbf523f..d8db11bd0 100644 --- a/pages/stack/interop.mdx +++ b/pages/stack/interop.mdx @@ -17,7 +17,7 @@ Documentation covering explainers and tutorials for using Superchain interop. } /> - } /> + } /> } /> From c58f69fda02a3292e9165871a30a5f008aa48e3f Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 02:12:20 +0100 Subject: [PATCH 04/21] Described mermaid diagrams --- pages/stack/interop/reading-logs.mdx | 75 +++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 0767e9220..d8a6307d3 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -11,17 +11,18 @@ import { InteropCallout } from '@/components/WipCallout' # Reading logs in superchain interop -Superchain interop enables developers to leverage current and historical logs from other blockchains within the Superchain interop cluster directly on their local chain. This feature allows for cross-chain log consumption with low latency in a trust-minimized way. +Superchain interop enables developers to leverage current and historical logs from other blockchains within the Superchain interop cluster directly on their local chain. +This allows for cross-chain log consumption with low latency in a trust-minimized way. ## Overview -While the [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol) enables sending messages across chains, the [`CrossL2Inbox#validateMessage`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L49) function allows smart contracts to verify and consume logs that were emitted on other chains within the Superchain ecosystem. +Instead of relying solely on [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), developers can use [`CrossL2Inbox#validateMessage`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L49) and treat `CrossL2Inbox` as an oracle for logs that occurred on different chains or even their local chain. -This capability enables developers to: +This enables developers to: -* Reference attestations or events from other chains -* Build cross-chain applications that react to events happening across the Superchain -* Create novel financial products that leverage data from multiple chains +* Reference attestations or events from other chains. +* Build cross-chain applications that react to events happening across the Superchain. +* Create novel dApps that leverage data from multiple chains. ## Why use `CrossL2Inbox`? @@ -35,8 +36,8 @@ This capability enables developers to: The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L33) contract, which serves as an oracle for logs from other chains in the Superchain: -1. A smart contract on Chain A emits a log (event) -2. Your contract on Chain B calls `CrossL2Inbox#validateMessage` with the log's identifier +1. A smart contract on `Chain A` emits a log (event) +2. Your contract on `Chain B` calls `CrossL2Inbox#validateMessage` with the log's identifier 3. The `CrossL2Inbox` contract verifies the log's authenticity 4. Your contract can then use the validated log data @@ -66,6 +67,14 @@ sequenceDiagram Note over Log: Event contains attestation data ``` +1. The user initiates a request for an attestation through an application. + +2. The application calls the `createAttestation()` function on the EAS (Ethereum Attestation Service) contract on the source chain. + +3. The EAS contract processes the attestation request and emits an `AttestationCreated` event. + +4. The event is recorded in the chain's log, containing all necessary attestation data. + ### Destination chain: verifying the attestation On the destination chain (e.g., Base), a DeFi application wants to verify this attestation: @@ -88,6 +97,22 @@ sequenceDiagram DeFi-->>User: Grant access based on attestation ``` +1. The user requests access to a DeFi application on the destination chain, referencing an attestation created on the source chain. + +2. The DeFi application calls `verifyAttestation()` on the `AttestationVerifier` contract, passing the attestation's identifier and event data. + +3. The AttestationVerifier calls `validateMessage()` on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. + +4. The `CrossL2Inbox` contract interacts with the `OP-Supervisor` node to check if the specified log exists on the source chain. + +5. The `OP-Supervisor` confirms the validity of the log to the `CrossL2Inbox` contract. + +6. The `CrossL2Inbox` returns the validation result to the `AttestationVerifier`. + +7. The `AttestationVerifier` returns the verification status to the DeFi application. + +8. If validation is successful, the DeFi application grants the user access based on the verified attestation. + ### Sample code for attestation verification ```solidity @@ -150,6 +175,14 @@ flowchart TD C -.-> F ``` +1. First, identify which log from another chain you want to consume in your application. + +2. Create an Identifier struct that contains all necessary information about the log, including the chain ID and the contract address that emitted the log. + +3. Call the `validateMessage()` function on the `CrossL2Inbox` contract, passing the identifier and a hash of the log data. + +4. After validation, process the log data according to your application's requirements. + ## Important considerations * This feature works between chains within the same Superchain interop cluster @@ -186,6 +219,32 @@ flowchart LR end ``` +This diagram compares the two approaches for cross-chain communication: + +### L2ToL2CrossDomainMessenger (Push Model): + +1. A source contract calls `sendMessage()` on the `L2ToL2CrossDomainMessenger`. + +2. The messenger emits an event to the event log. + +3. An autorelayer detects the event and relays it to the destination chain. + +4. The destination `L2ToL2CrossDomainMessenger` receives the relayed message. + +5. The destination messenger executes the message on the target contract. + +### CrossL2Inbox (Pull Model): + +1. A source contract emits an event to the event log. + +2. The `OP-Supervisor` node monitors events across chains. + +3. A destination contract calls `validateMessage()` on the `CrossL2Inbox`. + +4. The `CrossL2Inbox` verifies the log's existence by communicating with the `OP-Supervisor`. + +5. The destination contract receives verification and proceeds with its logic. + ## Next steps * [Build a revolutionary app](/app-developers/get-started) that uses multiple blockchains within the Superchain From 7ac6de1976c00db43019c32171de4769ed0d5a76 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 17:53:10 +0100 Subject: [PATCH 05/21] update links --- pages/stack/interop/reading-logs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index d8a6307d3..b08ce2a1a 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -103,7 +103,7 @@ sequenceDiagram 3. The AttestationVerifier calls `validateMessage()` on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. -4. The `CrossL2Inbox` contract interacts with the `OP-Supervisor` node to check if the specified log exists on the source chain. +4. The `CrossL2Inbox` contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) node to check if the specified log exists on the source chain. 5. The `OP-Supervisor` confirms the validity of the log to the `CrossL2Inbox` contract. From 8af01909b7d4c4b70af470f7e888d9bd29f0fa35 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 17:56:03 +0100 Subject: [PATCH 06/21] Update pages/stack/interop/reading-logs.mdx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- pages/stack/interop/reading-logs.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index b08ce2a1a..11c39c6a4 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -2,6 +2,10 @@ title: Reading Logs in Superchain Interop lang: en-US description: Learn how to reference logs from one chain on another within the Superchain. +topic: Cross-Chain Log Verification +personas: [ "Developer" ] +categories: [ "Documentation", "Interop" ] +content_type: documentation --- import { Callout } from 'nextra/components' From 11a09a9df827db91fb23bb6ab247f1a4ce00fcaf Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 17:56:23 +0100 Subject: [PATCH 07/21] Update pages/stack/interop/reading-logs.mdx Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com> --- pages/stack/interop/reading-logs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 11c39c6a4..3d71de739 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -26,7 +26,7 @@ This enables developers to: * Reference attestations or events from other chains. * Build cross-chain applications that react to events happening across the Superchain. -* Create novel dApps that leverage data from multiple chains. +* Create novel applications that leverage data from multiple chains. ## Why use `CrossL2Inbox`? From 5a73a899fbce23d9f66d8508586567d2b5460707 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 13 Mar 2025 17:56:44 +0100 Subject: [PATCH 08/21] updated contract address --- pages/stack/interop/reading-logs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index b08ce2a1a..52d64f2a6 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -123,7 +123,7 @@ import { ICrossL2Inbox, Identifier } from "interfaces/L2/ICrossL2Inbox.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; contract AttestationVerifier { - address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000014; + address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000021; address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000EAS; // Example address // Event selector for AttestationCreated event From 8b23aef1ea684108c65b635325b09720fce3bb6d Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 16:50:00 +0100 Subject: [PATCH 09/21] Updated address --- pages/stack/interop/reading-logs.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 4570f5c46..b35e60a94 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -16,7 +16,7 @@ import { InteropCallout } from '@/components/WipCallout' # Reading logs in superchain interop Superchain interop enables developers to leverage current and historical logs from other blockchains within the Superchain interop cluster directly on their local chain. -This allows for cross-chain log consumption with low latency in a trust-minimized way. +This allows smart contracts to consume local and cross-chain logs with low latency in a trust-minimized way. ## Overview @@ -47,7 +47,7 @@ The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optim ### Key components -* **Identifier**: A struct containing information about the log, including `chainId`, `origin` (contract address), and other log metadata +* **[Identifier](/stack/interop/tutorials/relay-messages-cast#message-identifier)**: A struct containing information about the log, including `chainId`, `origin` (contract address), and other log metadata * **validateMessage**: Function that verifies a log's authenticity before allowing its use ## Example: cross-chain attestation verification @@ -89,7 +89,7 @@ sequenceDiagram participant DeFi as DeFi Application participant Verifier as AttestationVerifier participant CrossL2 as CrossL2Inbox - participant OP as OP-Supervisor Node + participant OP as OP-Supervisor Service User->>DeFi: Request access using attestation DeFi->>Verifier: verifyAttestation(id, attestationEvent) @@ -107,7 +107,7 @@ sequenceDiagram 3. The AttestationVerifier calls `validateMessage()` on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. -4. The `CrossL2Inbox` contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) node to check if the specified log exists on the source chain. +4. The `CrossL2Inbox` contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) service to check if the specified log exists on the source chain. 5. The `OP-Supervisor` confirms the validity of the log to the `CrossL2Inbox` contract. @@ -127,7 +127,7 @@ import { ICrossL2Inbox, Identifier } from "interfaces/L2/ICrossL2Inbox.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; contract AttestationVerifier { - address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000021; + address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000EAS; // Example address // Event selector for AttestationCreated event @@ -241,7 +241,7 @@ This diagram compares the two approaches for cross-chain communication: 1. A source contract emits an event to the event log. -2. The `OP-Supervisor` node monitors events across chains. +2. The `OP-Supervisor` service monitors events across chains. 3. A destination contract calls `validateMessage()` on the `CrossL2Inbox`. From b7d5e0cb65fac9fba4e3cbb264d4bbe9a59b3a16 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 16:51:22 +0100 Subject: [PATCH 10/21] updated the eas address --- pages/stack/interop/reading-logs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index b35e60a94..03826dc3e 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -128,7 +128,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; contract AttestationVerifier { address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; - address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000EAS; // Example address + address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000021; // Event selector for AttestationCreated event bytes32 constant ATTESTATION_CREATED_EVENT_SELECTOR = From 482efa1f39c8f27121fad497ca7c9072307a73b7 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 16:59:32 +0100 Subject: [PATCH 11/21] Add steps to handle validation --- pages/stack/interop/reading-logs.mdx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 03826dc3e..d35c78ee6 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -189,10 +189,16 @@ flowchart TD ## Important considerations -* This feature works between chains within the same Superchain interop cluster -* The same functionality can be used on a single chain (for example, to maintain a consistent architecture) -* The `CrossL2Inbox` contract needs to be able to verify logs from the source chain -* Ensure your contract handles validation failures gracefully +* This feature works between chains within the same Superchain interop cluster. +* The same functionality can be used on a single chain (for example, to maintain a consistent architecture). +* The `CrossL2Inbox` contract needs to be able to verify logs from the source chain. +* Ensure your contract handles validation failures gracefully. + +### Validation failures + +* The `validateMessage` call will revert the entire transaction if validation fails. +* Consider implementing a try-catch pattern in your application's frontend to handle these failures. +* Design your contract to allow for retry mechanisms where appropriate. ## Comparison with `L2ToL2CrossDomainMessenger` From 4c882debb3d1e516f3cdb423f8b5002c5478ef46 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 16:59:52 +0100 Subject: [PATCH 12/21] Auto-fix: Update breadcrumbs, spelling dictionary and other automated fixes --- pages/stack/interop/reading-logs.mdx | 2 +- words.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index d35c78ee6..c3e945299 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -194,7 +194,7 @@ flowchart TD * The `CrossL2Inbox` contract needs to be able to verify logs from the source chain. * Ensure your contract handles validation failures gracefully. -### Validation failures +### Handlingg validation failures * The `validateMessage` call will revert the entire transaction if validation fails. * Consider implementing a try-catch pattern in your application's frontend to handle these failures. diff --git a/words.txt b/words.txt index a798274ff..47ed7d717 100644 --- a/words.txt +++ b/words.txt @@ -152,6 +152,7 @@ GLOBALSLOTS globalslots gokzg growthepie +Handlingg hardfork hardforks HEALTHCHECK From 09634f5ae36918b8e505da7e08d46bc6259f29f7 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 17:00:21 +0100 Subject: [PATCH 13/21] Auto-fix: Update breadcrumbs, spelling dictionary and other automated fixes --- pages/stack/interop/reading-logs.mdx | 2 +- words.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index c3e945299..e50952f5c 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -194,7 +194,7 @@ flowchart TD * The `CrossL2Inbox` contract needs to be able to verify logs from the source chain. * Ensure your contract handles validation failures gracefully. -### Handlingg validation failures +### Handling validation failures * The `validateMessage` call will revert the entire transaction if validation fails. * Consider implementing a try-catch pattern in your application's frontend to handle these failures. diff --git a/words.txt b/words.txt index 47ed7d717..a798274ff 100644 --- a/words.txt +++ b/words.txt @@ -152,7 +152,6 @@ GLOBALSLOTS globalslots gokzg growthepie -Handlingg hardfork hardforks HEALTHCHECK From 54cf3ed9662d1f16e881daf2cf1bf8147ef303fe Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 17:37:34 +0100 Subject: [PATCH 14/21] updated the table text --- pages/stack/interop/reading-logs.mdx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index e50952f5c..780786a1d 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -24,7 +24,6 @@ Instead of relying solely on [L2ToL2CrossDomainMessenger](https://github.com/eth This enables developers to: -* Reference attestations or events from other chains. * Build cross-chain applications that react to events happening across the Superchain. * Create novel applications that leverage data from multiple chains. @@ -202,12 +201,12 @@ flowchart TD ## Comparison with `L2ToL2CrossDomainMessenger` -| Feature | L2ToL2CrossDomainMessenger | CrossL2Inbox#validateMessage | -| ---------- | -------------------------------- | ------------------------------------- | -| Purpose | Send messages between chains | Verify logs from other chains | -| Initiation | Active sending from source | Passive reading from destination | -| Use Case | Transfer tokens, trigger actions | Verify attestations, reference events | -| Flow | Push model | Pull model | +| Feature | L2ToL2CrossDomainMessenger | CrossL2Inbox#validateMessage | +| ---------- | ---------------------------------------------- | ------------------------------------------------- | +| Purpose | Send messages between chains | Verify logs from other chains or local chain | +| Initiation | Source explicitly sends message to destination | Destination queries for existing logs from source | +| Use Case | Transfer tokens, trigger actions | Verify attestations, reference events | +| Flow | Push model | Pull model | ## End-to-End flow comparison From c54eb31130b2466699548ea0d7d0ee08b12bac82 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 14 Mar 2025 18:09:18 +0100 Subject: [PATCH 15/21] Update bullet points --- pages/stack/interop/reading-logs.mdx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 780786a1d..661e6e130 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -29,9 +29,10 @@ This enables developers to: ## Why use `CrossL2Inbox`? -* **Lower latency**: Directly reference logs without waiting for cross-chain message confirmation. -* **Trust-minimized**: Uses cryptographic validation rather than relying on off-chain relayers. -* **Flexibility**: Can be used to validate events from another chain or even the same chain. +* **Reference existing logs**: Allows contracts to verify and use logs that were already emitted, without requiring those logs to have been sent as cross-chain messages. +* **Consistent trust model**: Uses the same trust assumptions as the underlying OP Stack infrastructure. +* **Flexibility**: Can be used to validate events from another chain or even the local chain. + ## How it works From a65245ca84ed3754a79790cd61d17547b1a0e845 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 20 Mar 2025 18:23:17 +0100 Subject: [PATCH 16/21] removed codes and used explanations --- pages/stack/interop/reading-logs.mdx | 78 +++++++++++----------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 661e6e130..47c7d6069 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -33,7 +33,6 @@ This enables developers to: * **Consistent trust model**: Uses the same trust assumptions as the underlying OP Stack infrastructure. * **Flexibility**: Can be used to validate events from another chain or even the local chain. - ## How it works ### Architecture @@ -52,7 +51,7 @@ The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optim ## Example: cross-chain attestation verification -Let's walk through a practical example of verifying an Ethereum Attestation Service (EAS) attestation across chains. +Let's walk through a conceptual example of verifying an Ethereum Attestation Service (EAS) attestation across chains. ### Source chain: creating an attestation @@ -103,57 +102,40 @@ sequenceDiagram 1. The user requests access to a DeFi application on the destination chain, referencing an attestation created on the source chain. -2. The DeFi application calls `verifyAttestation()` on the `AttestationVerifier` contract, passing the attestation's identifier and event data. +2. The DeFi application calls a verification function on an attestation verifier contract, passing the attestation's identifier and event data. -3. The AttestationVerifier calls `validateMessage()` on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. +3. The attestation verifier calls [`validateMessage()`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L79) on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. -4. The `CrossL2Inbox` contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) service to check if the specified log exists on the source chain. +4. The [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) service to check if the specified log exists on the source chain. 5. The `OP-Supervisor` confirms the validity of the log to the `CrossL2Inbox` contract. -6. The `CrossL2Inbox` returns the validation result to the `AttestationVerifier`. +6. The `CrossL2Inbox` returns the validation result to the attestation verifier. -7. The `AttestationVerifier` returns the verification status to the DeFi application. +7. The attestation verifier returns the verification status to the DeFi application. 8. If validation is successful, the DeFi application grants the user access based on the verified attestation. -### Sample code for attestation verification +### Conceptual approach for attestation verification -```solidity -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +When implementing an attestation verification system using `CrossL2Inbox`, you would need to: -import { ICrossL2Inbox, Identifier } from "interfaces/L2/ICrossL2Inbox.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; +1. **Create an [Identifier struct](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L13)** that uniquely identifies the attestation event: + * Include the source chain ID where the attestation was created + * Specify the EAS contract address (origin) that emitted the event + * Include other necessary parameters to identify the specific log -contract AttestationVerifier { - address constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; - address constant EAS_CONTRACT = 0x4200000000000000000000000000000000000021; - - // Event selector for AttestationCreated event - bytes32 constant ATTESTATION_CREATED_EVENT_SELECTOR = - 0x831531dabaca5375ba77364edc9627be5638660e8b613d921b86766021d3c165; // Example selector - - function verifyAttestation( - Identifier calldata _id, - bytes calldata _attestationEvent - ) external returns (bool) { - // Ensure the log came from the EAS contract - require(_id.origin == EAS_CONTRACT, "Not from EAS contract"); - - // Validate the message through CrossL2Inbox - ICrossL2Inbox(CROSS_L2_INBOX).validateMessage(_id, keccak256(_attestationEvent)); - - // Decode the attestation event data - // (implementation depends on EAS event structure) - - // Process the attestation - // For example, grant special permissions or better rates - - return true; - } -} -``` +2. **Validate the attestation event**: + * Call the `validateMessage()` function on the CrossL2Inbox contract + * Pass the identifier struct and a hash of the attestation event data + * Handle potential validation failures in your contract logic + +3. **Process the validated attestation**: + * Once validated, your contract can trust that the attestation exists on the source chain + * Extract relevant data from the attestation to inform your application's logic + * Implement business rules based on the verified attestation (e.g., grant access, enable features) + +The primary benefit of this approach is that it allows your contract to verify attestations that already exist on another chain without requiring those attestations to have been explicitly sent as cross-chain messages. ## Implementation guide @@ -165,14 +147,14 @@ flowchart TD B --> C[3. Call validateMessage] C --> D[4. Process validated log data] - subgraph "Code Examples" - E["Identifier memory id = Identifier({ - chainId: sourceChainId, - origin: sourceContractAddress, - // Other identifier parameters - });"] + subgraph "Conceptual Approach" + E["Define an Identifier struct with: + - chainId: The source chain ID + - origin: The source contract address + - Other required identifier parameters"] - F["ICrossL2Inbox(Predeploys.CROSS_L2_INBOX).validateMessage(id, keccak256(logData));"] + F["Call validateMessage on CrossL2Inbox + Pass the identifier and hash of log data"] end B -.-> E From 25e3adc46615374f588c907fd0caa1b5b41c612b Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 20 Mar 2025 18:38:56 +0100 Subject: [PATCH 17/21] update links --- pages/stack/interop/reading-logs.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 47c7d6069..f642ea379 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -47,7 +47,7 @@ The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optim ### Key components * **[Identifier](/stack/interop/tutorials/relay-messages-cast#message-identifier)**: A struct containing information about the log, including `chainId`, `origin` (contract address), and other log metadata -* **validateMessage**: Function that verifies a log's authenticity before allowing its use +* **[validateMessage](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L79)**: Function that verifies a log's authenticity before allowing its use ## Example: cross-chain attestation verification @@ -104,7 +104,7 @@ sequenceDiagram 2. The DeFi application calls a verification function on an attestation verifier contract, passing the attestation's identifier and event data. -3. The attestation verifier calls [`validateMessage()`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L79) on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. +3. The attestation verifier calls `validateMessage()` on the `CrossL2Inbox` contract, passing the attestation identifier and a hash of the event data. 4. The [`CrossL2Inbox`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol) contract interacts with the [`OP-Supervisor`](/stack/interop/op-supervisor) service to check if the specified log exists on the source chain. @@ -120,7 +120,7 @@ sequenceDiagram When implementing an attestation verification system using `CrossL2Inbox`, you would need to: -1. **Create an [Identifier struct](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L13)** that uniquely identifies the attestation event: +1. **Create an Identifier struct** that uniquely identifies the attestation event: * Include the source chain ID where the attestation was created * Specify the EAS contract address (origin) that emitted the event * Include other necessary parameters to identify the specific log From e3a876d6b926e580a32614b7843df7faa4b957cb Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 20 Mar 2025 14:37:09 -0700 Subject: [PATCH 18/21] Update pages/stack/interop/reading-logs.mdx Co-authored-by: Bradley Camacho <42678939+bradleycamacho@users.noreply.github.com> --- pages/stack/interop/reading-logs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index f642ea379..7b983212a 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -20,7 +20,7 @@ This allows smart contracts to consume local and cross-chain logs with low laten ## Overview -Instead of relying solely on [L2ToL2CrossDomainMessenger](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), developers can use [`CrossL2Inbox#validateMessage`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L49) and treat `CrossL2Inbox` as an oracle for logs that occurred on different chains or even their local chain. +Instead of relying solely on [`L2ToL2CrossDomainMessenger`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol), developers can use [`CrossL2Inbox#validateMessage`](https://github.com/ethereum-optimism/optimism/blob/af091753917c1d7101314cbfe8ac5cbc2efe0e5e/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol#L49) and treat `CrossL2Inbox` as an oracle for logs that occurred on different chains or even their local chain. This enables developers to: From bdc3450a5c1a587c136c04f8447b7b43e009b5bc Mon Sep 17 00:00:00 2001 From: krofax Date: Thu, 20 Mar 2025 15:42:16 -0700 Subject: [PATCH 19/21] updated bullet points --- pages/stack/interop/reading-logs.mdx | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 7b983212a..ac6545aea 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -31,6 +31,7 @@ This enables developers to: * **Reference existing logs**: Allows contracts to verify and use logs that were already emitted, without requiring those logs to have been sent as cross-chain messages. * **Consistent trust model**: Uses the same trust assumptions as the underlying OP Stack infrastructure. +* **Trust-minimized security**: Leverages the existing Superchain security model with no additional trust assumptions, unlike traditional oracle solutions that require trusting external validators. * **Flexibility**: Can be used to validate events from another chain or even the local chain. ## How it works @@ -116,25 +117,6 @@ sequenceDiagram 8. If validation is successful, the DeFi application grants the user access based on the verified attestation. -### Conceptual approach for attestation verification - -When implementing an attestation verification system using `CrossL2Inbox`, you would need to: - -1. **Create an Identifier struct** that uniquely identifies the attestation event: - * Include the source chain ID where the attestation was created - * Specify the EAS contract address (origin) that emitted the event - * Include other necessary parameters to identify the specific log - -2. **Validate the attestation event**: - * Call the `validateMessage()` function on the CrossL2Inbox contract - * Pass the identifier struct and a hash of the attestation event data - * Handle potential validation failures in your contract logic - -3. **Process the validated attestation**: - * Once validated, your contract can trust that the attestation exists on the source chain - * Extract relevant data from the attestation to inform your application's logic - * Implement business rules based on the verified attestation (e.g., grant access, enable features) - The primary benefit of this approach is that it allows your contract to verify attestations that already exist on another chain without requiring those attestations to have been explicitly sent as cross-chain messages. ## Implementation guide From 33fb25ae1d57db855abced37dd377c2ce1b41bc9 Mon Sep 17 00:00:00 2001 From: krofax Date: Thu, 20 Mar 2025 18:52:56 -0700 Subject: [PATCH 20/21] updated the bullet point --- pages/stack/interop/reading-logs.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index ac6545aea..061056e7e 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -155,7 +155,6 @@ flowchart TD * This feature works between chains within the same Superchain interop cluster. * The same functionality can be used on a single chain (for example, to maintain a consistent architecture). -* The `CrossL2Inbox` contract needs to be able to verify logs from the source chain. * Ensure your contract handles validation failures gracefully. ### Handling validation failures From d2832ee784a24389d252e945f517d1016f836eda Mon Sep 17 00:00:00 2001 From: krofax Date: Fri, 21 Mar 2025 09:47:32 -0700 Subject: [PATCH 21/21] updated content based on zains comment --- pages/stack/interop/reading-logs.mdx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/pages/stack/interop/reading-logs.mdx b/pages/stack/interop/reading-logs.mdx index 061056e7e..d35cca577 100644 --- a/pages/stack/interop/reading-logs.mdx +++ b/pages/stack/interop/reading-logs.mdx @@ -1,5 +1,5 @@ --- -title: Reading Logs in Superchain Interop +title: Reading Logs with Superchain Interop lang: en-US description: Learn how to reference logs from one chain on another within the Superchain. topic: Cross-Chain Log Verification @@ -13,9 +13,9 @@ import { InteropCallout } from '@/components/WipCallout' -# Reading logs in superchain interop +# Reading Logs with Superchain Interop -Superchain interop enables developers to leverage current and historical logs from other blockchains within the Superchain interop cluster directly on their local chain. +Superchain interop enables developers to leverage current and historical logs from other blockchains within the [Superchain interop cluster](/stack/interop/explainer#superchain-interop-cluster) directly on their local chain. This allows smart contracts to consume local and cross-chain logs with low latency in a trust-minimized way. ## Overview @@ -30,8 +30,7 @@ This enables developers to: ## Why use `CrossL2Inbox`? * **Reference existing logs**: Allows contracts to verify and use logs that were already emitted, without requiring those logs to have been sent as cross-chain messages. -* **Consistent trust model**: Uses the same trust assumptions as the underlying OP Stack infrastructure. -* **Trust-minimized security**: Leverages the existing Superchain security model with no additional trust assumptions, unlike traditional oracle solutions that require trusting external validators. +* **Trust-minimized security**: Leverages the existing Superchain security model with no additional trust assumptions. * **Flexibility**: Can be used to validate events from another chain or even the local chain. ## How it works @@ -53,6 +52,7 @@ The process works through the [`CrossL2Inbox`](https://github.com/ethereum-optim ## Example: cross-chain attestation verification Let's walk through a conceptual example of verifying an Ethereum Attestation Service (EAS) attestation across chains. +EAS is a [predeploy](/stack/interop/predeploy) in the OP Stack for making attestations on or off-chain about anything. ### Source chain: creating an attestation @@ -81,7 +81,7 @@ sequenceDiagram ### Destination chain: verifying the attestation -On the destination chain (e.g., Base), a DeFi application wants to verify this attestation: +On the destination chain (e.g., Unichain), a DeFi application wants to verify this attestation: ```mermaid sequenceDiagram @@ -119,7 +119,7 @@ sequenceDiagram The primary benefit of this approach is that it allows your contract to verify attestations that already exist on another chain without requiring those attestations to have been explicitly sent as cross-chain messages. -## Implementation guide +## Overview of the process To implement cross-chain log reading: @@ -139,8 +139,8 @@ flowchart TD Pass the identifier and hash of log data"] end - B -.-> E - C -.-> F + B --> E + C --> F ``` 1. First, identify which log from another chain you want to consume in your application. @@ -153,9 +153,8 @@ flowchart TD ## Important considerations -* This feature works between chains within the same Superchain interop cluster. +* This feature works between chains within the [Superchain interop cluster](/stack/interop/explainer#superchain-interop-cluster). * The same functionality can be used on a single chain (for example, to maintain a consistent architecture). -* Ensure your contract handles validation failures gracefully. ### Handling validation failures