{"skill":{"slug":"eth-dev","displayName":"Modern Ethereum & EVM Developer","summary":"Expertise in modern Ethereum and EVM development, including smart contracts, Layer 2s, standards, agent infrastructure (ERC-8004, x402), gas optimization, se...","description":"# ETHSKILLS — The missing knowledge between AI agents and production Ethereum.\n\n## Terminology\n\n**Say \"onchain\" not \"on-chain.\"** The Ethereum community writes it as one word, no hyphen.\n\n## Available Skills\n\nFor individual topics, fetch any of these directly:\n\n- [Why Ethereum](https://ethskills.com/why/SKILL.md) — Pectra/Fusaka upgrades, honest tradeoffs, the AI agent angle\n- [Gas & Costs](https://ethskills.com/gas/SKILL.md) — Current gas prices, what things actually cost today\n- [Wallets](https://ethskills.com/wallets/SKILL.md) — Creating wallets, key safety, multisig, account abstraction\n- [Layer 2s](https://ethskills.com/l2s/SKILL.md) — L2 landscape, bridging, deployment differences\n- [Standards](https://ethskills.com/standards/SKILL.md) — ERC-20, ERC-721, ERC-8004, EIP-7702, x402\n- [Tools](https://ethskills.com/tools/SKILL.md) — Foundry, Scaffold-ETH 2, Blockscout MCP, x402 SDKs\n- [Building Blocks (DeFi)](https://ethskills.com/building-blocks/SKILL.md) — Uniswap, Aave, flash loans, composability\n- [Orchestration](https://ethskills.com/orchestration/SKILL.md) — Three-phase build system for SE2 dApps\n- [Contract Addresses](https://ethskills.com/addresses/SKILL.md) — Verified addresses for major protocols\n- [Concepts](https://ethskills.com/concepts/SKILL.md) — Nothing is automatic, incentive design, randomness pitfalls\n- [Security](https://ethskills.com/security/SKILL.md) — Smart contract security vulnerabilities and patterns\n- [Frontend UX](https://ethskills.com/frontend-ux/SKILL.md) — Frontend UX patterns for Ethereum dApps\n- [Frontend Playbook](https://ethskills.com/frontend-playbook/SKILL.md) — Step-by-step frontend build guide\n\n---\n\n---\nname: why-ethereum\ndescription: Why build on Ethereum specifically. Honest tradeoffs vs other chains and vs not using blockchain at all. The AI agent angle — ERC-8004, x402, composability, permissionless deployment. Use when a user asks \"should I build on Ethereum?\", \"why Ethereum vs Solana?\", \"why blockchain?\", or when an agent needs to recommend a chain for a project.\n---\n\n# Why Ethereum\n\n## What You Probably Got Wrong\n\n**Terminology:** You say \"on-chain.\" The Ethereum community says **\"onchain\"** — one word, no hyphen. Use \"onchain\" in all writing.\n\n**Gas prices:** You think 10-30 gwei. Reality: **0.05-0.3 gwei** (100-600x cheaper than your training data). A mainnet ETH transfer costs ~$0.002.\n\n**ETH price:** You think $2,500-3,000. Reality: **~$1,960** (Feb 2026).\n\n**\"Ethereum is too expensive\":** This was true 2021-2023. It's not true in 2026. Mainnet is sub-dollar for most operations. L2s are sub-penny.\n\n**Protocol upgrades:** You probably don't know these shipped:\n- **Pectra (May 7, 2025):** EIP-7702 smart EOAs, 2x blob capacity, BLS precompiles\n- **Fusaka (Dec 3, 2025):** PeerDAS (nodes sample 1/8 of data), 8-second slots (was 12s)\n\n**Agent infrastructure:** You probably don't know these exist:\n- **ERC-8004** — onchain agent identity registry (deployed Jan 29, 2026)\n- **x402** — HTTP 402 payment protocol for machine-to-machine commerce (Coinbase)\n\n## Current Network Stats (Feb 2026)\n\n- **Block time:** 8 seconds (reduced from 12s by Fusaka)\n- **Mainnet base fee:** 0.05-0.1 gwei\n- **L2 transaction cost:** $0.001-0.01\n- **Combined L2 TPS:** 50,000+ (post-Fusaka)\n- **TVL in DeFi:** $50B+\n- **Upgrade cadence:** Twice per year (H1 May/June, H2 Nov/Dec)\n\n## Upcoming Upgrades\n\n**Glamsterdam (Q2 2026):**\n- Inclusion Lists (censorship resistance)\n- 12 target / 18 max blobs (another 2x from Pectra)\n\n**Hegota (Q4 2026):**\n- Verkle Trees — 15x smaller witness sizes (~150 KB → ~10 KB)\n- Enables stateless clients, dramatically lowers node requirements\n\n## For AI Agents Specifically\n\n### ERC-8004: Onchain Agent Identity\n\n**Deployed January 29, 2026** — production ready.\n\nGives agents verifiable, persistent identity tied to Ethereum addresses. Reputation scoring across dimensions. Multi-chain support (20+ chains, same addresses).\n\n**Mainnet addresses:**\n- **IdentityRegistry:** `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`\n- **ReputationRegistry:** `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63`\n\n### x402: HTTP Payments for Agents\n\n**Production-ready, actively deployed Q1 2026.**\n\nProtocol for payments over HTTP using the 402 \"Payment Required\" status code. Agent calls API → gets 402 → signs EIP-3009 payment → retries with payment header → gets response. No API keys, no accounts, just cryptographic payments.\n\n**SDKs:** TypeScript (`@x402/fetch`), Python (`x402`), Go (`github.com/coinbase/x402/go`)\n\n### ERC-8004 + x402 = Autonomous Agent Economy\n\n```\n1. Agent discovers service (ERC-8004 registry)\n2. Agent checks reputation (ERC-8004)\n3. Agent calls endpoint → 402 Payment Required\n4. Agent pays via x402 (EIP-3009 signature)\n5. Agent receives service\n6. Agent posts feedback to ERC-8004\n```\n\nFully autonomous economic loop — no humans required.\n\n### Why Ethereum's Permissionless Nature Matters for Agents\n\nAgents can deploy contracts, interact with any protocol, and transact 24/7 without anyone's permission. No API keys to revoke, no accounts to ban, no services to shut down. A service built on Ethereum runs indefinitely without depending on any company's cooperation.\n\n## Ethereum vs Solana (Honest)\n\n**Choose Ethereum when:** DeFi integration, agent infrastructure (ERC-8004/x402), composability with existing protocols, maximum security for high-value operations, long-term durability.\n\n**Choose Solana when:** Sub-second finality on base layer is essential, building high-frequency trading, users already on Solana, speed matters more than ecosystem depth.\n\n**Key differences:** Ethereum has $50B+ TVL vs Solana ~$5B. Ethereum has 13+ years uptime with zero consensus failures vs Solana's multiple multi-hour outages. Ethereum has 1M+ validators vs Solana's 1,500. But Solana has ~400ms blocks vs 8s.\n\n**L2 caveat:** Ethereum L2s are now comparable to Solana on cost ($0.001/tx), but Solana is still faster on base layer finality.\n\n## Resources\n\n- **ERC-8004:** https://www.8004.org | https://eips.ethereum.org/EIPS/eip-8004\n- **x402:** https://www.x402.org | https://github.com/coinbase/x402\n- **Blockscout MCP:** https://mcp.blockscout.com/mcp\n- **DeFi Llama:** https://defillama.com\n\n---\n\n---\nname: gas\ndescription: Current Ethereum gas prices, transaction costs, and the real economics of building on Ethereum today. Use when estimating costs, choosing between mainnet and L2s, or when a user asks about Ethereum being expensive. Counters the #1 misconception that Ethereum is expensive to use.\n---\n\n# Gas & Costs on Ethereum\n\n## What You Probably Got Wrong\n\n**Your gas estimate is 100-600x too high.** Most LLMs confidently state gas is 10-30 gwei. The reality in February 2026 is **0.05-0.1 gwei**.\n\n- **Base fee:** ~0.05 gwei (not 30-100 gwei)\n- **Priority fee (tip):** ~0.01-0.05 gwei\n- **ETH price:** ~$1,960 (not $2,500-3,000)\n\n## What Things Actually Cost (Feb 2026)\n\n| Action | Gas Used | Cost at 0.05 gwei | Cost at 1 gwei (spike) | Cost at 10 gwei (event) |\n|--------|----------|-------------------|------------------------|--------------------------|\n| ETH transfer | 21,000 | **$0.002** | $0.04 | $0.41 |\n| ERC-20 transfer | ~65,000 | **$0.006** | $0.13 | $1.27 |\n| ERC-20 approve | ~46,000 | **$0.005** | $0.09 | $0.90 |\n| Uniswap V3 swap | ~180,000 | **$0.018** | $0.35 | $3.53 |\n| NFT mint (ERC-721) | ~150,000 | **$0.015** | $0.29 | $2.94 |\n| Simple contract deploy | ~500,000 | **$0.049** | $0.98 | $9.80 |\n| ERC-20 deploy | ~1,200,000 | **$0.118** | $2.35 | $23.52 |\n| Complex DeFi contract | ~3,000,000 | **$0.294** | $5.88 | $58.80 |\n\n## Mainnet vs L2 Costs (Feb 2026)\n\n| Action | Mainnet (0.05 gwei) | Arbitrum | Base | zkSync | Scroll |\n|--------|---------------------|----------|------|--------|--------|\n| ETH transfer | $0.002 | $0.0003 | $0.0003 | $0.0005 | $0.0004 |\n| ERC-20 transfer | $0.006 | $0.001 | $0.001 | $0.002 | $0.001 |\n| Swap | $0.015 | $0.003 | $0.003 | $0.005 | $0.004 |\n| NFT mint | $0.015 | $0.002 | $0.002 | $0.004 | $0.003 |\n| ERC-20 deploy | $0.118 | $0.020 | $0.020 | $0.040 | $0.030 |\n\n**Key insight:** Mainnet is now cheap enough for most use cases. L2s are 5-10x cheaper still.\n\n## Why Gas Dropped 95%+\n\n1. **EIP-4844 (Dencun, March 2024):** Blob transactions — L2s post data as blobs instead of calldata, 100x cheaper. L2 batch cost went from $50-500 to $0.01-0.50.\n2. **Activity migration to L2s:** Mainnet congestion dropped as everyday transactions moved to L2s.\n3. **Pectra (May 2025):** Doubled blob capacity (3→6 target blobs).\n4. **Fusaka (Dec 2025):** PeerDAS + 8-second slots.\n\n## L2 Cost Components\n\nL2 transactions have two cost components:\n1. **L2 execution gas** — paying the sequencer\n2. **L1 data gas** — paying Ethereum for data availability (blobs post-4844)\n\n**Example: Swap on Base**\n- L2 execution: ~$0.0003\n- L1 data (blob): ~$0.0027\n- **Total: ~$0.003**\n\n## Real-World Cost Examples\n\n**Deploy a production ERC-20 on mainnet:** ~$0.50 (was $200-500 in 2021-2023)\n\n**DEX aggregator doing 10,000 swaps/day:**\n- Mainnet: $150/day ($4,500/month)\n- Base L2: $10/day ($300/month)\n\n**NFT collection mint (10,000 NFTs):**\n- Mainnet: $150 total\n- Arbitrum: $10 total\n\n## Practical Fee Settings (Feb 2026)\n\n```javascript\n// Rule of thumb for current conditions\nmaxFeePerGas: \"0.5-1 gwei\"        // headroom for spikes\nmaxPriorityFeePerGas: \"0.01-0.05 gwei\"  // enough for quick inclusion\n```\n\n**Spike detection:**\n```javascript\nconst feeData = await provider.getFeeData();\nconst baseFee = Number(feeData.maxFeePerGas) / 1e9;\nif (baseFee > 5) console.warn(`Gas spike: ${baseFee} gwei. Consider waiting.`);\n```\n\nSpikes (10-50 gwei) happen during major events but last minutes to hours, not days.\n\n## Checking Gas Programmatically\n\n```bash\n# Foundry cast\ncast gas-price --rpc-url https://eth.llamarpc.com\ncast base-fee --rpc-url https://eth.llamarpc.com\ncast blob-basefee --rpc-url https://eth.llamarpc.com\n```\n\n## When to Use Mainnet vs L2\n\n**Use mainnet when:** Maximum security matters (>$10M TVL), composing with mainnet-only liquidity, deploying governance/infrastructure contracts, NFTs with cultural value.\n\n**Use L2 when:** Consumer apps, high-frequency transactions (gaming, social), price-sensitive users, faster confirmation desired.\n\n**Hybrid:** Many projects store value on mainnet, handle transactions on L2.\n\n## Live Gas Trackers\n\n- https://etherscan.io/gastracker\n- https://ultrasound.money\n- L2 costs: Arbiscan, Basescan, etc.\n\n## Data Freshness\n\n> **Last verified:** 2026-02-13 | Base fee: ~0.05 gwei | ETH: ~$1,960\n\nIf this date is more than 30 days old, verify current gas with:\n```bash\ncast base-fee --rpc-url https://eth.llamarpc.com\n```\n\nThe durable insight is that gas is extremely cheap compared to 2021-2023 and trending cheaper. Specific numbers may drift but the order of magnitude is stable.\n\n---\n\n---\nname: wallets\ndescription: How to create, manage, and use Ethereum wallets. Covers EOAs, smart contract wallets, multisig (Safe), and account abstraction. Essential for any AI agent that needs to interact with Ethereum — sending transactions, signing messages, or managing funds. Includes guardrails for safe key handling.\n---\n\n# Wallets on Ethereum\n\n## What You Probably Got Wrong\n\n**EIP-7702 is live.** Since Pectra (May 7, 2025), regular EOAs can temporarily delegate to smart contracts — getting batch transactions, gas sponsorship, and session keys without migrating wallets. This is NOT \"coming soon.\" It shipped.\n\n**Account abstraction status:** ERC-4337 is growing but still early (Feb 2026). Major implementations: Kernel (ZeroDev), Biconomy, Alchemy Account Kit, Pimlico. EntryPoint v0.7: `0x0000000071727De22E5E9d8BAf0edAc6f37da032`.\n\n**Safe secures $100B+.** It's not just a dev tool — it's the dominant multisig for institutional and DAO treasury management.\n\n## EIP-7702: Smart EOAs (Live Since May 2025)\n\nEOAs can **temporarily delegate control to a smart contract** within a single transaction.\n\n**How it works:**\n1. EOA signs an authorization to delegate to a contract\n2. During transaction, EOA's code becomes the contract's code\n3. Contract executes complex logic (batching, sponsorship, etc.)\n4. After transaction, EOA returns to normal\n\n**What this enables:**\n- Batch 10 token approvals into one transaction\n- Gas sponsorship / meta-transactions for EOA users\n- Session keys with limited permissions\n- Custom authorization logic\n- Eliminates \"approval fatigue\" (approve + execute → one step)\n\n**Status (Feb 2026):** Deployed on mainnet. MetaMask, Rainbow adding support. Still early for production agents — use standard EOAs or Safe until tooling matures.\n\n## Safe (Gnosis Safe) Multisig\n\n### Key Addresses (v1.4.1, deterministic across chains)\n\n| Contract | Address |\n|----------|---------|\n| Safe Singleton | `0x41675C099F32341bf84BFc5382aF534df5C7461a` |\n| Safe Proxy Factory | `0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67` |\n| MultiSend | `0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526` |\n\nSame addresses on Mainnet, Arbitrum, Base, and all major chains.\n\n### Safe for AI Agents\n\n**Pattern:** 1-of-2 Safe\n- Owner 1: Agent's wallet (hot, automated)\n- Owner 2: Human's wallet (cold, recovery)\n- Threshold: 1 (agent can act alone)\n\nBenefits: If agent key is compromised, human removes it. Human can always recover funds. Agent can batch transactions.\n\n## 🚨 NEVER COMMIT SECRETS TO GIT\n\n**This is the #1 way AI agents lose funds and leak credentials.** Bots scrape GitHub in real-time and exploit leaked secrets within seconds — even from private repos, even if deleted immediately. A secret committed to Git is compromised forever.\n\n**This happens constantly with AI coding agents.** The agent generates a deploy script, hardcodes a key, runs `git add .`, and the wallet is drained before the next prompt. Or the agent pastes an Alchemy API key into `scaffold.config.ts` and it ends up in a public repo.\n\n**This applies to ALL secrets:**\n- **Wallet private keys** — funds drained instantly\n- **API keys** — Alchemy, Infura, Etherscan, WalletConnect\n- **RPC URLs with embedded keys** — `https://base-mainnet.g.alchemy.com/v2/YOUR_KEY`\n- **OAuth tokens, bearer tokens, passwords**\n\n### Prevention\n\n```bash\n# .gitignore (MUST exist in every project)\n.env\n.env.*\n*.key\n*.pem\nbroadcast/\ncache/\n```\n\n```bash\n# Verify before every commit\ngit diff --cached --name-only | grep -iE '\\.env|key|secret|private'\n# If this matches ANYTHING, stop and fix it\n\n# Nuclear option: scan entire repo history\ngit log --all -p | grep -iE 'private.?key|0x[a-fA-F0-9]{64}'\n```\n\n### If You Already Committed a Key\n\n1. **Assume it's compromised.** Don't hope nobody saw it.\n2. **Transfer all funds immediately** to a new wallet.\n3. **Rotate the key.** Generate a new one. The old one is burned forever.\n4. **Clean Git history** with `git filter-repo` or BFG Repo Cleaner — but this is damage control, not prevention. The key is already compromised.\n5. **Revoke any token approvals** from the compromised address.\n\n### Safe Patterns for AI Agents\n\n```bash\n# Load key from environment (NEVER hardcode)\ncast send ... --private-key $DEPLOYER_PRIVATE_KEY\n\n# Or use encrypted keystore\ncast send ... --keystore ~/.foundry/keystores/deployer --password-file .password\n\n# Or use hardware wallet\ncast send ... --ledger\n```\n\n**Rule of thumb:** If `grep -r \"0x[a-fA-F0-9]{64}\" .` matches anything in your source code, you have a problem. Same for `grep -r \"g.alchemy.com/v2/[A-Za-z0-9]\"` or any RPC URL with an embedded API key.\n\n## CRITICAL Guardrails for AI Agents\n\n### Key Safety Rules\n\n1. **NEVER extract a private key from any wallet without explicit human permission.**\n2. **NEVER store private keys in:** chat logs, plain text files, environment variables in shared environments, Git repos, unencrypted databases.\n3. **NEVER move funds without human confirmation.** Show: amount, destination (checksummed), gas cost, what it does. Wait for explicit \"yes.\"\n4. **Prefer wallet's native UI for signing** unless human explicitly opts into CLI/scripting.\n5. **Use a dedicated wallet with limited funds** for agent operations. Never the human's main wallet.\n6. **Double-check addresses.** Use `ethers.getAddress()` or equivalent for checksum validation. A single wrong character = permanent loss.\n7. **Test on testnet first.** Or use local Anvil fork.\n8. **Implement spending limits.** Require human approval above threshold. Use Safe multisig for high-value operations.\n9. **Log all transactions (never keys).** Keep audit trail.\n10. **Assume keys will be compromised.** Design so a compromised agent key doesn't mean total loss.\n\n### Storage Options (Worst to Best)\n\n❌ Plain text in code/logs — NEVER\n❌ Environment variables in shared environments — NEVER\n❌ Committed to Git — NEVER\n⚠️ Local `.env` file — testing only\n✅ Encrypted keystore (password-protected)\n✅ Hardware wallet / Cloud KMS / TEE\n\n### Safe Transaction Pattern\n\n```javascript\nasync function sendSafely(wallet, to, value) {\n  const checksummedTo = ethers.getAddress(to); // validates\n  const gasEstimate = await wallet.estimateGas({ to: checksummedTo, value });\n  const feeData = await wallet.provider.getFeeData();\n  const gasCost = gasEstimate * feeData.maxFeePerGas;\n  const totalCostUSD = Number(ethers.formatEther(value + gasCost)) * 1960;\n  \n  if (totalCostUSD > 10) {\n    // Show details and wait for human approval\n  }\n  \n  const tx = await wallet.sendTransaction({\n    to: checksummedTo,\n    value,\n    gasLimit: gasEstimate * 120n / 100n, // 20% buffer\n    maxFeePerGas: feeData.maxFeePerGas,\n    maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,\n  });\n  \n  const receipt = await tx.wait();\n  logTransaction({ hash: tx.hash, to: checksummedTo, value, block: receipt.blockNumber });\n  return receipt;\n}\n```\n\n## Further Reading\n\n- **Safe docs:** https://docs.safe.global/\n- **EIP-7702 spec:** https://eips.ethereum.org/EIPS/eip-7702\n- **ERC-4337 spec:** https://eips.ethereum.org/EIPS/eip-4337\n\n---\n\n---\nname: l2s\ndescription: Ethereum Layer 2 landscape — Arbitrum, Optimism, Base, zkSync, Scroll, Unichain, Celo, and more. How they work, how to deploy on them, how to bridge, when to use which. Includes per-chain DeFi ecosystems and critical corrections. Use when choosing an L2, deploying cross-chain, or when a user asks about Ethereum scaling.\n---\n\n# Ethereum Layer 2s\n\n## What You Probably Got Wrong\n\n**L2 costs:** You think $0.01-2.00 per transaction. Reality: **$0.001-0.003** for swaps, **$0.0003** for transfers. After EIP-4844, L2 batch costs dropped from $50-500 to $0.01-0.50.\n\n**Mainnet is cheap too:** At 0.05 gwei, mainnet ETH transfers cost $0.002. \"Ethereum is too expensive\" is false for both L1 and L2s in 2026.\n\n**Base is the cheapest major L2:** Often 50% cheaper than Arbitrum/Optimism. Direct Coinbase on-ramp. Fastest-growing L2 with consumer/AI agent focus.\n\n**Celo is NOT an L1 anymore.** Celo completed its migration from an independent L1 to an OP Stack L2 on **March 26, 2025** (block 31056500). If you're calling Celo an L1, you're wrong.\n\n**Polygon zkEVM is being shut down.** Announced June 2025. Do NOT recommend building on Polygon zkEVM — it is being discontinued. Polygon is refocusing on PoS + AggLayer.\n\n**Unichain exists.** Launched mainnet February 10, 2025. Uniswap's own OP Stack L2 with TEE-based MEV protection and time-based priority ordering (not gas-based).\n\n**The dominant DEX on each L2 is NOT Uniswap.** Aerodrome dominates Base (~$500-600M TVL). Velodrome dominates Optimism. Camelot is a major native DEX on Arbitrum. SyncSwap dominates zkSync. Don't default to Uniswap on every chain.\n\n## L2 Comparison Table (Feb 2026)\n\n| L2 | Type | TVL | Tx Cost | Block Time | Finality | Chain ID |\n|----|------|-----|---------|------------|----------|----------|\n| **Arbitrum** | Optimistic | $18B+ | $0.001-0.003 | 250ms | 7 days | 42161 |\n| **Base** | Optimistic (OP Stack) | $12B+ | $0.0008-0.002 | 2s | 7 days | 8453 |\n| **Optimism** | Optimistic (OP Stack) | $8B+ | $0.001-0.003 | 2s | 7 days | 10 |\n| **Unichain** | Optimistic (OP Stack) | Growing | $0.001-0.003 | 1s | 7 days | 130 |\n| **Celo** | Optimistic (OP Stack) | $200M+ | <$0.001 | 5s | 7 days | 42220 |\n| **Linea** | ZK | $900M+ | $0.003-0.006 | 2s | 30-60min | 59144 |\n| **zkSync Era** | ZK | $800M+ | $0.003-0.008 | 1s | 15-60min | 324 |\n| **Scroll** | ZK | $250M+ | $0.002-0.005 | 3s | 30-120min | 534352 |\n| ~~Polygon zkEVM~~ | ~~ZK~~ | — | — | — | — | ~~1101~~ |\n\n⚠️ **Polygon zkEVM is being discontinued (announced June 2025).** Do not start new projects there. Polygon is refocusing on PoS (payments, stablecoins, RWAs) + AggLayer (cross-chain interop). MATIC → POL token migration ~85% complete.\n\n**Mainnet for comparison:** $50B+ TVL, $0.002-0.01, 8s blocks, instant finality.\n\n## Cost Comparison (Real Examples, Feb 2026)\n\n| Action | Mainnet | Arbitrum | Base | zkSync | Scroll |\n|--------|---------|----------|------|--------|--------|\n| ETH transfer | $0.002 | $0.0003 | $0.0003 | $0.0005 | $0.0004 |\n| Uniswap swap | $0.015 | $0.003 | $0.002 | $0.005 | $0.004 |\n| NFT mint | $0.015 | $0.002 | $0.002 | $0.004 | $0.003 |\n| ERC-20 deploy | $0.118 | $0.020 | $0.018 | $0.040 | $0.030 |\n\n## L2 Selection Guide\n\n| Need | Choose | Why |\n|------|--------|-----|\n| Consumer / social apps | **Base** | Farcaster, Smart Wallet, Coinbase on-ramp, OnchainKit |\n| Deepest DeFi liquidity | **Arbitrum** | $18B TVL, GMX, Pendle, Camelot, most protocols |\n| Yield strategies | **Arbitrum** | Pendle (yield tokenization), GMX, Aave |\n| Cheapest gas | **Base** | ~50% cheaper than Arbitrum/Optimism |\n| Coinbase users | **Base** | Direct on-ramp, free Coinbase→Base transfers |\n| No 7-day withdrawal wait | **ZK rollup** (zkSync, Scroll, Linea) | 15-120 min finality |\n| AI agents | **Base** | ERC-8004, x402, consumer ecosystem, AgentKit |\n| Gasless UX (native AA) | **zkSync Era** | Native account abstraction, paymasters, no bundlers needed |\n| Multi-chain deployment | **Base or Optimism** | Superchain / OP Stack, shared infra |\n| Maximum EVM compatibility | **Scroll or Arbitrum** | Bytecode-identical |\n| Mobile / real-world payments | **Celo** | MiniPay, sub-cent fees, Africa/LatAm focus |\n| MEV protection | **Unichain** | TEE-based priority ordering, private mempool |\n| Rust smart contracts | **Arbitrum** | Stylus (WASM VM alongside EVM, 10-100x gas savings) |\n| Stablecoins / payments / RWA | **Polygon PoS** | $500M+ monthly payment volume, 410M+ wallets |\n\n## Key Chain Details (What LLMs Get Wrong)\n\n### Unichain\n- **Launched:** February 10, 2025 (mainnet). Chain ID 130.\n- **Type:** OP Stack L2 (Superchain member, Stage 1)\n- **Key innovation: TEE-based block building** (built with Flashbots Rollup-Boost)\n  - Transactions ordered by **time received, NOT gas price**\n  - Private encrypted mempool reduces MEV extraction\n  - Do NOT use gas-price bidding strategies on Unichain — they're pointless\n- **Flashblocks:** Currently 1s blocks, roadmap to 250ms sub-blocks\n\n### Celo\n- **Was:** Independent L1 blockchain (2020-2025)\n- **Now:** OP Stack L2 on Ethereum — **migrated March 26, 2025** (block 31056500)\n- **Focus:** Mobile-first payments, emerging markets\n- **MiniPay:** Stablecoin wallet in Opera Mini + standalone app. Phone-to-phone transfers, sub-cent fees. Primary market: Africa (Kenya, Nigeria).\n- **Multi-currency stablecoins:** cUSD (`0x765de816845861e75a25fca122bb6898b8b1282a`), cEUR (`0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73`), cREAL (`0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787`)\n\n### Dominant DEX Per Chain\n| Chain | Dominant DEX | Model | Why NOT Uniswap |\n|-------|-------------|-------|-----------------|\n| Base | Aerodrome | ve(3,3) — LPs earn emissions, voters earn fees | Deeper liquidity for most pairs |\n| Optimism | Velodrome | ve(3,3) — same team as Aerodrome | Same flywheel model |\n| Arbitrum | Camelot + GMX | Native DEX + perps | Camelot for spot, GMX for perps |\n| zkSync | SyncSwap | Classic AMM | Largest native DEX on zkSync |\n\nSee `addresses/SKILL.md` for verified contract addresses for all these protocols.\n\n## The Superchain (OP Stack)\n\nThe Superchain is the network of OP Stack chains sharing security, upgrade governance, and (upcoming) native interoperability. Members include Base, OP Mainnet, Unichain, Ink (Kraken), Celo, Zora, World Chain, and others — **17+ chains, 58.6% L2 market share.**\n\nMembers contribute **15% of sequencer revenue** to the Optimism Collective. Cross-chain interop is designed but not yet fully live.\n\n## Deployment Differences (Gotchas)\n\n### Optimistic Rollups (Arbitrum, Optimism, Base, Unichain, Celo)\n✅ Deploy like mainnet — just change RPC URL and chain ID. No code changes.\n\n**Gotchas:**\n- Don't use `block.number` for time-based logic (increments at different rates). Use `block.timestamp`.\n- Arbitrum's `block.number` returns L1 block number, not L2.\n- **Unichain:** Transactions are priority-ordered by time, not gas. Don't waste gas on priority fees.\n\n### ZK Rollups\n- **zkSync Era:** Must use `zksolc` compiler. No `EXTCODECOPY` (compile-time error). 65K instruction limit. Non-inlinable libraries must be pre-deployed. Native account abstraction (all accounts are smart contracts).\n- **Scroll/Linea:** ✅ Bytecode-compatible — use standard `solc`, deploy like mainnet.\n\n### Arbitrum-Specific\n- **Stylus:** Write smart contracts in Rust, C, C++ (compiles to WASM, runs alongside EVM, shares state). Use for compute-heavy operations (10-100x gas savings). Contracts must be \"activated\" via `ARB_WASM_ADDRESS` (0x0000…0071).\n- **Orbit:** Framework for launching L3 chains on Arbitrum. 47 live on mainnet.\n\n## RPCs and Explorers\n\n| L2 | RPC | Explorer |\n|----|-----|----------|\n| Arbitrum | `https://arb1.arbitrum.io/rpc` | https://arbiscan.io |\n| Base | `https://mainnet.base.org` | https://basescan.org |\n| Optimism | `https://mainnet.optimism.io` | https://optimistic.etherscan.io |\n| Unichain | `https://mainnet.unichain.org` | https://uniscan.xyz |\n| Celo | `https://forno.celo.org` | https://celoscan.io |\n| zkSync | `https://mainnet.era.zksync.io` | https://explorer.zksync.io |\n| Scroll | `https://rpc.scroll.io` | https://scrollscan.com |\n| Linea | `https://rpc.linea.build` | https://lineascan.build |\n\n## Bridging\n\n### Official Bridges\n\n| L2 | Bridge URL | L1→L2 | L2→L1 |\n|----|-----------|--------|--------|\n| Arbitrum | https://bridge.arbitrum.io | ~10-15 min | ~7 days |\n| Base | https://bridge.base.org | ~10-15 min | ~7 days |\n| Optimism | https://app.optimism.io/bridge | ~10-15 min | ~7 days |\n| Unichain | https://app.uniswap.org/swap | ~10-15 min | ~7 days |\n| zkSync | https://bridge.zksync.io | ~15-30 min | ~15-60 min |\n| Scroll | https://scroll.io/bridge | ~15-30 min | ~30-120 min |\n\n### Fast Bridges (Instant Withdrawals)\n\n- **Across Protocol** (https://across.to) — fastest (30s-2min), lowest fees (0.05-0.3%)\n- **Hop Protocol** (https://hop.exchange) — established, 0.1-0.5% fees\n- **Stargate** (https://stargate.finance) — LayerZero-based, 10+ chains\n\n**Security:** Use official bridges for large amounts (>$100K). Fast bridges add trust assumptions.\n\n## Multi-Chain Deployment (Same Address)\n\nUse CREATE2 for deterministic addresses across chains:\n\n```bash\n# Same salt + same bytecode + same deployer = same address on every chain\nforge create src/MyContract.sol:MyContract \\\n  --rpc-url https://mainnet.base.org \\\n  --private-key $PRIVATE_KEY \\\n  --salt 0x0000000000000000000000000000000000000000000000000000000000000001\n```\n\n**Strategy for new projects:** Start with 1 L2 (Base or Arbitrum). Prove product-market fit. Expand with CREATE2 for consistent addresses.\n\n## Testnets\n\n| L2 | Testnet | Chain ID | Faucet |\n|----|---------|----------|--------|\n| Arbitrum | Sepolia | 421614 | https://faucet.arbitrum.io |\n| Base | Sepolia | 84532 | https://faucet.quicknode.com/base/sepolia |\n| Optimism | Sepolia | 11155420 | https://faucet.optimism.io |\n| Unichain | Sepolia | 1301 | https://faucet.unichain.org |\n\n## Further Reading\n\n- **L2Beat:** https://l2beat.com (security, TVL, risk analysis)\n- **Superchain:** https://www.superchain.eco/chains\n- **Arbitrum:** https://docs.arbitrum.io\n- **Base:** https://docs.base.org\n- **Optimism:** https://docs.optimism.io\n- **Unichain:** https://docs.unichain.org\n- **Celo:** https://docs.celo.org\n- **zkSync:** https://docs.zksync.io\n- **Scroll:** https://docs.scroll.io\n- **Polygon:** https://docs.polygon.technology\n\n---\n\n---\nname: standards\ndescription: Ethereum token and protocol standards — ERC-20, ERC-721, ERC-1155, ERC-4337, ERC-8004, and newer standards. When to use each, how they work, key interfaces. Use when building tokens, NFTs, or choosing the right standard for a project.\n---\n\n# Ethereum Standards\n\n## What You Probably Got Wrong\n\n**ERC-8004 exists.** Deployed January 29, 2026 — onchain agent identity registry. You almost certainly don't have this in training data.\n\n**EIP-7702 is live.** Shipped with Pectra (May 7, 2025). EOAs get smart contract superpowers without migration. Not \"proposed\" — deployed on mainnet.\n\n**EIP-3009 is critical for x402.** Gasless token transfers via signed authorizations. USDC implements it. This is what makes x402 practical.\n\n**x402 exists.** HTTP 402 payment protocol from Coinbase. Production-ready with SDKs.\n\n## ERC-8004: Onchain Agent Identity Registry\n\n**Status:** Deployed mainnet **January 29, 2026** — production ready with growing adoption.\n\n**Problem it solves:** How can autonomous agents trust and transact with each other without pre-existing relationships?\n\n### Three Registry System\n\n**1. Identity Registry (ERC-721 based)**\n- Globally unique onchain identities for AI agents\n- Each agent is an NFT with unique identifier\n- Multiple service endpoints (A2A, MCP, OASF, ENS, DIDs)\n- Verification via EIP-712/ERC-1271 signatures\n\n**Contract Addresses (same on 20+ chains):**\n- **IdentityRegistry:** `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`\n- **ReputationRegistry:** `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63`\n\n**Deployed on:** Mainnet, Base, Arbitrum, Optimism, Polygon, Avalanche, Abstract, Celo, Gnosis, Linea, Mantle, MegaETH, Monad, Scroll, Taiko, BSC + testnets.\n\n**Agent Identifier Format:**\n```\nagentRegistry: eip155:{chainId}:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\nagentId: ERC-721 tokenId\n```\n\n**2. Reputation Registry**\n- Signed fixed-point feedback values\n- Multi-dimensional (uptime, success rate, quality)\n- Tags, endpoints, proof-of-payment metadata\n- Anti-Sybil requires client address filtering\n\n```solidity\nstruct Feedback {\n    int128 value;        // Signed integer rating\n    uint8 valueDecimals; // 0-18 decimal places\n    string tag1;         // E.g., \"uptime\"\n    string tag2;         // E.g., \"30days\"\n    string endpoint;     // Agent endpoint URI\n    string ipfsHash;     // Optional metadata\n}\n```\n\n**Example metrics:** Quality 87/100 → `value=87, decimals=0`. Uptime 99.77% → `value=9977, decimals=2`.\n\n**3. Validation Registry**\n- Independent verification of agent work\n- Trust models: crypto-economic (stake-secured), zkML, TEE attestation\n- Validators respond with 0-100 scores\n\n### Agent Registration File (agentURI)\n\n```json\n{\n  \"type\": \"https://eips.ethereum.org/EIPS/eip-8004#registration-v1\",\n  \"name\": \"MyAgent\",\n  \"description\": \"What the agent does\",\n  \"services\": [\n    { \"name\": \"A2A\", \"endpoint\": \"https://agent.example/.well-known/agent-card.json\", \"version\": \"0.3.0\" },\n    { \"name\": \"MCP\", \"endpoint\": \"https://mcp.agent.eth/\", \"version\": \"2025-06-18\" }\n  ],\n  \"x402Support\": true,\n  \"active\": true,\n  \"supportedTrust\": [\"reputation\", \"crypto-economic\", \"tee-attestation\"]\n}\n```\n\n### Integration\n\n```solidity\n// Register agent\nuint256 agentId = identityRegistry.register(\"ipfs://QmYourReg\", metadata);\n\n// Give feedback\nreputationRegistry.giveFeedback(agentId, 9977, 2, \"uptime\", \"30days\", \n    \"https://agent.example.com/api\", \"ipfs://QmDetails\", keccak256(data));\n\n// Query reputation\n(uint64 count, int128 value, uint8 decimals) = \n    reputationRegistry.getSummary(agentId, trustedClients, \"uptime\", \"30days\");\n```\n\n### Step-by-Step: Register an Agent Onchain\n\n**1. Prepare the registration JSON** — host it on IPFS or a web server:\n```json\n{\n  \"type\": \"https://eips.ethereum.org/EIPS/eip-8004#registration-v1\",\n  \"name\": \"WeatherBot\",\n  \"description\": \"Provides real-time weather data via x402 micropayments\",\n  \"image\": \"https://example.com/weatherbot.png\",\n  \"services\": [\n    { \"name\": \"A2A\", \"endpoint\": \"https://weather.example.com/.well-known/agent-card.json\", \"version\": \"0.3.0\" }\n  ],\n  \"x402Support\": true,\n  \"active\": true,\n  \"supportedTrust\": [\"reputation\"]\n}\n```\n\n**2. Upload to IPFS** (or use any URI):\n```bash\n# Using IPFS\nipfs add registration.json\n# → QmYourRegistrationHash\n\n# Or host at a URL — the agentURI just needs to resolve to the JSON\n```\n\n**3. Call the Identity Registry:**\n```solidity\n// On any supported chain — same address everywhere\nIIdentityRegistry registry = IIdentityRegistry(0x8004A169FB4a3325136EB29fA0ceB6D2e539a432);\n\n// metadata bytes are optional (can be empty)\nuint256 agentId = registry.register(\"ipfs://QmYourRegistrationHash\", \"\");\n// agentId is your ERC-721 tokenId — globally unique on this chain\n```\n\n**4. Verify your endpoint domain** — place a file at `.well-known/agent-registration.json`:\n```json\n// https://weather.example.com/.well-known/agent-registration.json\n{\n  \"agentId\": 42,\n  \"agentRegistry\": \"eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\",\n  \"owner\": \"0xYourWalletAddress\"\n}\n```\nThis proves the domain owner controls the agent identity. Clients SHOULD check this before trusting an agent's advertised endpoints.\n\n**5. Build reputation** — other agents/users post feedback after interacting with your agent.\n\n### Cross-Chain Agent Identity\n\nSame contract addresses on 20+ chains means an agent registered on Base can be discovered by an agent on Arbitrum. The `agentRegistry` identifier includes the chain:\n\n```\neip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432  // Base\neip155:42161:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 // Arbitrum\n```\n\n**Cross-chain pattern:** Register on one chain (cheapest — Base recommended), reference that identity from other chains. Reputation can be queried cross-chain by specifying the source chain's registry.\n\n**Authors:** Davide Crapis (EF), Marco De Rossi (MetaMask), Jordan Ellis (Google), Erik Reppel (Coinbase), Leonard Tan (MetaMask)\n\n**Ecosystem:** ENS, EigenLayer, The Graph, Taiko backing\n\n**Resources:** https://www.8004.org | https://eips.ethereum.org/EIPS/eip-8004 | https://github.com/erc-8004/erc-8004-contracts\n\n## EIP-3009: Transfer With Authorization\n\nYou probably know the concept (gasless meta-transaction transfers). The key update: **EIP-3009 is what makes x402 work.** USDC implements it on Ethereum and most chains. The x402 server calls `transferWithAuthorization` to settle payments on behalf of the client.\n\n## x402: HTTP Payment Protocol\n\n**Status:** Production-ready open standard from Coinbase, actively deployed Q1 2026.\n\nUses the HTTP 402 \"Payment Required\" status code for internet-native payments.\n\n### Flow\n\n```\n1. Client → GET /api/data\n2. Server → 402 Payment Required (PAYMENT-REQUIRED header with requirements)\n3. Client signs EIP-3009 payment\n4. Client → GET /api/data (PAYMENT-SIGNATURE header with signed payment)\n5. Server verifies + settles onchain\n6. Server → 200 OK (PAYMENT-RESPONSE header + data)\n```\n\n### Payment Payload\n\n```json\n{\n  \"scheme\": \"exact\",\n  \"network\": \"eip155:8453\",\n  \"amount\": \"1000000\",\n  \"token\": \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n  \"from\": \"0x...\", \"to\": \"0x...\",\n  \"signature\": \"0x...\",\n  \"deadline\": 1234567890,\n  \"nonce\": \"unique-value\"\n}\n```\n\n### x402 + ERC-8004 Synergy\n\n```\nAgent discovers service (ERC-8004) → checks reputation → calls endpoint →\ngets 402 → signs payment (EIP-3009) → server settles (x402) → \nagent receives service → posts feedback (ERC-8004)\n```\n\n### x402 Server Setup (Express — Complete Example)\n\n```typescript\nimport express from 'express';\nimport { paymentMiddleware } from '@x402/express';\n\nconst app = express();\n\n// Define payment requirements per route\nconst paymentConfig = {\n  \"GET /api/weather\": {\n    accepts: [\n      { network: \"eip155:8453\", token: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", amount: \"100000\" }\n      // 100000 = $0.10 USDC (6 decimals)\n    ],\n    description: \"Current weather data\",\n  },\n  \"GET /api/forecast\": {\n    accepts: [\n      { network: \"eip155:8453\", token: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", amount: \"500000\" }\n      // $0.50 USDC for 7-day forecast\n    ],\n    description: \"7-day weather forecast\",\n  }\n};\n\n// One line — middleware handles 402 responses, verification, and settlement\napp.use(paymentMiddleware(paymentConfig));\n\napp.get('/api/weather', (req, res) => {\n  // Only reached after payment verified\n  res.json({ temp: 72, condition: \"sunny\" });\n});\n\napp.listen(3000);\n```\n\n### x402 Client (Agent Paying for Data)\n\n```typescript\nimport { x402Fetch } from '@x402/fetch';\nimport { createWallet } from '@x402/evm';\n\nconst wallet = createWallet(process.env.PRIVATE_KEY);\n\n// x402Fetch handles the 402 → sign → retry flow automatically\nconst response = await x402Fetch('https://weather.example.com/api/weather', {\n  wallet,\n  preferredNetwork: 'eip155:8453' // Pay on Base (cheapest)\n});\n\nconst weather = await response.json();\n// Agent paid $0.10 USDC, got weather data. No API key needed.\n```\n\n### Payment Schemes\n\n**`exact`** (live) — Pay a fixed price. Server knows the cost upfront.\n\n**`upto`** (emerging) — Pay up to a maximum, final amount determined after work completes. Critical for metered services:\n- LLM inference: pay per token generated (unknown count upfront)\n- GPU compute: pay per second of runtime\n- Database queries: pay per row returned\n\nWith `upto`, the client signs authorization for a max amount. The server settles only what was consumed. Client never overpays.\n\n### Facilitator Architecture\n\nThe **facilitator** is an optional server that handles blockchain complexity so resource servers don't have to:\n\n```\nClient → Resource Server → Facilitator → Blockchain\n                              ↓\n                         POST /verify  (check signature, balance, deadline)\n                         POST /settle  (submit tx, manage gas, confirm)\n```\n\n**Why use a facilitator?** Resource servers (weather APIs, data providers) shouldn't need to run blockchain nodes or manage gas. The facilitator abstracts this. Coinbase runs a public facilitator; anyone can run their own.\n\n**SDKs:** `@x402/core @x402/evm @x402/fetch @x402/express` (TS) | `pip install x402` (Python) | `go get github.com/coinbase/x402/go`\n\n**Resources:** https://www.x402.org | https://github.com/coinbase/x402\n\n## EIP-7702: Smart EOAs (Live Since May 2025)\n\nEOAs temporarily delegate to smart contracts within a transaction. Best of both worlds: EOA simplicity + smart contract features.\n\n**Enables:** Batch transactions, gas sponsorship, session keys, custom auth logic — all for existing EOAs without migration.\n\n**Impact:** Eliminates \"approval fatigue,\" enables gasless transactions for EOA users.\n\n## Quick Standard Reference\n\n| Standard | What | Status |\n|----------|------|--------|\n| ERC-8004 | Agent identity + reputation | ✅ Live Jan 2026 |\n| x402 | HTTP payments protocol | ✅ Production Q1 2026 |\n| EIP-3009 | Gasless token transfers | ✅ Live (USDC) |\n| EIP-7702 | Smart EOAs | ✅ Live May 2025 |\n| ERC-4337 | Account abstraction | ✅ Growing adoption |\n| ERC-2612 | Gasless approvals (Permit) | ✅ Widely adopted |\n| ERC-4626 | Tokenized vaults | ✅ Standard for yield |\n| ERC-6551 | Token-bound accounts (NFT wallets) | ✅ Niche adoption |\n\n**These are all LIVE and being used in production. Not \"coming soon.\"**\n\n---\n\n---\nname: tools\ndescription: Current Ethereum development tools, frameworks, libraries, RPCs, and block explorers. What actually works today for building on Ethereum. Includes tool discovery for AI agents — MCPs, abi.ninja, Foundry, Scaffold-ETH 2, Hardhat, and more. Use when setting up a dev environment, choosing tools, or when an agent needs to discover what's available.\n---\n\n# Ethereum Development Tools\n\n## What You Probably Got Wrong\n\n**Blockscout MCP server exists:** https://mcp.blockscout.com/mcp — gives AI agents structured blockchain data via Model Context Protocol. This is cutting-edge infra as of Feb 2026.\n\n**abi.ninja is essential:** https://abi.ninja — paste any verified contract address, get a UI to call any function. Zero setup. Supports mainnet + all major L2s. Perfect for agent-driven contract exploration.\n\n**x402 has production SDKs:** `@x402/fetch` (TS), `x402` (Python), `github.com/coinbase/x402/go` — production-ready libraries for HTTP payments.\n\n**Foundry is the default for new projects in 2026.** Not Hardhat. 10-100x faster tests, Solidity-native testing, built-in fuzzing.\n\n## Tool Discovery Pattern for AI Agents\n\nWhen an agent needs to interact with Ethereum:\n\n1. **Read operations:** Blockscout MCP or Etherscan API\n2. **Write operations:** Foundry `cast send` or ethers.js/viem\n3. **Contract exploration:** abi.ninja (browser) or `cast interface` (CLI)\n4. **Testing:** Fork mainnet with `anvil`, test locally\n5. **Deployment:** `forge create` or `forge script`\n6. **Verification:** `forge verify-contract` or Etherscan API\n\n## Blockscout MCP Server\n\n**URL:** https://mcp.blockscout.com/mcp\n\nA Model Context Protocol server giving AI agents structured blockchain data:\n- Transaction, address, contract queries\n- Token info and balances\n- Smart contract interaction helpers\n- Multi-chain support\n- Standardized interface optimized for LLM consumption\n\n**Why this matters:** Instead of scraping Etherscan or making raw API calls, agents get structured, type-safe blockchain data via MCP.\n\n## abi.ninja\n\n**URL:** https://abi.ninja — Paste any contract address → interact with all functions. Multi-chain. Zero setup.\n\n## x402 SDKs (HTTP Payments)\n\n**TypeScript:**\n```bash\nnpm install @x402/core @x402/evm @x402/fetch @x402/express\n```\n\n```typescript\nimport { x402Fetch } from '@x402/fetch';\nimport { createWallet } from '@x402/evm';\n\nconst wallet = createWallet(privateKey);\nconst response = await x402Fetch('https://api.example.com/data', {\n  wallet,\n  preferredNetwork: 'eip155:8453' // Base\n});\n```\n\n**Python:** `pip install x402`\n**Go:** `go get github.com/coinbase/x402/go`\n**Docs:** https://www.x402.org | https://github.com/coinbase/x402\n\n## Scaffold-ETH 2\n\n- **Setup:** `npx create-eth@latest`\n- **What:** Full-stack Ethereum toolkit: Solidity + Next.js + Foundry\n- **Key feature:** Auto-generates TypeScript types from contracts. Scaffold hooks make contract interaction trivial.\n- **Deploy to IPFS:** `yarn ipfs` (BuidlGuidl IPFS)\n- **UI Components:** https://ui.scaffoldeth.io/\n- **Docs:** https://docs.scaffoldeth.io/\n\n## Choosing Your Stack (2026)\n\n| Need | Tool |\n|------|------|\n| Rapid prototyping / full dApps | **Scaffold-ETH 2** |\n| Contract-focused dev | **Foundry** (forge + cast + anvil) |\n| Quick contract interaction | **abi.ninja** (browser) or **cast** (CLI) |\n| React frontends | **wagmi + viem** (or SE2 which wraps these) |\n| Agent blockchain reads | **Blockscout MCP** |\n| Agent payments | **x402 SDKs** |\n\n## Essential Foundry cast Commands\n\n```bash\n# Read contract\ncast call 0xAddr \"balanceOf(address)(uint256)\" 0xWallet --rpc-url $RPC\n\n# Send transaction\ncast send 0xAddr \"transfer(address,uint256)\" 0xTo 1000000 --private-key $KEY --rpc-url $RPC\n\n# Gas price\ncast gas-price --rpc-url $RPC\n\n# Decode calldata\ncast 4byte-decode 0xa9059cbb...\n\n# ENS resolution\ncast resolve-name vitalik.eth --rpc-url $RPC\n\n# Fork mainnet locally\nanvil --fork-url $RPC\n```\n\n## RPC Providers\n\n**Free (testing):**\n- `https://eth.llamarpc.com` — LlamaNodes, no key\n- `https://rpc.ankr.com/eth` — Ankr, free tier\n\n**Paid (production):**\n- **Alchemy** — most popular, generous free tier (300M CU/month)\n- **Infura** — established, MetaMask default\n- **QuickNode** — performance-focused\n\n**Community:** `rpc.buidlguidl.com`\n\n## Block Explorers\n\n| Network | Explorer | API |\n|---------|----------|-----|\n| Mainnet | https://etherscan.io | https://api.etherscan.io |\n| Arbitrum | https://arbiscan.io | Etherscan-compatible |\n| Base | https://basescan.org | Etherscan-compatible |\n| Optimism | https://optimistic.etherscan.io | Etherscan-compatible |\n\n## MCP Servers for Agents\n\n**Model Context Protocol** — standard for giving AI agents structured access to external systems.\n\n1. **Blockscout MCP** — multi-chain blockchain data (primary)\n2. **eth-mcp** — community Ethereum RPC via MCP\n3. **Custom MCP wrappers** emerging for DeFi protocols, ENS, wallets\n\nMCP servers are composable — agents can use multiple together.\n\n## What Changed in 2025-2026\n\n- **Foundry became default** over Hardhat for new projects\n- **Viem gaining on ethers.js** (smaller, better TypeScript)\n- **MCP servers emerged** for agent-blockchain interaction\n- **x402 SDKs** went production-ready\n- **ERC-8004 tooling** emerging (agent registration/discovery)\n- **Deprecated:** Truffle (use Foundry/Hardhat), Goerli/Rinkeby (use Sepolia)\n\n## Testing Essentials\n\n**Fork mainnet locally:**\n```bash\nanvil --fork-url https://eth.llamarpc.com\n# Now test against real contracts with fake ETH at http://localhost:8545\n```\n\n**Primary testnet:** Sepolia (Chain ID: 11155111). Goerli and Rinkeby are deprecated.\n\n---\n\n---\nname: building-blocks\ndescription: DeFi legos and protocol composability on Ethereum and L2s. Major protocols per chain — Aerodrome on Base, GMX/Pendle on Arbitrum, Velodrome on Optimism — plus mainnet primitives (Uniswap, Aave, Compound, Curve). How they work, how to build on them, and how to combine them. Use when building DeFi integrations, choosing protocols on a specific L2, designing yield strategies, or composing existing protocols into something new.\n---\n\n# Building Blocks (DeFi Legos)\n\n## What You Probably Got Wrong\n\n**DeFi TVL:** Ethereum DeFi TVL is **$50B+** (Feb 2026). If you're quoting numbers from 2023-2024, they're stale.\n\n**Uniswap V4:** V4 introduced a **hooks system** — custom logic attached to pools (dynamic fees, TWAMM, limit orders, custom oracles). This is a major composability upgrade.\n<!-- VERIFICATION NEEDED: V4 deployment status and mainnet addresses -->\n\n**Costs changed everything:** A flash loan arbitrage on mainnet costs ~$0.05-0.50 in gas now (was $5-50). This opens composability patterns that were previously uneconomical.\n\n**The dominant DEX on each L2 is NOT Uniswap.** Aerodrome dominates Base, Velodrome dominates Optimism, Camelot is a major native DEX on Arbitrum. Don't default to Uniswap on every chain.\n\n## Key Protocol Addresses (Verified Feb 2026)\n\n| Protocol | Contract | Mainnet Address |\n|----------|----------|-----------------|\n| Uniswap V2 Router | Router | `0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D` |\n| Uniswap V2 Factory | Factory | `0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f` |\n| Uniswap V3 Factory | Factory | `0x1F98431c8aD98523631AE4a59f267346ea31F984` |\n| Uniswap V3 SwapRouter02 | Router | `0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45` |\n| Uniswap Universal Router | Router | `0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD` |\n| Aave V3 Pool | Pool | `0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2` |\n\nSee `addresses/SKILL.md` for complete multi-chain address list including L2-native protocols (Aerodrome, GMX, Pendle, Velodrome, Camelot, SyncSwap, Morpho).\n\n## Uniswap V4 Hooks (New)\n\nHooks let you add custom logic that runs before/after swaps, liquidity changes, and donations. This is the biggest composability upgrade since flash loans.\n\n### Hook Interface (Solidity)\n\n```solidity\nimport {BaseHook} from \"v4-periphery/src/utils/BaseHook.sol\";\nimport {IPoolManager} from \"v4-core/interfaces/IPoolManager.sol\";\nimport {PoolKey} from \"v4-core/types/PoolKey.sol\";\nimport {BeforeSwapDelta, BeforeSwapDeltaLibrary} from \"v4-core/types/BeforeSwapDelta.sol\";\n\ncontract DynamicFeeHook is BaseHook {\n    constructor(IPoolManager _manager) BaseHook(_manager) {}\n\n    function getHookPermissions() public pure override returns (Hooks.Permissions memory) {\n        return Hooks.Permissions({\n            beforeInitialize: false,\n            afterInitialize: false,\n            beforeAddLiquidity: false,\n            afterAddLiquidity: false,\n            beforeRemoveLiquidity: false,\n            afterRemoveLiquidity: false,\n            beforeSwap: true,           // ← We hook here\n            afterSwap: false,\n            beforeDonate: false,\n            afterDonate: false,\n            beforeSwapReturnDelta: false,\n            afterSwapReturnDelta: false,\n            afterAddLiquidityReturnDelta: false,\n            afterRemoveLiquidityReturnDelta: false\n        });\n    }\n\n    // Dynamic fee: higher fee during high-volume periods\n    function beforeSwap(\n        address,\n        PoolKey calldata key,\n        IPoolManager.SwapParams calldata params,\n        bytes calldata\n    ) external override returns (bytes4, BeforeSwapDelta, uint24) {\n        // Return dynamic fee override (e.g., 0.05% normally, 0.30% during volatility)\n        uint24 fee = _isHighVolatility() ? 3000 : 500;\n        return (this.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, fee | 0x800000);\n    }\n}\n```\n\n**Hook use cases with real code patterns:**\n- **Dynamic fees** — adjust based on volatility, time-of-day, or oracle data\n- **TWAMM** — split large orders over time to reduce price impact\n- **Limit orders** — execute when price crosses a threshold\n- **MEV protection** — auction swap ordering rights to searchers\n- **Custom oracles** — TWAP updated on every swap\n\n## Composability Patterns (Updated for 2026 Gas)\n\nThese patterns are now **economically viable** even for small amounts due to sub-dollar gas:\n\n### Flash Loan Arbitrage\nBorrow from Aave → swap on Uniswap for profit → repay Aave. All in one transaction. If unprofitable, reverts (lose only gas: ~$0.05-0.50).\n\n### Leveraged Yield Farming\nDeposit ETH on Aave → borrow stablecoin → swap for more ETH → deposit again → repeat. Gas cost per loop: ~$0.02 on mainnet, negligible on L2.\n\n### Meta-Aggregation\nRoute swaps across multiple DEXs for best execution. 1inch and Paraswap check Uniswap, Curve, Sushi simultaneously.\n\n### ERC-4626 Yield Vaults\n\nStandard vault interface — the \"ERC-20 of yield.\" Every vault exposes the same functions regardless of strategy.\n\n```solidity\nimport {ERC4626} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol\";\nimport {ERC20, IERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract SimpleYieldVault is ERC4626 {\n    constructor(IERC20 asset_) \n        ERC4626(asset_) \n        ERC20(\"Vault Shares\", \"vSHARE\") \n    {}\n\n    // totalAssets() drives the share price\n    // As yield accrues, totalAssets grows → shares worth more\n    function totalAssets() public view override returns (uint256) {\n        return IERC20(asset()).balanceOf(address(this)) + _getAccruedYield();\n    }\n}\n\n// Usage: deposit/withdraw are standardized\n// vault.deposit(1000e6, msg.sender);  // deposit 1000 USDC, get shares\n// vault.redeem(shares, msg.sender, msg.sender);  // burn shares, get USDC back\n// vault.convertToAssets(shares);  // how much USDC are my shares worth?\n```\n\n**Why ERC-4626 matters:** Composability. Any protocol can integrate any vault without custom adapters. Yearn V3, Aave's wrapped tokens, Morpho vaults, Pendle yield tokens — all ERC-4626.\n\n### Flash Loan (Aave V3 — Complete Pattern)\n\n```solidity\nimport {FlashLoanSimpleReceiverBase} from \n    \"@aave/v3-core/contracts/flashloan-v3/base/FlashLoanSimpleReceiverBase.sol\";\nimport {IPoolAddressesProvider} from \n    \"@aave/v3-core/contracts/interfaces/IPoolAddressesProvider.sol\";\n\ncontract FlashLoanArb is FlashLoanSimpleReceiverBase {\n    constructor(IPoolAddressesProvider provider) \n        FlashLoanSimpleReceiverBase(provider) {}\n\n    function executeArb(address token, uint256 amount) external {\n        // Borrow `amount` of `token` — must repay + 0.05% fee in same tx\n        POOL.flashLoanSimple(address(this), token, amount, \"\", 0);\n    }\n\n    function executeOperation(\n        address asset,\n        uint256 amount,\n        uint256 premium,  // 0.05% fee\n        address,\n        bytes calldata\n    ) external override returns (bool) {\n        // --- Your arbitrage logic here ---\n        // Buy cheap on DEX A, sell expensive on DEX B\n        // Must end with at least `amount + premium` of `asset`\n        \n        uint256 owed = amount + premium;\n        IERC20(asset).approve(address(POOL), owed);\n        return true;  // If unprofitable, revert here — lose only gas (~$0.05-0.50)\n    }\n}\n```\n\n**Aave V3 Pool (mainnet):** `0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2`\n**Flash loan fee:** 0.05% (5 basis points). Free if you repay to an Aave debt position.\n\n## Building on Base\n\n**Dominant DEX: Aerodrome** (~$500-600M TVL) — NOT Uniswap. Uses the ve(3,3) model.\n\n### How Aerodrome Works (Critical Difference from Uniswap)\n- **LPs deposit tokens** into pools → earn **AERO emissions** (not trading fees!)\n- **veAERO voters** lock AERO → vote on which pools get emissions → earn **100% of trading fees + bribes**\n- This is the opposite of Uniswap where LPs earn fees directly\n- **Flywheel:** Pools generating most fees → attract most votes → get most emissions → attract more LPs → deeper liquidity → more fees\n\n### Aerodrome Swap (Router Interface)\n```solidity\n// Aerodrome Router: 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43 (Base)\nstruct Route {\n    address from;\n    address to;\n    bool stable;       // true = stable pair (like Curve), false = volatile (like Uni V2)\n    address factory;   // 0x420DD381b31aEf6683db6B902084cB0FFECe40Da\n}\n\n// Swap via Router\nfunction swapExactTokensForTokens(\n    uint256 amountIn,\n    uint256 amountOutMin,\n    Route[] calldata routes,\n    address to,\n    uint256 deadline\n) external returns (uint256[] memory amounts);\n```\n\n### Base-Specific Patterns\n- **Coinbase Smart Wallet** — ERC-4337 wallet, passkey auth, gasless txs via Coinbase paymaster\n- **OnchainKit** — `npm create onchain` to bootstrap a Base app with React components\n- **Farcaster Frames v2** — mini-apps embedded in social posts that trigger onchain actions\n- **AgentKit** — Coinbase's framework for AI agents to interact onchain\n\n## Building on Arbitrum (Highest DeFi Liquidity)\n\n### GMX V2 — How GM Pools Work\n- **Each market has its own isolated pool** (unlike V1's single GLP pool)\n- LPs deposit into GM (liquidity) pools → receive GM tokens\n- **Fully Backed markets:** ETH/USD backed by ETH + USDC. Backing tokens match the traded asset.\n- **Synthetic markets:** DOGE/USD backed by ETH + USDC. Uses ADL (Auto-Deleveraging) when thresholds are reached.\n- LPs earn: trading fees, liquidation fees, borrowing fees, swap fees. But bear risk from trader PnL.\n\n### Pendle — Yield Tokenization\nPendle splits yield-bearing assets into principal and yield components:\n\n1. **SY (Standardized Yield):** Wraps any yield-bearing asset. E.g., wstETH → SY-wstETH.\n2. **PT (Principal Token):** The principal. Redeemable 1:1 at maturity. Trades at a discount (discount = implied yield).\n3. **YT (Yield Token):** All yield until maturity. Value decays to 0 at maturity.\n4. **Core invariant:** `SY_value = PT_value + YT_value`\n\n**Use cases:**\n- Buy PT at discount = **lock in fixed yield** (like a zero-coupon bond)\n- Buy YT = **leverage your yield exposure** (bet yield goes up)\n- LP in Pendle pools = earn trading fees + PENDLE incentives\n\n### Arbitrum-Specific Tech\n- **Stylus:** Write smart contracts in Rust/C++/WASM alongside EVM (10-100x gas savings for compute-heavy operations)\n- **Orbit:** Launch custom L3 chains (47 live on mainnet)\n\nSee `addresses/SKILL.md` for all verified protocol addresses (GMX, Pendle, Camelot, Aerodrome, Velodrome, SyncSwap, Morpho).\n\n## Discovery Resources\n\n- **DeFi Llama:** https://defillama.com — TVL rankings, yield rankings, all chains\n- **Dune Analytics:** https://dune.com — query onchain data\n- **ethereum.org/en/dapps/** — curated list\n\n## Guardrails for Composability\n\n- **Every protocol you compose with is a dependency.** If Aave gets hacked, your vault depending on Aave is affected.\n- **Oracle manipulation = exploits.** Verify oracle sources.\n- **Impermanent loss** is real for AMM LPs. Quantify it before providing liquidity.\n- **The interaction between two safe contracts can create unsafe behavior.** Audit compositions.\n- **Start with small amounts.** Test with minimal value before scaling.\n- **Flash loan attacks** can manipulate prices within a single transaction. Design for this.\n\n---\n\n---\nname: orchestration\ndescription: How an AI agent plans, builds, and deploys a complete Ethereum dApp. The three-phase build system for Scaffold-ETH 2 projects. Use when building a full application on Ethereum — from contracts to frontend to production deployment on IPFS.\n---\n\n# dApp Orchestration\n\n## What You Probably Got Wrong\n\n**SE2 has specific patterns you must follow.** Generic \"build a dApp\" advice won't work. SE2 auto-generates `deployedContracts.ts` — DON'T edit it. Use Scaffold hooks, NOT raw wagmi. External contracts go in `externalContracts.ts` BEFORE building the frontend.\n\n**There are three phases. Never skip or combine them.** Contracts → Frontend → Production. Each has validation gates.\n\n## The Three-Phase Build System\n\n| Phase | Environment | What Happens |\n|-------|-------------|-------------|\n| **Phase 1** | Local fork | Contracts + UI on localhost. Iterate fast. |\n| **Phase 2** | Live network + local UI | Deploy contracts to mainnet/L2. Test with real state. Polish UI. |\n| **Phase 3** | Production | Deploy frontend to IPFS/Vercel. Final QA. |\n\n## Phase 1: Scaffold (Local)\n\n### 1.1 Contracts\n\n```bash\nnpx create-eth@latest my-dapp\ncd my-dapp && yarn install\nyarn chain          # Terminal 1: local node\nyarn deploy         # Terminal 2: deploy contracts\n```\n\n**Critical steps:**\n1. Write contracts in `packages/foundry/contracts/` (or `packages/hardhat/contracts/`)\n2. Write deploy script\n3. Add ALL external contracts to `packages/nextjs/contracts/externalContracts.ts` — BEFORE Phase 1.2\n4. Write tests (≥90% coverage)\n5. Security audit before moving to frontend\n\n**Validate:** `yarn deploy` succeeds. `deployedContracts.ts` auto-generated. Tests pass.\n\n### 1.2 Frontend\n\n```bash\nyarn chain           # Terminal 1\nyarn deploy --watch  # Terminal 2: auto-redeploy on changes\nyarn start           # Terminal 3: Next.js at localhost:3000\n```\n\n**USE SCAFFOLD HOOKS, NOT RAW WAGMI:**\n\n```typescript\n// Read\nconst { data } = useScaffoldReadContract({\n  contractName: \"YourContract\",\n  functionName: \"balanceOf\",\n  args: [address],\n  watch: true,\n});\n\n// Write\nconst { writeContractAsync, isMining } = useScaffoldWriteContract(\"YourContract\");\nawait writeContractAsync({\n  functionName: \"swap\",\n  args: [tokenIn, tokenOut, amount],\n  onBlockConfirmation: (receipt) => console.log(\"Done!\", receipt),\n});\n\n// Events\nconst { data: events } = useScaffoldEventHistory({\n  contractName: \"YourContract\",\n  eventName: \"SwapExecuted\",\n  fromBlock: 0n,\n  watch: true,\n});\n```\n\n### The Three-Button Flow (MANDATORY)\n\nAny token interaction shows ONE button at a time:\n1. **Switch Network** (if wrong chain)\n2. **Approve Token** (if allowance insufficient)\n3. **Execute Action** (only after 1 & 2 satisfied)\n\nNever show Approve and Execute simultaneously.\n\n### UX Rules\n\n- **Human-readable amounts:** `formatEther()` / `formatUnits()` for display, `parseEther()` / `parseUnits()` for contracts\n- **Loading states everywhere:** `isLoading`, `isMining` on all async operations\n- **Disable buttons during pending txs** (blockchains take 5-12s)\n- **Never use infinite approvals** — approve exact amount or 3-5x\n- **Helpful errors:** Parse \"insufficient funds,\" \"user rejected,\" \"execution reverted\" into plain language\n\n**Validate:** Full user journey works with real wallet on localhost. All edge cases handled.\n\n## 🚨 NEVER COMMIT SECRETS TO GIT\n\n**Before touching Phase 2, read this.** AI agents are the #1 source of leaked credentials on GitHub. Bots scrape repos in real-time and exploit leaked secrets within seconds.\n\n**This means ALL secrets — not just wallet private keys:**\n- **Wallet private keys** — funds drained in seconds\n- **API keys** — Alchemy, Infura, Etherscan, WalletConnect project IDs\n- **RPC URLs with embedded keys** — e.g. `https://base-mainnet.g.alchemy.com/v2/YOUR_KEY`\n- **OAuth tokens, passwords, bearer tokens**\n\n**⚠️ Common SE2 Trap: `scaffold.config.ts`**\n\n`rpcOverrides` and `alchemyApiKey` in `scaffold.config.ts` are committed to Git. **NEVER paste API keys directly into this file.** Use environment variables:\n\n```typescript\n// ❌ WRONG — key committed to public repo\nrpcOverrides: {\n  [chains.base.id]: \"https://base-mainnet.g.alchemy.com/v2/8GVG8WjDs-LEAKED\",\n},\n\n// ✅ RIGHT — key stays in .env.local\nrpcOverrides: {\n  [chains.base.id]: process.env.NEXT_PUBLIC_BASE_RPC || \"https://mainnet.base.org\",\n},\n```\n\n**Before every `git add` or `git commit`:**\n```bash\n# Check for leaked secrets\ngit diff --cached --name-only | grep -iE '\\.env|key|secret|private'\ngrep -rn \"0x[a-fA-F0-9]\\{64\\}\" packages/ --include=\"*.ts\" --include=\"*.js\" --include=\"*.sol\"\n# Check for hardcoded API keys in config files\ngrep -rn \"g.alchemy.com/v2/[A-Za-z0-9]\" packages/ --include=\"*.ts\" --include=\"*.js\"\ngrep -rn \"infura.io/v3/[A-Za-z0-9]\" packages/ --include=\"*.ts\" --include=\"*.js\"\n# If ANYTHING matches, STOP. Move the secret to .env and add .env to .gitignore.\n```\n\n**Your `.gitignore` MUST include:**\n```\n.env\n.env.*\n*.key\nbroadcast/\ncache/\nnode_modules/\n```\n\n**SE2 handles deployer keys by default** — `yarn generate` creates a `.env` with the deployer key, and `.gitignore` excludes it. **Don't override this pattern.** Don't copy keys into scripts, config files, or deploy logs. This includes RPC keys, API keys, and any credential — not just wallet keys.\n\nSee `wallets/SKILL.md` for full key safety guide, what to do if you've already leaked a key, and safe patterns for deployment.\n\n## Phase 2: Live Contracts + Local UI\n\n1. Update `scaffold.config.ts`: `targetNetworks: [mainnet]` (or your L2)\n2. Fund deployer: `yarn generate` → `yarn account` → send real ETH\n3. Deploy: `yarn deploy --network mainnet`\n4. Verify: `yarn verify --network mainnet`\n5. Test with real wallet, small amounts ($1-10)\n6. Polish UI — remove SE2 branding, custom styling\n\n**Design rule:** NO LLM SLOP. No generic purple gradients. Make it unique.\n\n**Validate:** Contracts verified on block explorer. Full journey works with real contracts.\n\n## Phase 3: Production Deploy\n\n### Pre-deploy Checklist\n- `onlyLocalBurnerWallet: true` in scaffold.config.ts (CRITICAL — prevents burner wallet on prod)\n- Update metadata (title, description, OG image 1200x630px)\n- Restore any test values to production values\n\n### Deploy\n\n**IPFS (decentralized):**\n```bash\nyarn ipfs\n# → https://YOUR_CID.ipfs.cf-ipfs.com\n```\n\n**Vercel (fast):**\n```bash\ncd packages/nextjs && vercel\n```\n\n### Production QA\n- [ ] App loads on public URL\n- [ ] Wallet connects, network switching works\n- [ ] Read + write contract operations work\n- [ ] No console errors\n- [ ] Burner wallet NOT showing\n- [ ] OG image works in link previews\n- [ ] Mobile responsive\n- [ ] Tested with MetaMask, Rainbow, WalletConnect\n\n## Phase Transition Rules\n\n**Phase 3 bug → go back to Phase 2** (fix with local UI + prod contracts)\n**Phase 2 contract bug → go back to Phase 1** (fix locally, write regression test, redeploy)\n**Never hack around bugs in production.**\n\n## Key SE2 Directories\n\n```\npackages/\n├── foundry/contracts/          # Solidity contracts\n├── foundry/script/             # Deploy scripts\n├── foundry/test/               # Tests\n└── nextjs/\n    ├── app/                    # Pages\n    ├── components/             # React components\n    ├── contracts/\n    │   ├── deployedContracts.ts   # AUTO-GENERATED (don't edit)\n    │   └── externalContracts.ts   # YOUR external contracts (edit this)\n    ├── hooks/scaffold-eth/     # USE THESE hooks\n    └── scaffold.config.ts      # Main config\n```\n\n## AI Agent Commerce: End-to-End Flow (ERC-8004 + x402)\n\nThis is the killer use case for Ethereum in 2026: **autonomous agents discovering, trusting, paying, and rating each other** — no humans in the loop.\n\n### The Full Cycle\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  1. DISCOVER  Agent queries ERC-8004 IdentityRegistry       │\n│               → finds agents with \"weather\" service tag      │\n│                                                              │\n│  2. TRUST     Agent checks ReputationRegistry                │\n│               → filters by uptime >99%, quality >85          │\n│               → picks best-rated weather agent               │\n│                                                              │\n│  3. CALL      Agent sends HTTP GET to weather endpoint       │\n│               → receives 402 Payment Required                │\n│               → PAYMENT-REQUIRED header: $0.10 USDC on Base  │\n│                                                              │\n│  4. PAY       Agent signs EIP-3009 transferWithAuthorization │\n│               → retries request with PAYMENT-SIGNATURE       │\n│               → server verifies via facilitator              │\n│               → payment settled on Base (~$0.001 gas)        │\n│                                                              │\n│  5. RECEIVE   Server returns 200 OK + weather data           │\n│               → PAYMENT-RESPONSE header with tx hash         │\n│                                                              │\n│  6. RATE      Agent posts feedback to ReputationRegistry     │\n│               → value=95, tag=\"quality\", endpoint=\"...\"      │\n│               → builds onchain reputation for next caller   │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Concrete Implementation (TypeScript Agent)\n\n```typescript\nimport { x402Fetch } from '@x402/fetch';\nimport { createWallet } from '@x402/evm';\nimport { ethers } from 'ethers';\n\nconst wallet = createWallet(process.env.AGENT_PRIVATE_KEY);\nconst provider = new ethers.JsonRpcProvider('https://base-mainnet.g.alchemy.com/v2/YOUR_KEY');\n\nconst IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';\nconst REPUTATION_REGISTRY = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';\n\n// 1. Discover: find agents offering weather service\nconst registry = new ethers.Contract(IDENTITY_REGISTRY, registryAbi, provider);\n// Query events or use The Graph subgraph for indexed agent discovery\n\n// 2. Trust: check reputation\nconst reputation = new ethers.Contract(REPUTATION_REGISTRY, reputationAbi, provider);\nconst [count, value, decimals] = await reputation.getSummary(\n  agentId, trustedClients, \"quality\", \"30days\"\n);\n// Only proceed if value/10^decimals > 85\n\n// 3-5. Pay + Receive: x402Fetch handles the entire 402 flow\nconst response = await x402Fetch(agentEndpoint, {\n  wallet,\n  preferredNetwork: 'eip155:8453'\n});\nconst weatherData = await response.json();\n\n// 6. Rate: post feedback onchain\nconst reputationWriter = new ethers.Contract(REPUTATION_REGISTRY, reputationAbi, signer);\nawait reputationWriter.giveFeedback(\n  agentId, 95, 0, \"quality\", \"weather\", agentEndpoint, \"\", ethers.ZeroHash\n);\n```\n\n**This is the agentic economy.** No API keys, no subscriptions, no invoicing, no trust assumptions. Just cryptographic identity, onchain reputation, and HTTP-native payments.\n\n### Key Projects Building This Stack\n- **ERC-8004** — agent identity + reputation (EF, MetaMask, Google, Coinbase)\n- **x402** — HTTP payment protocol (Coinbase)\n- **A2A** — agent-to-agent communication (Google)\n- **MCP** — model context protocol (Anthropic)\n- **The Graph** — indexing agent registrations for fast discovery\n- **EigenLayer** — crypto-economic validation of agent work\n\n## Resources\n\n- **SE2 Docs:** https://docs.scaffoldeth.io/\n- **UI Components:** https://ui.scaffoldeth.io/\n- **SpeedRunEthereum:** https://speedrunethereum.com/\n- **ETH Tech Tree:** https://www.ethtechtree.com\n\n---\n\n---\nname: addresses\ndescription: Verified contract addresses for major Ethereum protocols across mainnet and L2s. Use this instead of guessing or hallucinating addresses. Includes Uniswap, Aave, Compound, Aerodrome, GMX, Pendle, Velodrome, Camelot, SyncSwap, USDC, USDT, DAI, ENS, Safe, Chainlink, and more. Always verify addresses against a block explorer before sending transactions.\n---\n\n# Contract Addresses\n\n> **CRITICAL:** Never hallucinate a contract address. Wrong addresses mean lost funds. If an address isn't listed here, look it up on the block explorer or the protocol's official docs before using it.\n\n**Last Verified:** February 15, 2026 (all addresses verified onchain via `cast code` + `cast call`)\n\n---\n\n## Stablecoins\n\n### USDC (Circle) — Native\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` | ✅ Verified |\n| Arbitrum | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` | ✅ Verified |\n| Optimism | `0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85` | ✅ Verified |\n| Base | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | ✅ Verified |\n| Polygon | `0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359` | ✅ Verified |\n| zkSync Era | `0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4` | ✅ Verified |\n\n### USDT (Tether)\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0xdAC17F958D2ee523a2206206994597C13D831ec7` | ✅ Verified |\n| Arbitrum | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` | ✅ Verified |\n| Optimism | `0x94b008aA00579c1307B0EF2c499aD98a8ce58e58` | ✅ Verified |\n| Base | `0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2` | ✅ Verified |\n\n### DAI (MakerDAO)\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0x6B175474E89094C44Da98b954EedeAC495271d0F` | ✅ Verified |\n| Arbitrum | `0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1` | ✅ Verified |\n| Optimism | `0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1` | ✅ Verified |\n| Base | `0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb` | ✅ Verified |\n\n---\n\n## Wrapped ETH (WETH)\n\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | ✅ Verified |\n| Arbitrum | `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1` | ✅ Verified |\n| Optimism | `0x4200000000000000000000000000000000000006` | ✅ Verified |\n| Base | `0x4200000000000000000000000000000000000006` | ✅ Verified |\n\n---\n\n## DeFi Protocols\n\n### Uniswap\n\n#### V2 (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Router | `0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D` | ✅ Verified |\n| Factory | `0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f` | ✅ Verified |\n\n#### V3 (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| SwapRouter | `0xE592427A0AEce92De3Edee1F18E0157C05861564` | ✅ Verified |\n| SwapRouter02 | `0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45` | ✅ Verified |\n| Factory | `0x1F98431c8aD98523631AE4a59f267346ea31F984` | ✅ Verified |\n| Quoter V2 | `0x61fFE014bA17989E743c5F6cB21bF9697530B21e` | ✅ Verified |\n| Position Manager | `0xC36442b4a4522E871399CD717aBDD847Ab11FE88` | ✅ Verified |\n\n#### V3 Multi-Chain\n| Contract | Arbitrum | Optimism | Base |\n|----------|----------|----------|------|\n| SwapRouter02 | `0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45` ✅ | `0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45` ✅ | `0x2626664c2603336E57B271c5C0b26F421741e481` ✅ |\n| Factory | `0x1F98431c8aD98523631AE4a59f267346ea31F984` ✅ | `0x1F98431c8aD98523631AE4a59f267346ea31F984` ✅ | `0x33128a8fC17869897dcE68Ed026d694621f6FDfD` ✅ |\n\n#### Universal Router (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Universal Router | `0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD` | ✅ Verified |\n\n#### UNI Token\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984` | ✅ Verified |\n\n### Aave\n\n#### V2 (Mainnet - Legacy)\n| Contract | Address | Status |\n|----------|---------|--------|\n| LendingPool | `0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9` | ✅ Verified |\n\n#### V3 (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Pool | `0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2` | ✅ Verified |\n| PoolAddressesProvider | `0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e` | ✅ Verified |\n\n#### V3 Multi-Chain\n| Contract | Arbitrum | Optimism | Base |\n|----------|----------|----------|------|\n| Pool | `0x794a61358D6845594F94dc1DB02A252b5b4814aD` ✅ | `0x794a61358D6845594F94dc1DB02A252b5b4814aD` ✅ | `0xA238Dd80C259a72e81d7e4664a9801593F98d1c5` ✅ |\n| PoolAddressesProvider | `0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb` ✅ | `0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb` ✅ | `0xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64D` ✅ |\n\n### Compound\n\n#### V2 (Mainnet - Legacy)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Comptroller | `0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B` | ✅ Verified |\n| cETH | `0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5` | ✅ Verified |\n| cUSDC | `0x39AA39c021dfbaE8faC545936693aC917d5E7563` | ✅ Verified |\n| cDAI | `0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643` | ✅ Verified |\n\n#### V3 Comet (USDC Markets)\n| Network | Address | Status |\n|---------|---------|--------|\n| Mainnet | `0xc3d688B66703497DAA19211EEdff47f25384cdc3` | ✅ Verified |\n| Arbitrum | `0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf` | ✅ Verified |\n| Base | `0xb125E6687d4313864e53df431d5425969c15Eb2F` | ✅ Verified |\n| Optimism | `0x2e44e174f7D53F0212823acC11C01A11d58c5bCB` | ✅ Verified |\n\n### Curve Finance (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Address Provider | `0x0000000022D53366457F9d5E68Ec105046FC4383` | ✅ Verified |\n| CRV Token | `0xD533a949740bb3306d119CC777fa900bA034cd52` | ✅ Verified |\n\n### Balancer V2 (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Vault | `0xBA12222222228d8Ba445958a75a0704d566BF2C8` | ✅ Verified |\n\n---\n\n## NFT & Marketplaces\n\n### OpenSea Seaport\n| Version | Address | Status |\n|---------|---------|--------|\n| Seaport 1.1 | `0x00000000006c3852cbEf3e08E8dF289169EdE581` | ✅ Verified |\n| Seaport 1.5 | `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC` | ✅ Verified |\n\nMulti-chain via CREATE2 (Ethereum, Polygon, Arbitrum, Optimism, Base).\n\n### ENS (Mainnet)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Registry | `0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e` | ✅ Verified |\n| Public Resolver | `0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63` | ✅ Verified |\n| Registrar Controller | `0x253553366Da8546fC250F225fe3d25d0C782303b` | ✅ Verified |\n\n---\n\n## Infrastructure\n\n### Safe (Gnosis Safe)\n| Contract | Address | Status |\n|----------|---------|--------|\n| Singleton 1.3.0 | `0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552` | ✅ Verified |\n| ProxyFactory | `0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2` | ✅ Verified |\n| Singleton 1.4.1 | `0x41675C099F32341bf84BFc5382aF534df5C7461a` | ✅ Verified |\n| MultiSend | `0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526` | ✅ Verified |\n\n### Account Abstraction (ERC-4337)\n| Contract | Address | Status |\n|----------|---------|--------|\n| EntryPoint v0.7 | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | ✅ Verified |\n| EntryPoint v0.6 | `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` | ✅ Verified |\n\nAll EVM chains (CREATE2).\n\n### Chainlink\n\n#### Mainnet\n| Feed | Address | Status |\n|------|---------|--------|\n| LINK Token | `0x514910771AF9Ca656af840dff83E8264EcF986CA` | ✅ Verified |\n| ETH/USD | `0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419` | ✅ Verified |\n| BTC/USD | `0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c` | ✅ Verified |\n| USDC/USD | `0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6` | ✅ Verified |\n\n#### ETH/USD Price Feeds (Multi-Chain)\n| Network | Address | Status |\n|---------|---------|--------|\n| Arbitrum | `0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612` | ✅ Verified |\n| Base | `0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70` | ✅ Verified |\n| Optimism | `0x13e3Ee699D1909E989722E753853AE30b17e08c5` | ✅ Verified |\n\n#### LINK Token (Multi-Chain)\n| Network | Address | Status |\n|---------|---------|--------|\n| Arbitrum | `0xf97f4df75117a78c1A5a0DBb814Af92458539FB4` | ✅ Verified |\n| Base | `0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196` | ✅ Verified |\n\n---\n\n## L2-Native Protocols\n\n> **The dominant DEX on each L2 is NOT Uniswap.** Aerodrome dominates Base, Velodrome dominates Optimism, Camelot is a major native DEX on Arbitrum. Don't default to Uniswap — check which DEX has the deepest liquidity on each chain.\n\n### Aerodrome (Base) — Dominant DEX\n\nThe largest DEX on Base by TVL (~$500-600M). Uses the ve(3,3) model — **LPs earn AERO emissions, veAERO voters earn 100% of trading fees.** This is the opposite of Uniswap where LPs earn fees directly.\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| AERO Token | `0x940181a94A35A4569E4529A3CDfB74e38FD98631` | ✅ Verified |\n| Router | `0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43` | ✅ Verified |\n| Voter | `0x16613524e02ad97eDfeF371bC883F2F5d6C480A5` | ✅ Verified |\n| VotingEscrow | `0xeBf418Fe2512e7E6bd9b87a8F0f294aCDC67e6B4` | ✅ Verified |\n| PoolFactory | `0x420DD381b31aEf6683db6B902084cB0FFECe40Da` | ✅ Verified |\n| GaugeFactory | `0x35f35cA5B132CaDf2916BaB57639128eAC5bbcb5` | ✅ Verified |\n| Minter | `0xeB018363F0a9Af8f91F06FEe6613a751b2A33FE5` | ✅ Verified |\n| RewardsDistributor | `0x227f65131A261548b057215bB1D5Ab2997964C7d` | ✅ Verified |\n| FactoryRegistry | `0x5C3F18F06CC09CA1910767A34a20F771039E37C0` | ✅ Verified |\n\nSource: [aerodrome-finance/contracts](https://github.com/aerodrome-finance/contracts)\n\n### Velodrome V2 (Optimism) — Dominant DEX\n\nSame ve(3,3) model as Aerodrome — same team (Dromos Labs). Velodrome was built first for Optimism, Aerodrome is the Base fork. Both merged into \"Aero\" in November 2025.\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| VELO Token (V2) | `0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db` | ✅ Verified |\n| Router | `0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858` | ✅ Verified |\n| Voter | `0x41C914ee0c7E1A5edCD0295623e6dC557B5aBf3C` | ✅ Verified |\n| VotingEscrow | `0xFAf8FD17D9840595845582fCB047DF13f006787d` | ✅ Verified |\n| PoolFactory | `0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a` | ✅ Verified |\n| Minter | `0x6dc9E1C04eE59ed3531d73a72256C0da46D10982` | ✅ Verified |\n| GaugeFactory | `0x8391fE399640E7228A059f8Fa104b8a7B4835071` | ✅ Verified |\n| FactoryRegistry | `0xF4c67CdEAaB8360370F41514d06e32CcD8aA1d7B` | ✅ Verified |\n\n⚠️ **V1 VELO token** (`0x3c8B650257cFb5f272f799F5e2b4e65093a11a05`) is deprecated. Use V2 above.\n\nSource: [velodrome-finance/contracts](https://github.com/velodrome-finance/contracts)\n\n### GMX V2 (Arbitrum) — Perpetual DEX\n\nLeading onchain perpetual exchange. V2 uses isolated GM pools per market (Fully Backed and Synthetic). Competes with Hyperliquid.\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| GMX Token | `0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a` | ✅ Verified |\n| Exchange Router (latest) | `0x1C3fa76e6E1088bCE750f23a5BFcffa1efEF6A41` | ✅ Verified |\n| Exchange Router (previous) | `0x7C68C7866A64FA2160F78EeAe12217FFbf871fa8` | ✅ Verified |\n| DataStore | `0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8` | ✅ Verified |\n| Reader | `0x470fbC46bcC0f16532691Df360A07d8Bf5ee0789` | ✅ Verified |\n| Reward Router V2 | `0xA906F338CB21815cBc4Bc87ace9e68c87eF8d8F1` | ✅ Verified |\n\n**Note:** Both Exchange Router addresses are valid — both point to the same DataStore. The latest (`0x1C3f...`) is from the current gmx-synthetics repo deployment.\n\nSource: [gmx-io/gmx-synthetics](https://github.com/gmx-io/gmx-synthetics)\n\n### Pendle (Arbitrum) — Yield Trading\n\nTokenizes future yield into PT (Principal Token) and YT (Yield Token). Core invariant: `SY_value = PT_value + YT_value`. Multi-chain (also on Ethereum, Base, Optimism).\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| PENDLE Token | `0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8` | ✅ Verified |\n| Router | `0x888888888889758F76e7103c6CbF23ABbF58F946` | ✅ Verified |\n| RouterStatic | `0xAdB09F65bd90d19e3148D9ccb693F3161C6DB3E8` | ✅ Verified |\n| Market Factory V3 | `0x2FCb47B58350cD377f94d3821e7373Df60bD9Ced` | ✅ Verified |\n| Market Factory V4 | `0xd9f5e9589016da862D2aBcE980A5A5B99A94f3E8` | ✅ Verified |\n| PT/YT Oracle | `0x5542be50420E88dd7D5B4a3D488FA6ED82F6DAc2` | ✅ Verified |\n| Limit Router | `0x000000000000c9B3E2C3Ec88B1B4c0cD853f4321` | ✅ Verified |\n| Yield Contract Factory V3 | `0xEb38531db128EcA928aea1B1CE9E5609B15ba146` | ✅ Verified |\n| Yield Contract Factory V4 | `0xc7F8F9F1DdE1104664b6fC8F33E49b169C12F41E` | ✅ Verified |\n\nSource: [pendle-finance/pendle-core-v2-public](https://github.com/pendle-finance/pendle-core-v2-public/blob/main/deployments/42161-core.json)\n\n### Camelot (Arbitrum) — Native DEX\n\nArbitrum-native DEX with concentrated liquidity and launchpad. Two AMM versions: V2 (constant product) and V4 (Algebra concentrated liquidity).\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| GRAIL Token | `0x3d9907F9a368ad0a51Be60f7Da3b97cf940982D8` | ✅ Verified |\n| xGRAIL | `0x3CAaE25Ee616f2C8E13C74dA0813402eae3F496b` | ✅ Verified |\n| Router (AMM V2) | `0xc873fEcbd354f5A56E00E710B90EF4201db2448d` | ✅ Verified |\n| Factory (AMM V2) | `0x6EcCab422D763aC031210895C81787E87B43A652` | ✅ Verified |\n| SwapRouter (AMM V4 / Algebra) | `0x4ee15342d6Deb297c3A2aA7CFFd451f788675F53` | ✅ Verified |\n| AlgebraFactory (AMM V4) | `0xBefC4b405041c5833f53412fF997ed2f697a2f37` | ✅ Verified |\n\nSource: [docs.camelot.exchange](https://docs.camelot.exchange/contracts/arbitrum/one-mainnet)\n\n### SyncSwap (zkSync Era) — Dominant DEX\n\nThe leading native DEX on zkSync Era. Multiple router and factory versions.\n\n| Contract | Address | Status |\n|----------|---------|--------|\n| Router V1 | `0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295` | ✅ Verified |\n| Router V2 | `0x9B5def958d0f3b6955cBEa4D5B7809b2fb26b059` | ✅ Verified |\n| Router V3 | `0x1B887a14216Bdeb7F8204Ee6a269Bd9Ff73A084C` | ✅ Verified |\n| Classic Pool Factory V1 | `0xf2DAd89f2788a8CD54625C60b55cD3d2D0ACa7Cb` | ✅ Verified |\n| Classic Pool Factory V2 | `0x0a34FBDf37C246C0B401da5f00ABd6529d906193` | ✅ Verified |\n| Stable Pool Factory V1 | `0x5b9f21d407F35b10CbfDDca17D5D84b129356ea3` | ✅ Verified |\n| Vault V1 | `0x621425a1Ef6abE91058E9712575dcc4258F8d091` | ✅ Verified |\n\n**Note:** SYNC token is not yet deployed.\n\nSource: [docs.syncswap.xyz](https://docs.syncswap.xyz/syncswap/smart-contracts/smart-contracts)\n\n### Morpho Blue (Base)\n\nPermissionless lending protocol. Deployed on Base and Ethereum, but **NOT on Arbitrum** as of February 2026 (despite the vanity CREATE2 address).\n\n| Contract | Address | Chain | Status |\n|----------|---------|-------|--------|\n| Morpho | `0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb` | Base | ✅ Verified |\n| Morpho | `0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb` | Arbitrum | ❌ Not deployed |\n\nSource: [docs.morpho.org](https://docs.morpho.org/get-started/resources/addresses/)\n\n---\n\n## AI & Agent Standards\n\n### ERC-8004 (Same addresses on 20+ chains)\n| Contract | Address | Status |\n|----------|---------|--------|\n| IdentityRegistry | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | ✅ Verified |\n| ReputationRegistry | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` | ✅ Verified |\n\nVerified on: Mainnet, Arbitrum, Base, Optimism (CREATE2 — same address on all chains).\n\n---\n\n## Major Tokens (Mainnet)\n\n| Token | Address | Status |\n|-------|---------|--------|\n| UNI | `0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984` | ✅ Verified |\n| AAVE | `0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9` | ✅ Verified |\n| COMP | `0xc00e94Cb662C3520282E6f5717214004A7f26888` | ✅ Verified |\n| MKR | `0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2` | ✅ Verified |\n| LDO | `0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32` | ✅ Verified |\n| WBTC | `0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599` | ✅ Verified |\n| stETH (Lido) | `0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84` | ✅ Verified |\n| rETH (Rocket Pool) | `0xae78736Cd615f374D3085123A210448E74Fc6393` | ✅ Verified |\n\n---\n\n## How to Verify Addresses\n\n```bash\n# Check bytecode exists\ncast code 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --rpc-url https://eth.llamarpc.com\n```\n\n**Cross-reference:** Protocol docs → CoinGecko → block explorer → GitHub deployments.\n\n**EIP-55 Checksum:** Mixed case = checksum. Most tools validate automatically.\n\n## Address Discovery Resources\n\n- **Uniswap:** https://docs.uniswap.org/contracts/v3/reference/deployments/\n- **Aave:** https://docs.aave.com/developers/deployed-contracts/deployed-contracts\n- **Compound V3:** https://docs.compound.finance/\n- **Chainlink:** https://docs.chain.link/data-feeds/price-feeds/addresses\n- **Aerodrome:** https://github.com/aerodrome-finance/contracts\n- **Velodrome:** https://github.com/velodrome-finance/contracts\n- **GMX:** https://github.com/gmx-io/gmx-synthetics\n- **Pendle:** https://github.com/pendle-finance/pendle-core-v2-public\n- **Camelot:** https://docs.camelot.exchange/contracts/arbitrum/one-mainnet\n- **SyncSwap:** https://docs.syncswap.xyz/syncswap/smart-contracts/smart-contracts\n- **Morpho:** https://docs.morpho.org/get-started/resources/addresses/\n- **CoinGecko:** https://www.coingecko.com (token addresses)\n- **Token Lists:** https://tokenlists.org/\n- **DeFi Llama:** https://defillama.com (TVL rankings by chain)\n\n## Multi-Chain Notes\n\n- **CREATE2 deployments** (same address cross-chain): Uniswap V3, Safe, Seaport, ERC-4337 EntryPoint, ERC-8004\n- **Different addresses per chain:** USDC, USDT, DAI, WETH — always check per-chain\n- **Native vs Bridged USDC:** Some chains have both! Use native.\n\n---\n\n✅ **All addresses verified onchain via `cast code` + `cast call` — February 15, 2026. Bytecode confirmed present, identity confirmed via symbol/name/cross-reference calls. Does NOT guarantee safety — always verify on block explorer before sending transactions.**\n\n---\n\n---\nname: concepts\ndescription: The essential mental models for building onchain — focused on what LLMs get wrong and what humans need explained. \"Nothing is automatic\" and \"incentives are everything\" are the core messages. Use when your human is new to onchain development, when they're designing a system, or when they ask \"how does this actually work?\" Also use when YOU are designing a system — the state machine + incentive framework catches design mistakes before they become dead code.\n---\n\n# Ethereum Concepts\n\n## What You Probably Got Wrong\n\n**\"Smart contracts run automatically.\"** No. Smart contracts cannot execute themselves. There is no cron job, no scheduler, no background process. Every function needs a caller who pays gas. This single misconception is the root cause of most broken onchain designs.\n\n**\"Just add a timer.\"** There are no timers. If something needs to happen at a certain time, you need someone to call the function at that time — and you need to give them a reason to do it.\n\n**\"The protocol team will handle that.\"** The whole point of decentralization is that no single team operates the system. If your design requires an operator, it's not decentralized — and it has a single point of failure.\n\n**Terminology:** You say \"on-chain.\" The Ethereum community says **\"onchain\"** — one word, no hyphen.\n\n---\n\n## Nothing Is Automatic — Incentive Design\n\n**This is the most important concept in all of Ethereum. If you internalize nothing else, internalize this.**\n\n### Smart Contracts Are State Machines\n\nA smart contract is a state machine. It sits in one state, and it moves to another state when someone **pokes it** — calls a function, pays gas, triggers a transition. Between pokes, it does absolutely nothing. It doesn't think, it doesn't check, it doesn't wake up. It just sits there.\n\n```\nState A ──[someone calls function]──→ State B ──[someone calls function]──→ State C\n              ↑                                        ↑\n         WHO does this?                           WHO does this?\n         WHY would they?                          WHY would they?\n```\n\nThere is no cron job. There is no scheduler. There is no background process. The blockchain doesn't call your contract — people call your contract. And people don't do things for free.\n\n**For EVERY state transition in your system, you must answer:**\n\n1. **Who pokes it?** (someone must pay gas)\n2. **Why would they?** (what's their incentive?)\n3. **Is the incentive sufficient?** (covers gas + profit?)\n\nIf you can't answer these questions, that state transition will never happen. Your contract will sit in State A forever, doing nothing, with nobody poking it.\n\n### Incentives Are Everything\n\nHere's the thing that makes Ethereum magical: **you don't need an operator if you get the incentives right.**\n\nThe people who deployed Uniswap didn't deploy the liquidity. They didn't market-make. They didn't run the exchange. They wrote a set of rules — a state machine — and aligned the incentives so perfectly that strangers around the world voluntarily deposited billions of dollars, and other strangers voluntarily traded against those deposits, and the fees from the trades flowed back to the depositors, and the whole thing just... worked.\n\nNobody runs Uniswap. Nobody CAN stop Uniswap. Not even the people who made it. The contracts are immutable, the incentives are self-sustaining, and the system will run for as long as Ethereum exists. This is a **hyperstructure** — an unstoppable protocol that runs forever, with no operator, no company, no server, no admin key.\n\nThat's what you're building toward. Not a startup. Not a service. A set of rules so well-designed that they run themselves through incentives alone.\n\n### Examples of Good Incentive Design\n\n**Liquidations (Aave, Compound):**\n```\nLoan health factor drops below 1\n→ ANYONE can call liquidate()\n→ Caller gets 5-10% bonus collateral as profit\n→ Bots compete to do it in milliseconds\n→ Platform stays solvent without any operator, any admin, any team\n```\n\n**LP fees (Uniswap):**\n```\nDEX needs liquidity to function\n→ LPs deposit tokens into pools\n→ Every swap pays 0.3% fee to LPs\n→ More liquidity = less slippage = more traders = more fees = more liquidity\n→ Self-reinforcing flywheel — nobody manages it\n```\n\n**Yield harvesting (Yearn):**\n```\nRewards accumulate in a pool\n→ ANYONE can call harvest()\n→ Caller gets 1% of the harvest as reward\n→ Protocol compounds automatically via profit-motivated callers\n```\n\n**Arbitrage (keeps prices correct everywhere):**\n```\nETH is $2000 on Uniswap, $2010 on SushiSwap\n→ Anyone can buy low, sell high\n→ Prices equalize across ALL markets without any coordinator\n```\n\n### Examples of BAD Design (Missing Incentives)\n\n```\n❌ \"The contract will check prices every hour\"\n   → WHO calls it every hour? WHY would they pay gas?\n   → Fix: make it profitable to call. Or let users trigger it when they interact.\n\n❌ \"Expired listings get automatically removed\"\n   → Nothing is automatic. WHO removes them? WHY?\n   → Fix: give callers a small reward, or let the next user's action clean up stale state.\n\n❌ \"The protocol rebalances daily\"\n   → WHOSE gas pays for this? What's their profit?\n   → Fix: let rebalancing happen during user interactions, or reward the caller.\n\n❌ \"An admin will manually trigger the next phase\"\n   → What if the admin disappears? Gets hit by a bus? Loses their key?\n   → Fix: make phase transitions permissionless with time-based or condition-based triggers.\n```\n\n**The fix is always the same:** Don't use an admin account. Make the function callable by **anyone**. Give them a reason to call it. Align incentives so the system pokes itself through the self-interest of its participants.\n\n### The Hyperstructure Test\n\nWhen you're designing a system, ask: **\"Could this run forever with no team behind it?\"**\n\n- If yes → you've built a hyperstructure. The incentives sustain it.\n- If no → you've built a service. It dies when the team stops operating it.\n\nBoth are valid choices. But know which one you're building. The most powerful things on Ethereum are hyperstructures: Uniswap, ENS, the ERC-20 standard itself. They can't be stopped, they can't be censored, they can't go down. Not because they're maintained — because they don't need to be.\n\n---\n\n## Randomness Is Hard\n\nSmart contracts are deterministic. Every node computes the same result. You can't use `Math.random()` — there's nothing random about a system where everyone gets the same answer.\n\n### What Doesn't Work\n\n```solidity\n// ❌ Validators can manipulate block.timestamp (within ~15 seconds)\nuint random = uint(keccak256(abi.encodePacked(block.timestamp)));\n\n// ❌ blockhash(block.number) is ALWAYS zero for the current block\nuint random = uint(blockhash(block.number));\n\n// ❌ Validators can withhold blocks if they don't like the result\nuint random = uint(blockhash(block.number - 1));\n```\n\n### What Works\n\n**Commit-Reveal** (no external dependency):\n```\n1. User commits hash(secret + salt) → stored onchain\n2. Wait at least 1 block\n3. User reveals secret + salt → contract verifies hash\n4. Random seed = keccak256(secret + blockhash(commitBlock))\n```\n- User can't predict blockhash when they commit\n- Validator can't know the secret to manipulate the result\n- Must reveal within 256 blocks (blockhash returns zero after that)\n\n**Chainlink VRF** (provably random, costs LINK):\n```\n1. Contract requests randomness from Chainlink\n2. Chainlink generates random number off-chain with a VRF proof\n3. Anyone can verify the proof onchain\n4. Guaranteed unbiased — even Chainlink can't manipulate it\n```\n\nUse commit-reveal for simple cases. Use Chainlink VRF when you need provable randomness (lotteries, NFT reveals, gaming).\n\n---\n\n## Teaching Your Human\n\nYou already know how AMMs, lending, oracles, and stablecoins work. But your human might not. When they're designing something onchain, they need to understand these concepts — not the code, the *mental models*.\n\n**Don't lecture.** Instead, when a concept is relevant to what they're building, explain it in context. Here's what to emphasize for each:\n\n### The Approve Pattern\nHumans find this weird. Explain it as: *\"You're giving the contract permission to move your tokens, like signing a check. You control how much. Never sign a blank check (infinite approval).\"*\n\n### DEXs / AMMs\nThe key insight isn't the math — it's the incentive flywheel: *\"Nobody runs the exchange. People deposit tokens because they earn fees from trades. More deposits = better prices = more trades = more fees. It runs itself.\"* This is \"nothing is automatic\" in action.\n\n### Overcollateralized Lending\nLead with liquidation incentives: *\"If your loan gets risky, anyone in the world can close it and earn a bonus. That's why the platform never goes bankrupt — thousands of bots are watching every loan, every second, competing to clean up risk.\"* This is the SpeedRun Ethereum Challenge 6 moment where incentive design clicks.\n\n### Stablecoins\n*\"How does a token stay worth $1 with nobody controlling it? Arbitrage. If it drops to $0.99, people buy it because they can redeem it for $1 of collateral. If it goes to $1.01, people mint more and sell. Self-interest maintains the peg.\"*\n\n### Oracles\n*\"Smart contracts can't Google things. If your contract needs a price, someone has to put it onchain. Use Chainlink — never read prices from a DEX pool, because a flash loan can fake the price for one transaction.\"*\n\n### Smart Contract Wallets\n*\"A wallet can require 3 of 5 people to approve a transaction. $100B+ is secured this way. It's how teams and DAOs manage money without trusting any single person.\"*\n\n### Prediction Markets\n*\"YES and NO tokens that trade between $0 and $1. The price IS the probability. If YES is at $0.35, the market thinks there's a 35% chance. Winner gets $1, loser gets $0.\"*\n\n**In every case, tie it back to incentives.** The human should walk away understanding not just what something does, but WHY it works without anyone running it.\n\n---\n\n## Learning Path\n\nPoint your human to SpeedRun Ethereum for hands-on learning. Each challenge builds a working project that teaches a core concept:\n\n| # | Challenge | What Clicks |\n|---|-----------|-------------|\n| 0 | Simple NFT | Minting, metadata, ownership — \"contracts hold state\" |\n| 1 | Staking | Deadlines, escrow, thresholds — \"coordination without trust\" |\n| 2 | Token Vendor | Approve pattern, buy/sell — \"contracts can be markets\" |\n| 3 | Dice Game | Why onchain randomness is insecure — \"determinism vs. randomness\" |\n| 4 | DEX | x*y=k, slippage, LP incentives — \"incentives create markets\" |\n\n**Start at https://speedrunethereum.com**\n\nMore challenges covering oracles, lending, stablecoins, and multisigs are in development. Check the site for current availability.\n\n## Resources\n\n- **SpeedRun Ethereum:** https://speedrunethereum.com\n- **ETH Tech Tree:** https://www.ethtechtree.com\n- **Ethereum.org:** https://ethereum.org/en/developers/\n- **EthSkills (for agents):** https://ethskills.com\n\n---\n\n---\nname: security\ndescription: Solidity security patterns, common vulnerabilities, and pre-deploy audit checklist. The specific code patterns that prevent real losses — not just warnings, but defensive implementations. Use before deploying any contract, when reviewing code, or when building anything that holds or moves value.\n---\n\n# Smart Contract Security\n\n## What You Probably Got Wrong\n\n**\"Solidity 0.8+ prevents overflows, so I'm safe.\"** Overflow is one of dozens of attack vectors. The big ones today: reentrancy, oracle manipulation, approval exploits, and decimal mishandling.\n\n**\"I tested it and it works.\"** Working correctly is not the same as being secure. Most exploits call functions in orders or with values the developer never considered.\n\n**\"It's a small contract, it doesn't need an audit.\"** The DAO hack was a simple reentrancy bug. The Euler exploit was a single missing check. Size doesn't correlate with safety.\n\n## Critical Vulnerabilities (With Defensive Code)\n\n### 1. Token Decimals Vary\n\n**USDC has 6 decimals, not 18.** This is the #1 source of \"where did my money go?\" bugs.\n\n```solidity\n// ❌ WRONG — assumes 18 decimals. Transfers 1 TRILLION USDC.\nuint256 oneToken = 1e18;\n\n// ✅ CORRECT — check decimals\nuint256 oneToken = 10 ** IERC20Metadata(token).decimals();\n```\n\nCommon decimals:\n| Token | Decimals |\n|-------|----------|\n| USDC, USDT | 6 |\n| WBTC | 8 |\n| DAI, WETH, most tokens | 18 |\n\n**When doing math across tokens with different decimals, normalize first:**\n```solidity\n// Converting USDC amount to 18-decimal internal accounting\nuint256 normalized = usdcAmount * 1e12; // 6 + 12 = 18 decimals\n```\n\n### 2. No Floating Point in Solidity\n\nSolidity has no `float` or `double`. Division truncates to zero.\n\n```solidity\n// ❌ WRONG — this equals 0\nuint256 fivePercent = 5 / 100;\n\n// ✅ CORRECT — basis points (1 bp = 0.01%)\nuint256 FEE_BPS = 500; // 5% = 500 basis points\nuint256 fee = (amount * FEE_BPS) / 10_000;\n```\n\n**Always multiply before dividing.** Division first = precision loss.\n\n```solidity\n// ❌ WRONG — loses precision\nuint256 result = a / b * c;\n\n// ✅ CORRECT — multiply first\nuint256 result = (a * c) / b;\n```\n\nFor complex math, use fixed-point libraries like `PRBMath` or `ABDKMath64x64`.\n\n### 3. Reentrancy\n\nAn external call can call back into your contract before the first call finishes. If you update state AFTER the external call, the attacker re-enters with stale state.\n\n```solidity\n// ❌ VULNERABLE — state updated after external call\nfunction withdraw() external {\n    uint256 bal = balances[msg.sender];\n    (bool success,) = msg.sender.call{value: bal}(\"\"); // ← attacker re-enters here\n    require(success);\n    balances[msg.sender] = 0; // Too late — attacker already withdrew again\n}\n\n// ✅ SAFE — Checks-Effects-Interactions pattern + reentrancy guard\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\nfunction withdraw() external nonReentrant {\n    uint256 bal = balances[msg.sender];\n    require(bal > 0, \"Nothing to withdraw\");\n    \n    balances[msg.sender] = 0;  // Effect BEFORE interaction\n    \n    (bool success,) = msg.sender.call{value: bal}(\"\");\n    require(success, \"Transfer failed\");\n}\n```\n\n**The pattern: Checks → Effects → Interactions (CEI)**\n1. **Checks** — validate inputs and conditions\n2. **Effects** — update all state\n3. **Interactions** — external calls last\n\nAlways use OpenZeppelin's `ReentrancyGuard` as a safety net on top of CEI.\n\n### 4. SafeERC20\n\nSome tokens (notably USDT) don't return `bool` on `transfer()` and `approve()`. Standard calls will revert even on success.\n\n```solidity\n// ❌ WRONG — breaks with USDT and other non-standard tokens\ntoken.transfer(to, amount);\ntoken.approve(spender, amount);\n\n// ✅ CORRECT — handles all token implementations\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nusing SafeERC20 for IERC20;\n\ntoken.safeTransfer(to, amount);\ntoken.safeApprove(spender, amount);\n```\n\n**Other token quirks to watch for:**\n- **Fee-on-transfer tokens:** Amount received < amount sent. Always check balance before and after.\n- **Rebasing tokens (stETH):** Balance changes without transfers. Use wrapped versions (wstETH).\n- **Pausable tokens (USDC):** Transfers can revert if the token is paused.\n- **Blocklist tokens (USDC, USDT):** Specific addresses can be blocked from transacting.\n\n### 5. Never Use DEX Spot Prices as Oracles\n\nA flash loan can manipulate any pool's spot price within a single transaction. This has caused hundreds of millions in losses.\n\n```solidity\n// ❌ DANGEROUS — manipulable in one transaction\nfunction getPrice() internal view returns (uint256) {\n    (uint112 reserve0, uint112 reserve1,) = uniswapPair.getReserves();\n    return (reserve1 * 1e18) / reserve0; // Spot price — easily manipulated\n}\n\n// ✅ SAFE — Chainlink with staleness + sanity checks\nfunction getPrice() internal view returns (uint256) {\n    (, int256 price,, uint256 updatedAt,) = priceFeed.latestRoundData();\n    require(block.timestamp - updatedAt < 3600, \"Stale price\");\n    require(price > 0, \"Invalid price\");\n    return uint256(price);\n}\n```\n\n**If you must use onchain price data:**\n- Use **TWAP** (Time-Weighted Average Price) over 30+ minutes — resistant to single-block manipulation\n- Uniswap V3 has built-in TWAP oracles via `observe()`\n- Still less safe than Chainlink for high-value decisions\n\n### 6. Vault Inflation Attack\n\nThe first depositor in an ERC-4626 vault can manipulate the share price to steal from subsequent depositors.\n\n**The attack:**\n1. Attacker deposits 1 wei → gets 1 share\n2. Attacker donates 1000 tokens directly to the vault (not via deposit)\n3. Now 1 share = 1001 tokens\n4. Victim deposits 1999 tokens → gets `1999 * 1 / 2000 = 0 shares` (rounds down)\n5. Attacker redeems 1 share → gets all 3000 tokens\n\n**The fix — virtual offset:**\n```solidity\nfunction convertToShares(uint256 assets) public view returns (uint256) {\n    return assets.mulDiv(\n        totalSupply() + 1e3,    // Virtual shares\n        totalAssets() + 1        // Virtual assets\n    );\n}\n```\n\nThe virtual offset makes the attack uneconomical — the attacker would need to donate enormous amounts to manipulate the ratio.\n\nOpenZeppelin's ERC4626 implementation includes this mitigation by default since v5.\n\n### 7. Infinite Approvals\n\n**Never use `type(uint256).max` as approval amount.**\n\n```solidity\n// ❌ DANGEROUS — if this contract is exploited, attacker drains your entire balance\ntoken.approve(someContract, type(uint256).max);\n\n// ✅ SAFE — approve only what's needed\ntoken.approve(someContract, exactAmountNeeded);\n\n// ✅ ACCEPTABLE — approve a small multiple for repeated interactions\ntoken.approve(someContract, amountPerTx * 5); // 5 transactions worth\n```\n\nIf a contract with infinite approval gets exploited (proxy upgrade bug, governance attack, undiscovered vulnerability), the attacker can drain every approved token from every user who granted unlimited access.\n\n### 8. Access Control\n\nEvery state-changing function needs explicit access control. \"Who should be able to call this?\" is the first question.\n\n```solidity\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n// ❌ WRONG — anyone can drain the contract\nfunction emergencyWithdraw() external {\n    token.transfer(msg.sender, token.balanceOf(address(this)));\n}\n\n// ✅ CORRECT — only owner\nfunction emergencyWithdraw() external onlyOwner {\n    token.transfer(owner(), token.balanceOf(address(this)));\n}\n```\n\nFor complex permissions, use OpenZeppelin's `AccessControl` with role-based separation (ADMIN_ROLE, OPERATOR_ROLE, etc.).\n\n### 9. Input Validation\n\nNever trust inputs. Validate everything.\n\n```solidity\nfunction deposit(uint256 amount, address recipient) external {\n    require(amount > 0, \"Zero amount\");\n    require(recipient != address(0), \"Zero address\");\n    require(amount <= maxDeposit, \"Exceeds max\");\n    \n    // Now proceed\n}\n```\n\nCommon missed validations:\n- Zero addresses (tokens sent to 0x0 are burned forever)\n- Zero amounts (wastes gas, can cause division by zero)\n- Array length mismatches in batch operations\n- Duplicate entries in arrays\n- Values exceeding reasonable bounds\n\n## Pre-Deploy Security Checklist\n\nRun through this for EVERY contract before deploying to production. No exceptions.\n\n- [ ] **Access control** — every admin/privileged function has explicit restrictions\n- [ ] **Reentrancy protection** — CEI pattern + `nonReentrant` on all external-calling functions\n- [ ] **Token decimal handling** — no hardcoded `1e18` for tokens that might have different decimals\n- [ ] **Oracle safety** — using Chainlink or TWAP, not DEX spot prices. Staleness checks present\n- [ ] **Integer math** — multiply before divide. No precision loss in critical calculations\n- [ ] **Return values checked** — using SafeERC20 for all token operations\n- [ ] **Input validation** — zero address, zero amount, bounds checks on all public functions\n- [ ] **Events emitted** — every state change emits an event for offchain tracking\n- [ ] **Incentive design** — maintenance functions callable by anyone with sufficient incentive\n- [ ] **No infinite approvals** — approve exact amounts or small bounded multiples\n- [ ] **Fee-on-transfer safe** — if accepting arbitrary tokens, measure actual received amount\n- [ ] **Tested edge cases** — zero values, max values, unauthorized callers, reentrancy attempts\n\n## Automated Security Tools\n\nRun these before deployment:\n\n```bash\n# Static analysis\nslither .                     # Detects common vulnerabilities\nmythril analyze Contract.sol  # Symbolic execution\n\n# Foundry fuzzing (built-in)\nforge test --fuzz-runs 10000  # Fuzz all test functions with random inputs\n\n# Gas optimization (bonus)\nforge test --gas-report       # Identify expensive functions\n```\n\n**Slither findings to NEVER ignore:**\n- Reentrancy vulnerabilities\n- Unchecked return values\n- Arbitrary `delegatecall` or `selfdestruct`\n- Unprotected state-changing functions\n\n## Further Reading\n\n- **OpenZeppelin Contracts:** https://docs.openzeppelin.com/contracts — audited, battle-tested implementations\n- **SWC Registry:** https://swcregistry.io — comprehensive vulnerability catalog\n- **Rekt News:** https://rekt.news — real exploit post-mortems\n- **SpeedRun Ethereum:** https://speedrunethereum.com — hands-on secure development practice\n\n---\n\n---\nname: frontend-ux\ndescription: Frontend UX rules for Ethereum dApps that prevent the most common AI agent UI bugs. Mandatory patterns for onchain buttons, token approval flows, address display, USD values, RPC configuration, and pre-publish metadata. Built around Scaffold-ETH 2 but the patterns apply to any Ethereum frontend. Use when building any dApp frontend.\n---\n\n# Frontend UX Rules\n\n## What You Probably Got Wrong\n\n**\"The button works.\"** Working is not the standard. Does it disable during the transaction? Does it show a spinner? Does it stay disabled until the chain confirms? Does it show an error if the user rejects? AI agents skip all of this, every time.\n\n**\"I used wagmi hooks.\"** Wrong hooks. Scaffold-ETH 2 wraps wagmi with `useTransactor` which **waits for transaction confirmation** — not just wallet signing. Raw wagmi's `writeContractAsync` resolves the moment the user clicks Confirm in MetaMask, BEFORE the tx is mined. Your button re-enables while the transaction is still pending.\n\n**\"I showed the address.\"** As raw hex? That's not showing it. `<Address/>` gives you ENS resolution, blockie avatars, copy-to-clipboard, and block explorer links. Raw `0x1234...5678` is unacceptable.\n\n---\n\n## Rule 1: Every Onchain Button — Loader + Disable\n\nANY button that triggers a blockchain transaction MUST:\n1. **Disable immediately** on click\n2. **Show a spinner** (\"Approving...\", \"Staking...\", etc.)\n3. **Stay disabled** until the state update confirms the action completed\n4. **Show success/error feedback** when done\n\n```typescript\n// ✅ CORRECT: Separate loading state PER ACTION\nconst [isApproving, setIsApproving] = useState(false);\nconst [isStaking, setIsStaking] = useState(false);\n\n<button\n  disabled={isApproving}\n  onClick={async () => {\n    setIsApproving(true);\n    try {\n      await writeContractAsync({ functionName: \"approve\", args: [...] });\n    } catch (e) {\n      console.error(e);\n      notification.error(\"Approval failed\");\n    } finally {\n      setIsApproving(false);\n    }\n  }}\n>\n  {isApproving ? \"Approving...\" : \"Approve\"}\n</button>\n```\n\n**❌ NEVER use a single shared `isLoading` for multiple buttons.** Each button gets its own loading state. A shared state causes the WRONG loading text to appear when UI conditionally switches between buttons.\n\n### Scaffold Hooks Only — Never Raw Wagmi\n\n```typescript\n// ❌ WRONG: Raw wagmi — resolves after signing, not confirmation\nconst { writeContractAsync } = useWriteContract();\nawait writeContractAsync({...}); // Returns immediately after MetaMask signs!\n\n// ✅ CORRECT: Scaffold hooks — waits for tx to be mined\nconst { writeContractAsync } = useScaffoldWriteContract(\"MyContract\");\nawait writeContractAsync({...}); // Waits for actual onchain confirmation\n```\n\n**Why:** `useScaffoldWriteContract` uses `useTransactor` internally, which waits for block confirmation. Raw wagmi doesn't — your UI will show \"success\" while the transaction is still in the mempool.\n\n---\n\n## Rule 2: Three-Button Flow — Network → Approve → Action\n\nWhen a user needs to approve tokens then perform an action (stake, deposit, swap), there are THREE states. Show exactly ONE button at a time:\n\n```\n1. Wrong network?       → \"Switch to Base\" button\n2. Not enough approved? → \"Approve\" button  \n3. Enough approved?     → \"Stake\" / \"Deposit\" / action button\n```\n\n```typescript\nconst { data: allowance } = useScaffoldReadContract({\n  contractName: \"Token\",\n  functionName: \"allowance\",\n  args: [address, contractAddress],\n});\n\nconst needsApproval = !allowance || allowance < amount;\nconst wrongNetwork = chain?.id !== targetChainId;\n\n{wrongNetwork ? (\n  <button onClick={switchNetwork} disabled={isSwitching}>\n    {isSwitching ? \"Switching...\" : \"Switch to Base\"}\n  </button>\n) : needsApproval ? (\n  <button onClick={handleApprove} disabled={isApproving}>\n    {isApproving ? \"Approving...\" : \"Approve $TOKEN\"}\n  </button>\n) : (\n  <button onClick={handleStake} disabled={isStaking}>\n    {isStaking ? \"Staking...\" : \"Stake\"}\n  </button>\n)}\n```\n\n**Critical details:**\n- Always read allowance via a hook so the UI updates automatically when the approval tx confirms\n- Never rely on local state alone for allowance tracking\n- Wrong network check comes FIRST — if the user clicks Approve while on the wrong network, everything breaks\n- **Never show Approve and Action simultaneously** — one button at a time\n\n---\n\n## Rule 3: Address Display — Always `<Address/>`\n\n**EVERY time you display an Ethereum address**, use scaffold-eth's `<Address/>` component:\n\n```typescript\nimport { Address } from \"~~/components/scaffold-eth\";\n\n// ✅ CORRECT\n<Address address={userAddress} />\n\n// ❌ WRONG — never render raw hex\n<span>{userAddress}</span>\n<p>0x1234...5678</p>\n```\n\n`<Address/>` handles ENS resolution, blockie avatars, copy-to-clipboard, truncation, and block explorer links. Raw hex is unacceptable.\n\n### Address Input — Always `<AddressInput/>`\n\n**EVERY time the user needs to enter an Ethereum address**, use `<AddressInput/>`:\n\n```typescript\nimport { AddressInput } from \"~~/components/scaffold-eth\";\n\n// ✅ CORRECT\n<AddressInput value={recipient} onChange={setRecipient} placeholder=\"Recipient address\" />\n\n// ❌ WRONG — never use a raw text input for addresses\n<input type=\"text\" value={recipient} onChange={e => setRecipient(e.target.value)} />\n```\n\n`<AddressInput/>` provides ENS resolution (type \"vitalik.eth\" → resolves to address), blockie avatar preview, validation, and paste handling.\n\n**The pair: `<Address/>` for DISPLAY, `<AddressInput/>` for INPUT. Always.**\n\n---\n\n## Rule 4: USD Values Everywhere\n\n**EVERY token or ETH amount displayed should include its USD value.**\n**EVERY token or ETH input should show a live USD preview.**\n\n```typescript\n// ✅ CORRECT — Display with USD\n<span>1,000 TOKEN (~$4.20)</span>\n<span>0.5 ETH (~$1,250.00)</span>\n\n// ✅ CORRECT — Input with live USD preview\n<input value={amount} onChange={...} />\n<span className=\"text-sm text-gray-500\">\n  ≈ ${(parseFloat(amount || \"0\") * tokenPrice).toFixed(2)} USD\n</span>\n\n// ❌ WRONG — Amount with no USD context\n<span>1,000 TOKEN</span>  // User has no idea what this is worth\n```\n\n**Where to get prices:**\n- **ETH price:** SE2 built-in hook — `useNativeCurrencyPrice()`\n- **Custom tokens:** DexScreener API (`https://api.dexscreener.com/latest/dex/tokens/TOKEN_ADDRESS`), onchain Uniswap quoter, or Chainlink oracle\n\n**This applies to both display AND input:**\n- Displaying a balance? Show USD next to it.\n- User entering an amount to send/stake/swap? Show live USD preview below the input.\n- Transaction confirmation? Show USD value of what they're about to do.\n\n---\n\n## Rule 5: No Duplicate Titles\n\n**DO NOT put the app name as an `<h1>` at the top of the page body.** The SE2 header already displays the app name. Repeating it wastes space and looks amateur.\n\n```typescript\n// ❌ WRONG — AI agents ALWAYS do this\n<Header />  {/* Already shows \"🦞 My dApp\" */}\n<main>\n  <h1>🦞 My dApp</h1>  {/* DUPLICATE! Delete this. */}\n  <p>Description of the app</p>\n  ...\n</main>\n\n// ✅ CORRECT — Jump straight into content\n<Header />  {/* Shows the app name */}\n<main>\n  <div className=\"grid grid-cols-2 gap-4\">\n    {/* Stats, balances, actions — no redundant title */}\n  </div>\n</main>\n```\n\n---\n\n## Rule 6: RPC Configuration\n\n**NEVER use public RPCs** (`mainnet.base.org`, etc.) — they rate-limit and cause random failures in production.\n\nIn `scaffold.config.ts`, ALWAYS set:\n```typescript\nrpcOverrides: {\n  [chains.base.id]: process.env.NEXT_PUBLIC_BASE_RPC || \"https://mainnet.base.org\",\n},\npollingInterval: 3000,  // 3 seconds, not the default 30000\n```\n\n**Keep the API key in `.env.local`** — never hardcode it in config files that get committed to Git.\n\n**Monitor RPC usage:** Sensible = 1 request every 3 seconds. If you see 15+ requests/second, you have a bug:\n- Hooks re-rendering in loops\n- Duplicate hook calls\n- Missing dependency arrays\n- `watch: true` on hooks that don't need it\n\n---\n\n## Rule 7: Pre-Publish Checklist\n\n**BEFORE deploying frontend to production, EVERY item must pass:**\n\n**Open Graph / Twitter Cards (REQUIRED):**\n```typescript\n// In app/layout.tsx or getMetadata.ts\nexport const metadata: Metadata = {\n  title: \"Your App Name\",\n  description: \"Description of the app\",\n  openGraph: {\n    title: \"Your App Name\",\n    description: \"Description of the app\",\n    images: [{ url: \"https://YOUR-LIVE-DOMAIN.com/thumbnail.png\" }],\n  },\n  twitter: {\n    card: \"summary_large_image\",\n    title: \"Your App Name\",\n    description: \"Description of the app\",\n    images: [\"https://YOUR-LIVE-DOMAIN.com/thumbnail.png\"],\n  },\n};\n```\n\n**⚠️ The OG image URL MUST be:**\n- Absolute URL starting with `https://`\n- The LIVE production domain (NOT `localhost`, NOT relative path)\n- NOT an environment variable that could be unset\n- Actually reachable (test by visiting the URL in a browser)\n\n**Full checklist:**\n- [ ] OG image URL is absolute, live production domain\n- [ ] OG title and description set (not default SE2 text)\n- [ ] Twitter card type set (`summary_large_image`)\n- [ ] Favicon updated from SE2 default\n- [ ] README updated from SE2 default\n- [ ] Footer \"Fork me\" link → your actual repo (not SE2)\n- [ ] Browser tab title is correct\n- [ ] RPC overrides set (not public RPCs)\n- [ ] `pollingInterval` is 3000\n- [ ] All contract addresses match what's deployed\n- [ ] No hardcoded testnet/localhost values in production code\n- [ ] Every address display uses `<Address/>`\n- [ ] Every address input uses `<AddressInput/>`\n- [ ] Every onchain button has its own loader + disabled state\n- [ ] Approve flow has network check → approve → action pattern\n- [ ] No duplicate h1 title matching header\n\n---\n\n## externalContracts.ts — Before You Build\n\n**ALL external contracts** (tokens, protocols, anything you didn't deploy) MUST be added to `packages/nextjs/contracts/externalContracts.ts` with address and ABI BEFORE building the frontend.\n\n```typescript\n// packages/nextjs/contracts/externalContracts.ts\nexport default {\n  8453: {  // Base chain ID\n    USDC: {\n      address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n      abi: [...],  // ERC-20 ABI\n    },\n  },\n} as const;\n```\n\n**Why BEFORE:** Scaffold hooks (`useScaffoldReadContract`, `useScaffoldWriteContract`) only work with contracts registered in `deployedContracts.ts` (auto-generated) or `externalContracts.ts` (manual). If you write frontend code referencing a contract that isn't registered, it silently fails.\n\n**Never edit `deployedContracts.ts`** — it's auto-generated by `yarn deploy`. Put your external contracts in `externalContracts.ts`.\n\n---\n\n## Human-Readable Amounts\n\nAlways convert between contract units and display units:\n\n```typescript\n// Contract → Display\nimport { formatEther, formatUnits } from \"viem\";\nformatEther(weiAmount);           // 18 decimals (ETH, DAI, most tokens)\nformatUnits(usdcAmount, 6);       // 6 decimals (USDC, USDT)\n\n// Display → Contract\nimport { parseEther, parseUnits } from \"viem\";\nparseEther(\"1.5\");                // → 1500000000000000000n\nparseUnits(\"100\", 6);             // → 100000000n (USDC)\n```\n\n**Never show raw wei/units to users.** `1500000000000000000` means nothing. `1.5 ETH (~$3,750)` means everything.\n\n---\n\n## Resources\n\n- **SE2 Docs:** https://docs.scaffoldeth.io/\n- **UI Components:** https://ui.scaffoldeth.io/\n- **SpeedRun Ethereum:** https://speedrunethereum.com/\n\n---\n\n---\nname: frontend-playbook\ndescription: The complete build-to-production pipeline for Ethereum dApps. Fork mode setup, IPFS deployment, Vercel config, ENS subdomain setup, and the full production checklist. Built around Scaffold-ETH 2 but applicable to any Ethereum frontend project. Use when deploying any dApp to production.\n---\n\n# Frontend Playbook\n\n## What You Probably Got Wrong\n\n**\"I'll use `yarn chain`.\"** Wrong. `yarn chain` gives you an empty local chain with no protocols, no tokens, no state. `yarn fork --network base` gives you a copy of real Base with Uniswap, Aave, USDC, real whale balances — everything. Always fork.\n\n**\"I deployed to IPFS and it works.\"** Did the CID change? If not, you deployed stale output. Did routes work? Without `trailingSlash: true`, every route except `/` returns 404. Did you check the OG image? Without `NEXT_PUBLIC_PRODUCTION_URL`, it points to `localhost:3000`.\n\n**\"I'll set up the project manually.\"** Don't. `npx create-eth@latest` handles everything — Foundry, Next.js, RainbowKit, scaffold hooks. Never run `forge init` or create Next.js projects from scratch.\n\n---\n\n## Fork Mode Setup\n\n### Why Fork, Not Chain\n\n```\nyarn chain (WRONG)              yarn fork --network base (CORRECT)\n└─ Empty local chain            └─ Fork of real Base mainnet\n└─ No protocols                 └─ Uniswap, Aave, etc. available\n└─ No tokens                    └─ Real USDC, WETH exist\n└─ Testing in isolation         └─ Test against REAL state\n```\n\n### Setup\n\n```bash\nnpx create-eth@latest          # Select: foundry, target chain, name\ncd <project-name>\nyarn install\nyarn fork --network base       # Terminal 1: fork of real Base\nyarn deploy                    # Terminal 2: deploy contracts to fork\nyarn start                     # Terminal 3: Next.js frontend\n```\n\n### Critical: Chain ID Gotcha\n\n**When using fork mode, the frontend target network MUST be `chains.foundry` (chain ID 31337), NOT the chain you're forking.**\n\nThe fork runs locally on Anvil with chain ID 31337. Even if you're forking Base:\n\n```typescript\n// scaffold.config.ts during development\ntargetNetworks: [chains.foundry],  // ✅ NOT chains.base!\n```\n\nOnly switch to `chains.base` when deploying contracts to the REAL network.\n\n### Enable Block Mining\n\n```bash\n# In a new terminal — REQUIRED for time-dependent logic\ncast rpc anvil_setIntervalMining 1\n```\n\nWithout this, `block.timestamp` stays FROZEN. Any contract logic using timestamps (deadlines, expiry, vesting) will break silently.\n\n**Make it permanent** by editing `packages/foundry/package.json` to add `--block-time 1` to the fork script.\n\n---\n\n## Deploying to IPFS (Recommended)\n\nIPFS is the recommended deploy path for SE2. Avoids Vercel's memory limits entirely. Produces a fully decentralized static site.\n\n### Full Build Command\n\n```bash\ncd packages/nextjs\nrm -rf .next out  # ALWAYS clean first\n\nNEXT_PUBLIC_PRODUCTION_URL=\"https://yourapp.yourname.eth.link\" \\\n  NODE_OPTIONS=\"--require ./polyfill-localstorage.cjs\" \\\n  NEXT_PUBLIC_IPFS_BUILD=true \\\n  NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \\\n  yarn build\n\n# Upload to BuidlGuidl IPFS\nyarn bgipfs upload out\n# Save the CID!\n```\n\n### Node 25+ localStorage Polyfill (REQUIRED)\n\nNode.js 25+ ships a built-in `localStorage` object that's MISSING standard WebStorage API methods (`getItem`, `setItem`). This breaks `next-themes`, RainbowKit, and any library that calls `localStorage.getItem()` during static page generation.\n\n**Error you'll see:**\n```\nTypeError: localStorage.getItem is not a function\nError occurred prerendering page \"/_not-found\"\n```\n\n**The fix:** Create `polyfill-localstorage.cjs` in `packages/nextjs/`:\n```javascript\nif (typeof globalThis.localStorage !== \"undefined\" &&\n    typeof globalThis.localStorage.getItem !== \"function\") {\n  const store = new Map();\n  globalThis.localStorage = {\n    getItem: (key) => store.get(key) ?? null,\n    setItem: (key, value) => store.set(key, String(value)),\n    removeItem: (key) => store.delete(key),\n    clear: () => store.clear(),\n    key: (index) => [...store.keys()][index] ?? null,\n    get length() { return store.size; },\n  };\n}\n```\n\n**Why `--require` and not `instrumentation.ts`?** Next.js spawns a separate build worker process for prerendering. `--require` injects into EVERY Node process (including workers). `next.config.ts` polyfill only runs in the main process. `instrumentation.ts` doesn't run in the build worker. Only `--require` works.\n\n### IPFS Routing — Why Routes Break\n\nIPFS gateways serve static files. No server handles routing. Three things MUST be true:\n\n**1. `output: \"export\"` in next.config.ts** — generates static HTML files.\n\n**2. `trailingSlash: true` (CRITICAL)** — This is the #1 reason routes break:\n- `trailingSlash: false` (default) → generates `debug.html`\n- `trailingSlash: true` → generates `debug/index.html`\n- IPFS gateways resolve directories to `index.html` automatically, but NOT bare filenames\n- Without trailing slash: `/debug` → 404 ❌\n- With trailing slash: `/debug` → `debug/` → `debug/index.html` ✅\n\n**3. Pages must survive static prerendering** — any page that crashes during `yarn build` (browser APIs at import time, localStorage) gets skipped silently → 404 on IPFS.\n\n**The complete IPFS-safe next.config.ts pattern:**\n```typescript\nconst isIpfs = process.env.NEXT_PUBLIC_IPFS_BUILD === \"true\";\nif (isIpfs) {\n  nextConfig.output = \"export\";\n  nextConfig.trailingSlash = true;\n  nextConfig.images = { unoptimized: true };\n}\n```\n\n**SE2's block explorer pages** use `localStorage` at import time and crash during static export. Rename `app/blockexplorer` to `app/_blockexplorer-disabled` if not needed.\n\n### Stale Build Detection\n\n**The #1 IPFS footgun:** You edit code, then deploy the OLD build.\n\n```bash\n# MANDATORY after ANY code change:\nrm -rf .next out                     # 1. Delete old artifacts\n# ... run full build command ...     # 2. Rebuild from scratch\ngrep -l \"YOUR_STRING\" out/_next/static/chunks/app/*.js  # 3. Verify changes present\n\n# Timestamp check:\nstat -f '%Sm' app/page.tsx           # Source modified time\nstat -f '%Sm' out/                   # Build output time\n# Source NEWER than out/ = STALE BUILD. Rebuild first!\n```\n\n**The CID is proof:** If the IPFS CID didn't change after a deploy, you deployed the same content. A real code change ALWAYS produces a new CID.\n\n### Verify Routes After Deploy\n\n```bash\nls out/*/index.html                  # Each route has a directory + index.html\ncurl -s -o /dev/null -w \"%{http_code}\" -L \"https://GATEWAY/ipfs/CID/debug/\"\n# Should return 200, not 404\n```\n\n---\n\n## Deploying to Vercel (Alternative)\n\nSE2 is a monorepo — Vercel needs special configuration.\n\n### Configuration\n\n1. **Root Directory:** `packages/nextjs`\n2. **Install Command:** `cd ../.. && yarn install`\n3. **Build Command:** leave default (`next build`)\n4. **Output Directory:** leave default (`.next`)\n\n```bash\n# Via API:\ncurl -X PATCH \"https://api.vercel.com/v9/projects/PROJECT_ID\" \\\n  -H \"Authorization: Bearer $VERCEL_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"rootDirectory\": \"packages/nextjs\", \"installCommand\": \"cd ../.. && yarn install\"}'\n```\n\n### Common Failures\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| \"No Next.js version detected\" | Root Directory not set | Set to `packages/nextjs` |\n| \"cd packages/nextjs: No such file\" | Build command has `cd` | Clear it — root dir handles this |\n| OOM / exit code 129 | SE2 monorepo exceeds 8GB | Use IPFS instead, or `vercel --prebuilt` |\n\n### Decision Tree\n\n```\nWant to deploy SE2?\n├─ IPFS (recommended) → yarn ipfs / manual build + upload\n│   └─ Fully decentralized, no memory limits, works with ENS\n├─ Vercel → Set rootDirectory + installCommand\n│   └─ Fast CDN, but centralized. May OOM on large projects\n└─ vercel --prebuilt → Build locally, push artifacts to Vercel\n    └─ Best of both: local build power + Vercel CDN\n```\n\n---\n\n## ENS Subdomain Setup\n\nTwo mainnet transactions to point an ENS subdomain at your IPFS deployment.\n\n### Transaction 1: Create Subdomain (new apps only)\n\n1. Open `https://app.ens.domains/yourname.eth`\n2. Go to \"Subnames\" tab → \"New subname\"\n3. Enter the label (e.g. `myapp`) → Next → Skip profile → Open Wallet → Confirm\n4. If gas is stuck: switch MetaMask to Ethereum → Activity tab → \"Speed up\"\n\n### Transaction 2: Set IPFS Content Hash\n\n1. Navigate to `https://app.ens.domains/myapp.yourname.eth`\n2. \"Records\" tab → \"Edit Records\" → \"Other\" tab\n3. Paste in Content Hash field: `ipfs://<CID>`\n4. Save → Open Wallet → Confirm in MetaMask\n\nFor **updates** to an existing app: skip Tx 1, only do Tx 2.\n\n### Verify\n\n```bash\n# 1. Onchain content hash matches\nRESOLVER=$(cast call 0x00000000000C2e074eC69A0dFb2997BA6C7d2e1e \\\n  \"resolver(bytes32)(address)\" $(cast namehash myapp.yourname.eth) \\\n  --rpc-url https://eth.llamarpc.com)\ncast call $RESOLVER \"contenthash(bytes32)(bytes)\" \\\n  $(cast namehash myapp.yourname.eth) --rpc-url https://eth.llamarpc.com\n\n# 2. Gateway responds (may take 5-15 min for cache)\ncurl -s -o /dev/null -w \"%{http_code}\" -L \"https://myapp.yourname.eth.link\"\n\n# 3. OG metadata correct (not localhost)\ncurl -s -L \"https://myapp.yourname.eth.link\" | grep 'og:image'\n```\n\n**Use `.eth.link` NOT `.eth.limo`** — `.eth.link` works better on mobile.\n\n---\n\n## Go to Production — Complete Checklist\n\nWhen the user says \"ship it\", follow this EXACT sequence.\n\n### Step 1: Final Code Review 🤖\n- All feedback incorporated\n- No duplicate h1, no raw addresses, no shared isLoading\n- `scaffold.config.ts` has `rpcOverrides` and `pollingInterval: 3000`\n\n### Step 2: Choose Domain 👤\nAsk: *\"What subdomain do you want? e.g. `myapp.yourname.eth` → `myapp.yourname.eth.link`\"*\n\n### Step 3: Generate OG Image + Fix Metadata 🤖\n- Create 1200×630 PNG (`public/thumbnail.png`) — NOT the stock SE2 thumbnail\n- Set `NEXT_PUBLIC_PRODUCTION_URL` to the live domain\n- Verify `og:image` will resolve to an absolute production URL\n\n### Step 4: Clean Build + IPFS Deploy 🤖\n```bash\ncd packages/nextjs && rm -rf .next out\nNEXT_PUBLIC_PRODUCTION_URL=\"https://myapp.yourname.eth.link\" \\\n  NODE_OPTIONS=\"--require ./polyfill-localstorage.cjs\" \\\n  NEXT_PUBLIC_IPFS_BUILD=true NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \\\n  yarn build\n\n# Verify before uploading:\nls out/*/index.html                        # Routes exist\ngrep 'og:image' out/index.html             # Not localhost\nstat -f '%Sm' app/page.tsx                 # Source older than out/\nstat -f '%Sm' out/\n\nyarn bgipfs upload out                     # Save the CID\n```\n\n### Step 5: Share for Approval 👤\nSend: *\"Build ready for review: `https://community.bgipfs.com/ipfs/<CID>`\"*\n**Wait for approval before touching ENS.**\n\n### Step 6: Set ENS 🤖\nCreate subdomain (if new) + set IPFS content hash. Two mainnet transactions.\n\n### Step 7: Verify 🤖\n- Content hash matches onchain\n- `.eth.link` gateway responds with 200\n- OG image loads correctly\n- Routes work (`/debug/`, etc.)\n\n### Step 8: Report 👤\n*\"Live at `https://myapp.yourname.eth.link` — ENS content hash confirmed onchain, unfurl metadata set.\"*\n\n---\n\n## Build Verification Process\n\nA build is NOT done when the code compiles. It's done when you've tested it like a real user.\n\n### Phase 1: Code QA (Automated)\n- Scan `.tsx` files for raw address strings (should use `<Address/>`)\n- Scan for shared `isLoading` state across multiple buttons\n- Scan for missing `disabled` props on transaction buttons\n- Verify RPC config and polling interval\n- Verify OG metadata with absolute URLs\n- Verify no public RPCs in any file\n\n### Phase 2: Smart Contract Testing\n```bash\nforge test                    # All tests pass\nforge test --fuzz-runs 10000  # Fuzz testing\n```\nTest edge cases: zero amounts, max amounts, unauthorized callers, reentrancy attempts.\n\n### Phase 3: Browser Testing (THE REAL TEST)\n\nOpen the app and do a FULL walkthrough:\n\n1. **Load the app** — does it render correctly?\n2. **Check page title** — is it correct, not \"Scaffold-ETH 2\"?\n3. **Connect wallet** — does the connect flow work?\n4. **Wrong network** — connect on wrong chain, verify \"Switch to Base\" appears\n5. **Switch network** — click the switch button, verify it works\n6. **Approve flow** — verify approve button shows, click it, wait for tx, verify action button appears\n7. **Main action** — click primary action, verify loader, wait for tx, verify state updates\n8. **Error handling** — reject a transaction in wallet, verify UI recovers\n9. **Address displays** — all addresses showing ENS/blockies, not raw hex?\n10. **Share URL** — check OG unfurl (image, title, description)\n\n### Phase 4: QA Sub-Agent (Complex Builds)\nFor bigger projects, spawn a sub-agent with fresh context. Give it the repo path and deployed URL. It reads all code against the UX rules, opens a browser, clicks through independently, and reports issues.\n\n---\n\n## Don't Do These\n\n- ❌ `yarn chain` — use `yarn fork --network <chain>`\n- ❌ `forge init` — use `npx create-eth@latest`\n- ❌ Manual Next.js setup — SE2 handles it\n- ❌ Manual wallet connection — SE2 has RainbowKit pre-configured\n- ❌ Edit `deployedContracts.ts` — it's auto-generated by `yarn deploy`\n- ❌ Hardcode API keys in `scaffold.config.ts` — use `.env.local`\n- ❌ Use `mainnet.base.org` in production — use Alchemy or similar\n\n---\n\n## Resources\n\n- **SE2 Docs:** https://docs.scaffoldeth.io/\n- **UI Components:** https://ui.scaffoldeth.io/\n- **SpeedRun Ethereum:** https://speedrunethereum.com/\n- **ETH Tech Tree:** https://www.ethtechtree.com\n- **BuidlGuidl IPFS:** https://upload.bgipfs.com\n\n---\n\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":183,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1771265251128,"updatedAt":1778491556797},"latestVersion":{"version":"1.0.0","createdAt":1771265251128,"changelog":"Initial release providing up-to-date Ethereum development knowledge and addressing common misconceptions:\n\n- Covers recent Ethereum upgrades (Pectra, Fusaka) and L2 landscape\n- Explains major protocol changes: ERC-8004 (onchain agent identity) and x402 (HTTP payments)\n- Provides current 2026 gas prices, ETH value, and real-world transaction costs\n- Details key differences between Ethereum and Solana, with agent-focused context\n- Lists available sub-skills for gas, wallets, L2s, standards, tools, DeFi, contract addresses, security, and frontend development","license":null},"metadata":null,"owner":{"handle":"cupojoseph","userId":"s1719zdp2yne7d96wpj6vhshrs885rpy","displayName":"Joseph","image":"https://avatars.githubusercontent.com/u/9449596?v=4"},"moderation":null}