Loading...
Loading...
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.
npx skill4agent add austintgriffith/ethskills orchestrationdeployedContracts.tsexternalContracts.ts| 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. |
npx create-eth@latest my-dapp
cd my-dapp && yarn install
yarn fork --network base # Terminal 1: fork of real chain (or mainnet, your target chain)
yarn deploy # Terminal 2: deploy contractsAlways fork, never.yarn chaindoes everythingyarn forkdoes AND gives you real protocol state — Uniswap, USDC, Aave, whale balances, everything already deployed.yarn chaingives 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.yarn chain
packages/foundry/contracts/packages/hardhat/contracts/packages/nextjs/contracts/externalContracts.tsyarn deploydeployedContracts.tsyarn fork --network base # Terminal 1: fork of real chain (has Uniswap, USDC, etc.)
yarn deploy --watch # Terminal 2: auto-redeploy on changes
yarn start # Terminal 3: Next.js at localhost:3000// Read
const { data } = useScaffoldReadContract({
contractName: "YourContract",
functionName: "balanceOf",
args: [address],
watch: true,
});
// Write
const { writeContractAsync, isMining } = useScaffoldWriteContract("YourContract");
await writeContractAsync({
functionName: "swap",
args: [tokenIn, tokenOut, amount],
onBlockConfirmation: (receipt) => console.log("Done!", receipt),
});
// Events
const { data: events } = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "SwapExecuted",
fromBlock: 0n,
watch: true,
});formatEther()formatUnits()parseEther()parseUnits()isLoadingisMininghttps://base-mainnet.g.alchemy.com/v2/YOUR_KEYscaffold.config.tsrpcOverridesalchemyApiKeyscaffold.config.ts// ❌ WRONG — key committed to public repo
rpcOverrides: {
[chains.base.id]: "https://base-mainnet.g.alchemy.com/v2/8GVG8WjDs-LEAKED",
},
// ✅ RIGHT — key stays in .env.local
rpcOverrides: {
[chains.base.id]: process.env.NEXT_PUBLIC_BASE_RPC || "https://mainnet.base.org",
},git addgit commit# Check for leaked secrets
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"
# Check for hardcoded API keys in config files
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"
# If ANYTHING matches, STOP. Move the secret to .env and add .env to .gitignore..gitignore.env
.env.*
*.key
broadcast/
cache/
node_modules/yarn generate.env.gitignorewallets/SKILL.mdscaffold.config.tstargetNetworks: [mainnet]yarn generateyarn accountyarn deploy --network mainnetyarn verify --network mainnetonlyLocalBurnerWallet: trueyarn ipfs
# → https://YOUR_CID.ipfs.cf-ipfs.comcd packages/nextjs && vercelpackages/
├── 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┌─────────────────────────────────────────────────────────────┐
│ 1. DISCOVER Agent queries ERC-8004 IdentityRegistry │
│ → finds agents with "weather" service tag │
│ │
│ 2. TRUST Agent checks ReputationRegistry │
│ → filters by uptime >99%, quality >85 │
│ → picks best-rated weather agent │
│ │
│ 3. CALL Agent sends HTTP GET to weather endpoint │
│ → receives 402 Payment Required │
│ → PAYMENT-REQUIRED header: $0.10 USDC on Base │
│ │
│ 4. PAY Agent signs EIP-3009 transferWithAuthorization │
│ → retries request with PAYMENT-SIGNATURE │
│ → server verifies via facilitator │
│ → payment settled on Base (~$0.001 gas) │
│ │
│ 5. RECEIVE Server returns 200 OK + weather data │
│ → PAYMENT-RESPONSE header with tx hash │
│ │
│ 6. RATE Agent posts feedback to ReputationRegistry │
│ → value=95, tag="quality", endpoint="..." │
│ → builds onchain reputation for next caller │
└─────────────────────────────────────────────────────────────┘import { x402Fetch } from '@x402/fetch';
import { createWallet } from '@x402/evm';
import { ethers } from 'ethers';
const wallet = createWallet(process.env.AGENT_PRIVATE_KEY);
const provider = new ethers.JsonRpcProvider(process.env.BASE_RPC_URL);
const IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';
const REPUTATION_REGISTRY = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';
// 1. Discover: find agents offering weather service
const registry = new ethers.Contract(IDENTITY_REGISTRY, registryAbi, provider);
// Query events or use The Graph subgraph for indexed agent discovery
// 2. Trust: check reputation
const reputation = new ethers.Contract(REPUTATION_REGISTRY, reputationAbi, provider);
const [count, value, decimals] = await reputation.getSummary(
agentId, trustedClients, "quality", "30days"
);
// Only proceed if value/10^decimals > 85
// 3-5. Pay + Receive: x402Fetch handles the entire 402 flow
const response = await x402Fetch(agentEndpoint, {
wallet,
preferredNetwork: 'eip155:8453'
});
const weatherData = await response.json();
// 6. Rate: post feedback onchain
const reputationWriter = new ethers.Contract(REPUTATION_REGISTRY, reputationAbi, signer);
await reputationWriter.giveFeedback(
agentId, 95, 0, "quality", "weather", agentEndpoint, "", ethers.ZeroHash
);