diff --git a/docs/cookbook/mastering-cross-chain-state.mdx b/docs/cookbook/mastering-cross-chain-state.mdx new file mode 100644 index 00000000..90c51516 --- /dev/null +++ b/docs/cookbook/mastering-cross-chain-state.mdx @@ -0,0 +1,210 @@ +--- +title: Mastering Cross-Chain State +slug: /cookbook/mastering-cross-chain-state +description: A deep dive into the 7-day withdrawal lifecycle, native vs. third-party bridges, and advanced fund recovery techniques for mismatched addresses. +author: [YourGitHubUsername] +tags: [bridging, optimism, withdrawals, recovery, gnosis-safe, create2] +--- + +# Mastering Cross-Chain State: Bridging & Recovery + +**Target Audience:** DApp Developers, Support Engineers, Protocol Architects +**Prerequisites:** Understanding of EVM fundamentals (EOAs vs. Smart Contracts) + +In a multi-chain ecosystem, "State" is fragmented. Moving assets between Layer 1 (Ethereum) and Layer 2 (Base) is not just a database update—it is an asynchronous cryptographic protocol. This guide provides deep technical context on the **7-day withdrawal lifecycle**, **bridging architectures**, and **fund recovery scenarios**. + +--- + +## Part 1: The 7-Day Challenge Period (L2 → L1) + +When a user deposits funds *into* Base, it takes minutes. When they withdraw *back* to Ethereum using the official bridge, it takes 7 days. This asymmetry is the core security mechanism of an **Optimistic Rollup**. + +### The Technical "Why" + +Base "optimistically" assumes all transactions are valid. It does not verify them on Ethereum immediately to save gas. + +1. **Output Proposal:** A "Proposer" submits a bundle of L2 transactions to L1. +2. **Challenge Window (7 Days):** The system waits. During this time, any "Verifier" node can check the data. If they find an invalid transaction (e.g., minting ETH out of thin air), they submit a **Fraud Proof**. +3. **Finalization:** If no fraud is proven after 7 days, the bundle is finalized. Only then can the L1 smart contract release the locked funds. + +### Example Timeline: Alice's Withdrawal + +* **Day 0 (Monday 9:00 AM):** Alice initiates a withdrawal of 10 ETH on Base. +* *Status:* Her 10 ETH is burned/locked on Base. +* *L1 Status:* A "Withdrawal Initiated" event is logged. + + +* **Day 0 (Monday 10:00 AM):** The Proposer submits the Output Root to Ethereum. +* *Timer:* The 7-day clock starts ticking. + + +* **Day 1-6:** The funds sit in limbo. They do not exist in Alice's L1 wallet yet. +* **Day 7 (Monday 10:01 AM):** The challenge window closes. +* **Day 7 (Monday 10:05 AM):** Alice (or a relayer) must send a second transaction on Ethereum: `proveWithdrawalTransaction`. +* **Day 7 (Monday 10:10 AM):** Alice sends the final transaction: `finalizeWithdrawalTransaction`. +* *Result:* The L1 Bridge contract transfers 10 ETH to Alice. + + + +### UI Implementation Guide + +You must manage the user's anxiety during this week-long wait. + +**Anti-Pattern (Don't do this):** + +> Status: Pending... + +**Best Practice (Do this):** +Create a 3-step visual tracker. + +```javascript +// React Pseudocode for Withdrawal Status +const WithdrawalStatus = ({ status, daysRemaining }) => { + if (status === 'CHALLENGE_PERIOD') { + return ( +
+

Step 2 of 3: Security Verification

+

Your funds are currently undergoing the standard 7-day security challenge.

+ +

+ Time remaining: {daysRemaining} days. + It is safe to close this window. You can return on {getUnlockDate()} to claim your funds. +

+
+ ); + } + if (status === 'READY_TO_CLAIM') { + return ; + } +}; + +``` + +--- + +## Part 2: Native vs. Third-Party Bridges + +Understanding the trade-offs allows you to route users correctly. + +### 1. The Native Bridge (The "Slow & Secure" Route) + +* **Architecture:** Lock-and-Mint. Assets are locked in a contract on L1, and a canonical representation is minted on L2. +* **Security:** Inherits the full security of Ethereum. To steal funds, you would have to break Ethereum's consensus or the Optimism protocol itself. +* **Best For:** * **Whales:** Moving $1M+ where 0.1% fees are too expensive. +* **DAOs:** Governance actions that require canonical tokens. +* **Arbitrageurs:** Who don't care about time delays. + + + +### 2. Third-Party Bridges (The "Fast & Liquid" Route) + +* **Architecture:** Liquidity Pools. The bridge has a pool of USDC on L1 and a pool of USDC on L2. +* **Mechanism:** You give the bridge USDC on Base. The bridge (or a liquidity provider) immediately sends you USDC on Ethereum from their own pocket, minus a fee. They take on the 7-day risk for you. +* **Security:** Trust-based or Trust-minimized (depending on the protocol: Across, Hop, Stargate). If the bridge's smart contract is hacked, liquidity providers lose money. +* **Best For:** +* **Retail Users:** "I need ETH on Mainnet *now*." +* **Small Amounts:** Where paying $5 fee is worth saving 7 days. + + + +### Decision Matrix for Developers + +| Scenario | Recommended Route | Reason | +| --- | --- | --- | +| **User wants to move 0.5 ETH for gas** | **Third-Party** | Speed is priority. Fee is negligible. | +| **DAO Treasury moving 5,000 ETH** | **Native** | Security is priority. 0.1% fee on 5k ETH is too high (5 ETH!). | +| **User withdrawing NFT** | **Native** | Most third-party bridges only support fungible tokens (ERC20). | + +--- + +## Part 3: The "Stuck Funds" Recovery Guide + +This is a critical support topic. Users frequently send funds to the "wrong" address on Base because they assume their address is universal. + +### Scenario A: The EOA (Metamask User) + +* **The Issue:** "I use address `0x123` on Ethereum. I sent funds to `0x123` on Base, but I can't see them." +* **The Physics:** An Externally Owned Account (EOA) is derived from a **Private Key**. The math (`Public Key = G * Private Key`) is identical on all EVM chains. +* **The Solution:** The funds are safe. The user just needs to configure their wallet. +1. Open Metamask. +2. Add Network -> Base Mainnet. +3. The funds will appear at `0x123`. + + + +### Scenario B: The Smart Contract (Gnosis Safe / Multisig) + +* **The Issue:** "I have a Gnosis Safe at `0x888` on Ethereum. I sent 50 ETH to `0x888` on Base. I don't have access to it!" +* **The Physics:** Smart contracts do **not** have private keys. Their addresses are generated deterministically based on creation parameters. + +#### Type 1: The `CREATE` Opcode (Standard Deploy) + +The address is determined by: `Keccak256(RLP_Encode([Deployer_Address, Nonce]))`. + +* **Example:** +* **Ethereum:** You deployed your Safe from your personal wallet (`0xAlice`) when your wallet's nonce was **5**. The Safe landed at `0x888`. +* **Base:** You look at `0xAlice` on Base. If your nonce is currently **2**, you haven't reached nonce 5 yet. + + +* **Recovery Strategy (Nonce Replay):** +1. On Base, send 2 dummy transactions from `0xAlice` to increment the nonce from 2 to 4. +2. For the **5th transaction**, send the **exact same deployment payload** (same factory code) that you used on Ethereum. +3. **Result:** The contract *must* deploy to `0x888`. You now own the address and the funds. + + + +#### Type 2: The `CREATE2` Opcode (Counterfactual Deploy) + +The address is determined by: `Keccak256(0xff + Deployer_Address + Salt + Keccak256(Init_Code))`. + +* **Why this is harder:** The `Deployer_Address` is usually a "Factory" contract. +* **Recovery Strategy:** +1. Check if the **Factory Contract** exists on Base at the *exact same address* as Ethereum. +2. If **YES**: You can call that factory with the same `Salt` and `Init_Code`. Your Safe will appear at the correct address. +3. If **NO**: The factory doesn't exist. You must first deploy the factory (using the "Nonce Replay" method above) to the correct spot, *then* use the factory to deploy your Safe. + + + +> **Critical Warning:** If you sent funds to a contract address on Base, and that address was originally created on Ethereum by a different contract that *cannot* be replicated on Base (e.g., a one-off script that was self-destructed), the funds are **permanently lost**. + +--- + +### File Structure for Contribution + +**1. Create File:** `apps/base-docs/docs/cookbook/mastering-cross-chain-state.mdx` + +**2. Metadata Header:** + +```markdown +--- +title: Mastering Cross-Chain State +slug: /cookbook/mastering-cross-chain-state +description: A deep dive into the 7-day withdrawal lifecycle, native vs. third-party bridges, and advanced fund recovery techniques for mismatched addresses. +author: [YourGitHubUsername] +tags: [bridging, optimism, withdrawals, recovery, gnosis-safe, create2] +--- + +``` + +**3. PR Description:** + +```markdown +## Title: docs: Add "Mastering Cross-Chain State" Deep Dive to Cookbook + +### Description +This PR adds a production-grade guide to handling cross-chain state on Base. It addresses high-frequency developer/user confusion regarding bridge delays and address derivation. + +### Key Additions +* **Visualizing the 7-Day Challenge:** A detailed timeline breakdown of the Optimistic Rollup withdrawal process (Initiate -> Prove -> Finalize). +* **Bridge Architecture Comparison:** A decision matrix for developers choosing between Native (Canonical) and Third-Party (Liquidity) bridges. +* **The "Stuck Funds" Recovery Protocol:** A technical guide to recovering assets sent to mismatched addresses, distinguishing between EOA (simple) and Smart Contract (CREATE/CREATE2) recovery paths. + +### File Changes +* Created: `apps/base-docs/docs/cookbook/mastering-cross-chain-state.mdx` + +### Checklist +- [x] Technical examples (Nonce Replay, CREATE2) verified for accuracy. +- [x] Tone is educational yet authoritative. +- [x] Frontmatter included. + +``` diff --git a/docs/cookbook/production-grade-rpc-management.mdx b/docs/cookbook/production-grade-rpc-management.mdx new file mode 100644 index 00000000..43862537 --- /dev/null +++ b/docs/cookbook/production-grade-rpc-management.mdx @@ -0,0 +1,193 @@ +--- +title: Production-Grade RPC Management +slug: /cookbook/production-grade-rpc-management +description: A guide to handling RPC errors, configuring fallback providers, and forking Base Mainnet for simulation. +author: [YourGitHubUsername] +tags: [rpc, nodes, wagmi, ethers, foundry, hardhat, debugging] +--- + +# The Production-Grade RPC Management Guide + +**Target Network:** Base Mainnet (EVM) + +In a decentralized application (dApp), the RPC (Remote Procedure Call) Node is your gateway to the blockchain. If your RPC fails, your app looks broken, even if the blockchain itself is fine. A production-grade setup must handle **failures**, **rate limits**, and **data complexity** automatically. + +--- + +## Part 1: Handling Common JSON-RPC Errors + +When your dApp scales, you will encounter specific error codes. Understanding these is crucial for debugging. + +### 1. Error `-32000`: Server Error + +This is a generic wrapper for server-side issues, but the accompanying message usually reveals the specific problem. + +#### **Scenario A: "Header not found"** + +* **What it means:** You are asking for data from a block that the node has "pruned" (deleted) to save hard drive space. Most free/standard nodes only keep the last 128 blocks. +* **The Fix:** You must switch to an **Archival Node**. +* **Action:** In your Alchemy/Infura dashboard, enable the "Archive" add-on. This allows you to query block #1 (Genesis) through the current block. + + + +#### **Scenario B: "Execution timeout"** + +* **What it means:** Your request (usually `eth_call` or `eth_estimateGas`) took longer than the node's limit (usually 5 seconds) to process. +* **The Fix:** Your query is too complex. +* **Action:** If reading data, break the query into multiple smaller calls using `Multicall`. +* **Action:** If estimating gas, your smart contract logic might be hitting an infinite loop or doing too much computation. + + + +--- + +### 2. Error `-32602`: Invalid Params (Block Range Limit) + +* **The Context:** This happens specifically during `eth_getLogs` (event filtering). +* **The Error:** "Log response size exceeded" or "Query exceeds 2000 blocks." +* **What it means:** You asked the node to scan 50,000 blocks for events, but the node allows a maximum of 2,000 blocks per request to prevent overload. + +#### **The Solution: Recursive Chunking** + +Do not ask the user to shorten their search. Instead, write code that splits the range automatically. + +**Logical Flow:** + +1. Define the full range (e.g., Block 10,000 to 20,000). +2. Try to fetch the whole range. +3. **If it fails**, cut the range in half (10,000 to 15,000) and try again. +4. Repeat until the request succeeds, then fetch the next chunk. + +--- + +## Part 2: The "Waterfall" Strategy (Fallback Providers) + +**Rule #1 of Production:** Never rely on a single RPC provider. +If Alchemy goes down, your app should seamlessly switch to Infura or a public node without the user noticing. + +### Configuration for Modern Stacks (`wagmi` v2) + +Wagmi provides a `fallback` transport that attempts to connect to providers in the order you list them. + +```typescript +import { createConfig, http, fallback } from 'wagmi' +import { base } from 'wagmi/chains' + +export const config = createConfig({ + chains: [base], + transports: { + [base.id]: fallback([ + // 1. High Performance (Paid) + // Use this first for speed and reliability. + http('https://base-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_KEY'), + + // 2. Redundancy Layer (Paid/Free Tier) + // Use this if Alchemy is down or rate-limited. + http('https://base.nownodes.io/YOUR_NOWNODES_KEY'), + + // 3. Last Resort (Public) + // Free, slow, and strictly rate-limited. Only use if all else fails. + http('https://mainnet.base.org'), + ], { + rank: true, // Wagmi will ping all lists and prioritize the fastest one automatically + retryCount: 3, // Retry a failed request 3 times before switching providers + }), + }, +}) + +``` + +### Configuration for Traditional Stacks (`ethers.js` v6) + +Ethers uses a weighted system. Lower `priority` numbers are preferred. + +```javascript +import { ethers } from "ethers"; + +// Define your individual providers +const p1 = new ethers.JsonRpcProvider("https://base-mainnet.g.alchemy.com/v2/KEY"); +const p2 = new ethers.JsonRpcProvider("https://base.nownodes.io/KEY"); +const p3 = new ethers.JsonRpcProvider("https://mainnet.base.org"); + +// Create the Fallback Provider +const provider = new ethers.FallbackProvider([ + { provider: p1, priority: 1, weight: 2, stallTimeout: 1000 }, // Primary + { provider: p2, priority: 2, weight: 1, stallTimeout: 2000 }, // Secondary + { provider: p3, priority: 3, weight: 1, stallTimeout: 2000 } // Tertiary +]); + +// Use this 'provider' object for all your calls +const block = await provider.getBlockNumber(); + +``` + +--- + +## Part 3: Zero-Cost Simulation (Forking Mainnet) + +Testing on "Testnets" (like Base Sepolia) is useful, but it lacks **state**. Testnets don't have the real Uniswap liquidity pools, the real user token balances, or the real contract interactions you find on Mainnet. + +**Mainnet Forking** solves this by creating a temporary, local simulation of the real blockchain. + +### Method A: Using Anvil (Foundry) + +*Best for: Quick, command-line based simulations and backend script testing.* + +1. **Command:** +```bash +anvil --fork-url https://mainnet.base.org --chain-id 8453 --port 8545 + +``` + + +2. **What happened?** +* Your computer started a local blockchain at `http://127.0.0.1:8545`. +* It has the **exact state** of Base Mainnet as of right now. +* You have 10 test wallets with 10,000 ETH each. +* **Impersonation:** You can use cast to act as a whale: +```bash +# Send a transaction pretending to be a specific address (e.g., a known whale) +cast send --rpc-url http://127.0.0.1:8545 --unlocked --from + +``` + + + + + +### Method B: Using Hardhat + +*Best for: Running your Solidity test suite against real-world conditions.* + +1. **Configure `hardhat.config.js`:** +```javascript +module.exports = { + solidity: "0.8.24", + networks: { + hardhat: { + forking: { + // It is highly recommended to use an API key here, not the public endpoint + url: "https://base-mainnet.g.alchemy.com/v2/YOUR_KEY", + // Pinning a block ensures tests pass consistently every time you run them + blockNumber: 12543210 + } + } + } +}; + +``` + + +2. **Usage:** When you run `npx hardhat test`, Hardhat will download the data from that specific block number and run your tests as if they were happening on Base Mainnet at that moment in history. + +--- + +### Summary Checklist + +| Component | Development | Production | +| --- | --- | --- | +| **RPC URL** | Localhost (Anvil/Hardhat) | Fallback Array (Alchemy -> Quicknode -> Public) | +| **Data History** | Latest Block | Archival Mode (for deep history) | +| **Gas Costs** | Free (Simulated) | Real ETH (Optimized via Multicall) | +| **Error Handling** | Console Log | Auto-Retry & Chunking Logic | +