| name | orchestration |
| description | 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. |
dApp Orchestration
What You Probably Got Wrong
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.
There are three phases. Never skip or combine them. Contracts → Frontend → Production. Each has validation gates.
The Three-Phase Build System
| Phase | Environment | What Happens |
|---|
| Phase 1 | Local fork | Contracts + UI on localhost. Iterate fast. |
| Phase 2 | Live network + local UI | Deploy contracts to mainnet/L2. Test with real state. Polish UI. |
| Phase 3 | Production | Deploy frontend to IPFS/Vercel. Final QA. |
Phase 1: Scaffold (Local)
1.1 Contracts
npx create-eth@latest my-dapp
cd my-dapp && yarn install
yarn fork --network base
yarn deploy
Always fork, never yarn chain. yarn fork does everything yarn chain does AND gives you real protocol state — Uniswap, USDC, Aave, whale balances, everything already deployed (verified addresses: addresses/SKILL.md). yarn chain gives you an empty chain that tempts you into writing mock contracts you don't need. Don't mock what already exists onchain — just fork it.
Critical steps:
- Write contracts in
packages/foundry/contracts/ (or packages/hardhat/contracts/)
- Write deploy script
- Add ALL external contracts to
packages/nextjs/contracts/externalContracts.ts — BEFORE Phase 1.2
- Write tests (≥90% coverage)
- Audit contracts before moving to frontend — fetch audit/SKILL.md and run through it
Validate: yarn deploy succeeds. deployedContracts.ts auto-generated. Tests pass.
1.2 Frontend
yarn fork --network base
yarn deploy --watch
yarn start
USE SCAFFOLD HOOKS, NOT RAW WAGMI:
const { data } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "balanceOf",
args: [address],
watch: true,
});
const { writeContractAsync, isMining } = useScaffoldWriteContract("YourContract");
await writeContractAsync({
functionName: "swap",
args: [tokenIn, tokenOut, amount],
onBlockConfirmation: (receipt) => console.log("Done!", receipt),
});
const { data: events } = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "SwapExecuted",
fromBlock: 0n,
watch: true,
});
The Three-Button Flow (MANDATORY)
Any token interaction shows ONE button at a time:
- Switch Network (if wrong chain)
- Approve Token (if allowance insufficient)
- Execute Action (only after 1 & 2 satisfied)
Never show Approve and Execute simultaneously.
UX Rules
- Human-readable amounts:
formatEther() / formatUnits() for display, parseEther() / parseUnits() for contracts
- Loading states everywhere:
isLoading, isMining on all async operations
- Disable buttons during pending txs (blockchains take 5-12s)
- Never use infinite approvals — approve exact amount or 3-5x
- Helpful errors: Parse "insufficient funds," "user rejected," "execution reverted" into plain language
Validate: Full user journey works with real wallet on localhost. All edge cases handled.
🚨 NEVER COMMIT SECRETS TO GIT
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.
This means ALL secrets — not just wallet private keys:
- Wallet private keys — funds drained in seconds
- API keys — Alchemy, Infura, Etherscan, WalletConnect project IDs
- RPC URLs with embedded keys — e.g.
https://base-mainnet.g.alchemy.com/v2/YOUR_KEY
- OAuth tokens, passwords, bearer tokens
⚠️ Common SE2 Trap: scaffold.config.ts
rpcOverrides and alchemyApiKey in scaffold.config.ts are committed to Git. NEVER paste API keys directly into this file. Use environment variables:
rpcOverrides: {
[chains.base.id]: "https://base-mainnet.g.alchemy.com/v2/8GVG8WjDs-LEAKED",
},
rpcOverrides: {
[chains.base.id]: process.env.NEXT_PUBLIC_BASE_RPC || "https://mainnet.base.org",
},
Before every git add or git commit:
git diff --cached --name-only | grep -iE '\.env|key|secret|private'
grep -rn "0x[a-fA-F0-9]\{64\}" packages/ --include="*.ts" --include="*.js" --include="*.sol"
grep -rn "g.alchemy.com/v2/[A-Za-z0-9]" packages/ --include="*.ts" --include="*.js"
grep -rn "infura.io/v3/[A-Za-z0-9]" packages/ --include="*.ts" --include="*.js"
Your .gitignore MUST include:
.env
.env.*
*.key
broadcast/
cache/
node_modules/
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.
See wallets/SKILL.md for full key safety guide, what to do if you've already leaked a key, and safe patterns for deployment.
Phase 2: Live Contracts + Local UI
- Update
scaffold.config.ts: targetNetworks: [mainnet] (or your L2)
- Fund deployer:
yarn generate → yarn account → send real ETH
- Deploy:
yarn deploy --network mainnet
- Verify immediately after deploy:
yarn verify --network mainnet
- No block explorer API key needed — SE2 handles this for you
- Run it right after deploy, not later. Don't skip it.
- Test with real wallet, small amounts ($1-10)
- Polish UI — remove SE2 branding, custom styling
Design rule: NO LLM SLOP. No generic purple gradients. Make it unique.
Validate: Contracts verified on block explorer. Full journey works with real contracts.
Phase 3: Production Deploy
Pre-deploy Checklist
burnerWalletMode: "localNetworksOnly" in scaffold.config.ts (prevents burner wallet on prod)
- Update metadata (title, description, OG image 1200x630px)
- Restore any test values to production values
- Run a full frontend QA audit — fetch qa/SKILL.md and give it to a separate agent before deploying
Deploy
IPFS — use BGIPFS for decentralized deploys (fetch that skill for full details). It's built into SE2 — no setup needed:
yarn ipfs
Note: IPFS only works with static content — no server-side rendering, API endpoints, or functions.
Vercel:
yarn vercel
Production QA
Phase Transition Rules
Phase 3 bug → go back to Phase 2 (fix with local UI + prod contracts)
Phase 2 contract bug → go back to Phase 1 (fix locally, write regression test, redeploy)
Never hack around bugs in production.
Key SE2 Directories
packages/
├── foundry/contracts/ # Solidity contracts
├── foundry/script/ # Deploy scripts
├── foundry/test/ # Tests
└── nextjs/
├── app/ # Pages
├── components/ # React components
├── contracts/
│ ├── deployedContracts.ts # AUTO-GENERATED (don't edit)
│ └── externalContracts.ts # YOUR external contracts (edit this)
├── hooks/scaffold-eth/ # USE THESE hooks
└── scaffold.config.ts # Main config
Resources