Skip to content

Latest commit

Β 

History

History
964 lines (731 loc) Β· 39.1 KB

File metadata and controls

964 lines (731 loc) Β· 39.1 KB

🦞 Larvae dApp Playbook

The complete build pipeline for shipping Ethereum dApps with clawd-larvae. Follow this document step by step. Every build starts here.


🚨 NON-NEGOTIABLE: Scaffold-ETH 2 Is The Stack

Every dApp build uses Scaffold-ETH 2. No exceptions. No alternatives. No "simpler" approaches.

This is defined by ethskills.com and is the foundation of the entire pipeline:

# THIS is how you start every project:
npx create-eth@latest

# THIS is how you run it:
yarn fork --network base   # NOT yarn chain
yarn deploy                # Auto-generates deployedContracts.ts
yarn start                 # Next.js frontend at localhost:3000

❌ NEVER DO ANY OF THESE:

  • forge init β€” use npx create-eth@latest
  • forge create β€” use yarn deploy (SE2's deploy scripts)
  • Manual Next.js setup β€” SE2 handles it
  • Raw viem/ethers.js for frontend contract calls β€” use SE2 hooks
  • Raw wagmi hooks (useWriteContract, useReadContract) β€” use useScaffoldWriteContract, useScaffoldReadContract
  • Manual wallet connection β€” SE2 has RainbowKit pre-configured
  • Edit deployedContracts.ts β€” it's auto-generated by yarn deploy
  • yarn chain β€” use yarn fork --network base (gives you real protocols and tokens)
  • Build standalone apps outside SE2 β€” the whole pipeline assumes SE2 structure

βœ… ALWAYS:

  • Contracts in packages/foundry/contracts/
  • Deploy scripts in packages/foundry/script/
  • Tests in packages/foundry/test/
  • Frontend pages in packages/nextjs/app/
  • Components in packages/nextjs/components/
  • External contracts in packages/nextjs/contracts/externalContracts.ts
  • SE2 hooks: useScaffoldReadContract, useScaffoldWriteContract, useScaffoldEventHistory
  • SE2 components: <Address/>, <AddressInput/>, <RainbowKitCustomConnectButton/>
  • scaffold.config.ts for chain targeting and config

If you're tempted to "simplify" by skipping SE2 β€” stop. The playbook, the ethskills, the QA checklist, the deployment pipeline β€” ALL of it assumes SE2. Building outside SE2 means none of the quality gates work.

Source: https://ethskills.com/orchestration/SKILL.md, https://ethskills.com/frontend-playbook/SKILL.md, https://ethskills.com/tools/SKILL.md


πŸ“¦ Git: Every Project Is a Repo

Every project gets a git repo from the start. Commit early, commit often. When you ship, you ship a polished repo β€” not a pile of files.

The Rules

  1. Set up the remote immediately after npx create-eth@latest β€” SE2 already initializes a git repo with an initial commit, so just add your remote and push the baseline
  2. Commit after every meaningful milestone β€” contract written, tests passing, deploy working, frontend built, QA fixes applied
  3. Commit messages describe WHAT changed and WHY β€” not "update" or "fix"
  4. The final repo must be clean β€” no leftover debug code, no commented-out experiments, no console.log spam
  5. README.md gets rewritten at the end β€” the SE2 default README is about SE2, yours is about YOUR app

Commit Cadence Through the Pipeline

Step Commit
After npx create-eth@latest git remote add origin <repo-url> && git push -u origin main
Step 2: Contracts written + tests pass "feat: add <Contract> with tests (N/N passing)"
Step 3: Audit fixes applied "fix: address audit findings β€” <summary>"
Step 4: Local deploy verified "chore: verify local fork deploy"
Step 5: Frontend built "feat: add frontend β€” <summary of pages/features>"
Step 6: QA fixes applied "fix: address frontend QA β€” <summary>"
Step 7: E2E pass "test: E2E pass β€” all user journeys verified"
Step 8: Production deploy "deploy: contracts live on <chain> at <address>"
Step 10: Frontend deployed "deploy: frontend live at <url>"
Final "docs: polish README for release"

The Final README

The shipped repo README must include:

  • What the app does β€” one paragraph, plain English
  • Live URL β€” link to the deployed frontend
  • Contract addresses β€” deployed addresses on each chain with block explorer links
  • How to run locally β€” yarn fork, yarn deploy, yarn start
  • Architecture β€” what contracts exist, what they do, how the frontend talks to them
  • Screenshots β€” at least one showing the main user flow
  • Tech stack β€” Scaffold-ETH 2, Foundry, Next.js, etc.

Do NOT leave the SE2 default README. That's the #1 tell that someone didn't finish the project.

.gitignore

SE2 comes with a good .gitignore. Make sure these are NOT committed:

  • node_modules/, .next/, out/, cache/
  • .env files with secrets
  • deployedContracts.ts is OK to commit (it's auto-generated but useful for the repo)

The Problem This Solves

AI agents build apps that are unusable. They generate code that compiles but nobody can actually use. The contract works but the frontend is broken. The frontend loads but the user can't figure out what to do. The approve flow is missing. The button doesn't disable. The network switch doesn't work. The transfer history is empty.

This playbook fixes that by starting every build with a plan and user journeys. Before a single line of code is written, we know exactly who uses the app, what they do, and what every screen looks like at every step. Then we build to that spec, test against it, and don't ship until every journey works end to end.


The Three-Phase System (from ethskills.com/orchestration)

Every build follows three phases. Never skip or combine them. If you find a bug in a later phase, go back to the appropriate earlier phase and fix it there.

Phase Environment What Happens
Phase 1: Local yarn fork + yarn deploy + yarn start Contracts + frontend on localhost against a fork of the target chain. All development and testing happens here. Iterate fast.
Phase 2: Live Contracts + Local UI Contracts on Base/Arbitrum + frontend on localhost Deploy contracts to the real network. Point the local frontend at them. Test every user journey with real wallets on the real chain. Small amounts.
Phase 3: Production Everything live Deploy frontend to IPFS (yarn ipfs) or Vercel. Set up production URL (ENS subdomain or domain). Test every user journey again on the live site. Share with beta testers. Ship.

Phase transition rules:

  • Phase 3 bug β†’ go back to Phase 2 (fix with local UI + live contracts)
  • Phase 2 contract bug β†’ go back to Phase 1 (fix locally, write regression test, redeploy)
  • Never hack around bugs in production

Step 1: Write the Plan

Before spawning any larvae, the parent agent writes a complete build plan.

This is the most important step. A clear plan prevents the #1 failure mode: building something that technically works but nobody can use.

1a. Identify User Archetypes

Every dApp has different types of users. List them all. For each one, identify:

  • Who they are β€” what's their role?
  • What they want β€” what's their goal?
  • What they need β€” what do they bring (tokens, ETH, permissions)?

Example β€” DEX:

Archetype Who Goal Needs
Swapper Regular user Exchange Token A for Token B Wallet + Token A
Liquidity Provider (LP) DeFi user Earn fees by providing liquidity Wallet + both tokens
Admin Protocol owner Set fees, pause in emergency Owner wallet

Example β€” Staking App:

Archetype Who Goal Needs
Staker Token holder Stake tokens to earn rewards Wallet + tokens
Claimer Active staker Claim accumulated rewards Wallet + staked position
Admin Contract owner Set reward rates, fund rewards pool Owner wallet + reward tokens

Example β€” NFT Mint:

Archetype Who Goal Needs
Minter Collector Mint an NFT Wallet + ETH for mint price
Holder NFT owner View their NFTs, see metadata Wallet + minted NFT
Admin Creator Set mint price, reveal, withdraw Owner wallet

1b. Write User Journeys

For EACH archetype, write out the exact step-by-step journey. Every click. Every screen state. Every transaction. This is what we build to and test against.

The journey format:

[Archetype Name] Journey:
1. Land on app β†’ see [what they see]
2. Click [button] β†’ [what happens]
3. [Next step] β†’ [what happens]
...
N. Done β†’ [final state]

Example β€” DEX Swapper Journey:

Swapper Journey:
1. Land on app β†’ see swap card with "From" token selector, amount input, "To" token selector, output preview
2. No wallet connected β†’ see big "Connect Wallet" button where the swap button would be
3. Click Connect Wallet β†’ RainbowKit modal opens, pick wallet
4. Connected but wrong network β†’ button changes to "Switch to Base"
5. Click Switch to Base β†’ wallet prompts network switch, button updates
6. Select input token (e.g. USDC) β†’ token selector dropdown, shows user's balance
7. Enter amount β†’ see output amount update in real-time, see USD values for both
8. If first time using this token β†’ button shows "Approve USDC" (not swap button yet)
9. Click Approve β†’ button shows spinner "Approving...", disabled, wallet pops up
10. Sign in wallet β†’ button stays "Approving..." until tx confirms onchain
11. Approval confirmed β†’ button changes to "Swap"
12. Click Swap β†’ button shows spinner "Swapping...", disabled, wallet pops up
13. Sign in wallet β†’ button stays "Swapping..." until tx confirms
14. Swap confirmed β†’ success message, balances update, swap card resets
15. See tx in transfer history below the swap card

Example β€” DEX LP Journey:

LP Journey:
1. Land on app β†’ see "Pools" or "Liquidity" tab
2. Click Liquidity tab β†’ see list of pools with APY, TVL
3. Click a pool β†’ see pool details, "Add Liquidity" card
4. Not connected β†’ Connect Wallet button
5. Connected, wrong network β†’ Switch to Base button
6. Enter amounts for both tokens β†’ see pool share preview, USD values
7. Need to approve Token A β†’ "Approve Token A" button
8. Approve Token A β†’ spinner, wallet, wait for confirm
9. Need to approve Token B β†’ "Approve Token B" button
10. Approve Token B β†’ spinner, wallet, wait for confirm
11. Both approved β†’ "Add Liquidity" button
12. Click Add Liquidity β†’ spinner, wallet, confirm
13. Done β†’ see LP position in "Your Positions" section, see pool share %

1c. Define the Contract Interface

From the user journeys, extract every onchain action:

Contract: SwapRouter
  - swap(tokenIn, tokenOut, amountIn, minAmountOut) β†’ called by Swapper at step 12
  - getAmountOut(tokenIn, tokenOut, amountIn) β†’ read by UI at step 7

Contract: LiquidityPool
  - addLiquidity(tokenA, tokenB, amountA, amountB) β†’ called by LP at step 11
  - removeLiquidity(tokenA, tokenB, shares) β†’ called by LP when withdrawing
  - getPoolInfo() β†’ read by UI at step 2

Every function maps to a specific step in a specific user journey. If a function doesn't map to any journey step, question whether it's needed.

1d. Define Testing Values

For local development, define smaller/faster values:

Testing overrides:
  - Mint price: 0.001 ETH (production: 0.05 ETH)
  - Staking period: 60 seconds (production: 7 days)
  - Min stake: 1 token (production: 100 tokens)
  - Reward rate: 1 token/minute (production: 100 tokens/day)

These get used in Phase 1. Production values get set in Phase 2/3.

1e. Write It All Down

The parent agent writes this plan to shared-workspace/BUILD-PLAN.md. This file gets copied into every larva's workspace so they all work from the same spec.

1f. Set Up the Git Remote

SE2 already initializes a git repo with an initial commit. Just add the remote:

npx create-eth@latest       # Creates the SE2 project (includes git init + first commit)
cd <project-name>
git remote add origin <github-repo-url>
git push -u origin main

This clean SE2 baseline is already committed β€” every subsequent git diff shows exactly what you added.


Step 2: Build the Contract

Spawn the contract developer larva:

./larvae.sh spawn contract-dev --model opus --profile builder

Give it the plan. Be SPECIFIC and EXPLICIT about SE2:

Read ETHSKILLS.md first. Follow the phases exactly.

Here is the build plan:
[paste from BUILD-PLAN.md β€” archetypes, journeys, contract interface, testing values]

## Setup β€” FOLLOW EXACTLY:

1. Create the SE2 project:
   npx create-eth@latest
   (select Foundry when prompted for the framework)

2. Install dependencies:
   cd <project-name> && yarn install

3. Write your contracts in packages/foundry/contracts/
4. Write deploy scripts in packages/foundry/script/
5. Write tests in packages/foundry/test/

DO NOT use forge init. DO NOT create a standalone project.
DO NOT use raw viem or ethers.js. This is a Scaffold-ETH 2 project.

## Build the contracts. Write comprehensive tests covering:
- Every function from every user journey
- Edge cases: zero amounts, max uint, unauthorized callers, self-transfers
- Fuzz tests for any math operations
- Access control: non-owner can't call admin functions
- Events emitted for every state change

## Run the tests:
cd packages/foundry && forge test -vvv

They must all pass. Show me the results.

Parent validates after completion:

  • SE2 monorepo exists (packages/foundry/ present)
  • Contract files in packages/foundry/contracts/
  • Deploy script in packages/foundry/script/
  • Test file in packages/foundry/test/
  • Tests were actually run (look for pass/fail output)
  • All tests pass
  • No hallucinated addresses
  • Contract interface matches the build plan
  • Git: commit β€” git add -A && git commit -m "feat: add <Contract> with tests (N/N passing)"

Step 3: Audit the Contract

Spawn a SEPARATE QA larva with FRESH context. Never audit with the same agent that built the code. Fresh eyes catch what the builder is blind to.

./larvae.sh spawn qa-audit --model opus --profile auditor

Copy the project into the QA workspace:

cp -r shared-workspace/contract-dev/<project> shared-workspace/qa-audit/

Prompt the QA larva:

You are a smart contract security auditor.

Read ETHSKILLS.md first β€” focus on the security and qa sections.

The code to audit is in your workspace at:
  <project>/packages/foundry/contracts/
  <project>/packages/foundry/test/
  <project>/packages/foundry/script/

Your job:
1. Read every contract source file
2. Run the tests yourself: cd <project> && forge test -vvv
3. Run slither if available: slither .
4. Check every item on the ethskills/security pre-deploy checklist:
   - Access control on every admin function
   - Reentrancy protection (CEI pattern + nonReentrant)
   - Token decimal handling (no hardcoded 1e18 for non-18-decimal tokens)
   - Integer math (multiply before divide)
   - SafeERC20 for all token operations
   - Input validation (zero address, zero amount, bounds)
   - Events emitted for every state change
   - No infinite approvals
5. Report PASS/FAIL for each checklist item
6. List any bugs, vulnerabilities, or concerns
7. Give an overall SHIP / NO-SHIP verdict

Do NOT fix anything. Only report findings.

Parent reviews the audit report. There are three outcomes:

Outcome A: SHIP β€” All Clear

Move to Step 4.

Outcome B: NO-SHIP β€” Real Issues

Send the findings back to the contract-dev larva:

./larvae.sh talk contract-dev "Audit found these issues:
1. [finding]
2. [finding]
Fix them. Run tests. Confirm all pass."

Then re-audit (repeat Step 3).

Outcome C: NO-SHIP β€” False Positives or Known Edge Cases

Audit bots are often overzealous. Not every finding needs a fix. Common situations:

  • "No reentrancy guard on view function" β€” views can't be reentered, ignore
  • "Centralization risk: owner can pause" β€” that's by design, document it
  • "No timelocked admin" β€” valid for MVP, document as known limitation
  • "Token doesn't handle fee-on-transfer" β€” if you only support standard ERC-20s, that's fine

For each finding, decide: Fix, Document as known issue, or Dismiss as false positive.

Document decisions in shared-workspace/AUDIT-NOTES.md:

## Audit Notes
- Finding: "Owner can drain contract" β†’ Fix: Added withdrawal limits
- Finding: "No timelock on admin" β†’ Known: MVP ships without timelock, add in v2
- Finding: "Centralization risk" β†’ Dismissed: Owner is a multisig in production

Git: commit audit fixes β€” git add -A && git commit -m "fix: address audit findings β€” <summary>"


Step 4: Deploy to Local Fork

The contract is built and audited. Now deploy it locally and prepare for frontend development.

# In the SE2 project directory:
yarn fork --network base       # Terminal 1: fork of real Base
cast rpc anvil_setIntervalMining 1  # Enable block mining for timestamps
yarn deploy                    # Terminal 2: deploy to local fork

Critical: During local development, scaffold.config.ts must target chains.foundry (chain ID 31337), NOT chains.base. The fork runs on Anvil locally. Switch to chains.base only when deploying to the real network in Phase 2.

Use the testing values from the build plan (smaller amounts, shorter times) for fast iteration.


Step 5: Build the Frontend

Spawn the frontend developer larva:

./larvae.sh spawn frontend-dev --model opus --profile frontend

Copy the contract project (with contracts already built and deployed locally):

cp -r shared-workspace/contract-dev/<project> shared-workspace/frontend-dev/

Give it the build plan AND the user journeys. This is the key difference β€” the frontend dev builds to the user journeys, not to an abstract feature list.

Read ETHSKILLS.md first β€” especially frontend-ux, frontend-playbook, orchestration, and qa.

Here is the build plan with user journeys:
[paste BUILD-PLAN.md]

Build the frontend in the existing SE2 project at <project>/packages/nextjs/

CRITICAL RULES (from ethskills):

1. EVERY onchain button must disable + show spinner from click until block confirmation.
   Use useScaffoldWriteContract (NOT raw wagmi useWriteContract).
   Each button gets its OWN loading state. Never share isLoading across buttons.

2. Four-state button flow β€” show exactly ONE button at a time:
   Not connected β†’ "Connect Wallet" button (RainbowKitCustomConnectButton)
   Wrong network β†’ "Switch to Base" button
   Needs approval β†’ "Approve [Token]" button (with spinner per rule 1)
   Ready β†’ Action button ("Swap", "Stake", etc.)
   NEVER show "please connect your wallet" as text. Always a button.
   NEVER show Approve and Action buttons simultaneously.

3. Use <Address/> for ALL address display. Use <AddressInput/> for all address input.
   Show the deployed contract address at the bottom of the page.

4. Show USD values next to every token/ETH amount (display AND input).
   Use useNativeCurrencyPrice() for ETH price.

5. Use SE2 hooks ONLY β€” useScaffoldReadContract, useScaffoldWriteContract, useScaffoldEventHistory.
   Never use raw wagmi hooks (useWriteContract, useReadContract).

6. Human-readable amounts β€” formatEther/formatUnits for display, parseEther/parseUnits for contract calls.
   Never show raw wei to users.

7. scaffold.config.ts:
   - pollingInterval: 3000 (not the default 30000)
   - rpcOverrides via process.env (never hardcoded API keys)
   - targetNetworks: [chains.foundry] for local dev

8. Remove ALL SE2 default branding:
   - Footer: remove BuidlGuidl links, "Fork me", SE2 mentions
   - Tab title: app name, not "Scaffold-ETH 2"
   - README: about THIS project, not the SE2 template
   - Favicon: custom, not SE2 default
   - No duplicate h1 matching the header

9. Register any external contracts in externalContracts.ts BEFORE building components.

Build EACH user journey as described in the plan. The user should be able to walk through
every step of every journey exactly as written.

Git: commit frontend β€” git add -A && git commit -m "feat: add frontend β€” <summary of pages/features>"


Step 6: Frontend QA

Spawn a fresh QA larva for frontend review:

./larvae.sh spawn qa-frontend --model opus --profile qa

Copy the project:

cp -r shared-workspace/frontend-dev/<project> shared-workspace/qa-frontend/
You are a frontend QA reviewer for an Ethereum dApp.

Read ETHSKILLS.md first β€” focus on qa and frontend-ux sections.

The code is in your workspace. Review every .tsx file in packages/nextjs/app/
and packages/nextjs/components/, plus scaffold.config.ts and externalContracts.ts.

Check the ethskills/qa Pre-Ship Audit β€” report PASS/FAIL for each:

Ship-Blocking:
- [ ] Wallet connection shows a BUTTON, not text
- [ ] Wrong network shows a Switch button
- [ ] One button at a time (Connect β†’ Network β†’ Approve β†’ Action)
- [ ] Every onchain button disables + spinner through block confirmation
- [ ] Uses useScaffoldWriteContract, NOT raw wagmi useWriteContract
- [ ] SE2 footer branding removed
- [ ] SE2 tab title removed
- [ ] SE2 README replaced

Should Fix:
- [ ] Contract address displayed with <Address/> component
- [ ] <AddressInput/> used for all address inputs
- [ ] USD values next to all token/ETH amounts
- [ ] OG image is absolute production URL (not localhost, not relative)
- [ ] pollingInterval is 3000
- [ ] RPC overrides set via env vars (not default SE2 key, not hardcoded)
- [ ] No hardcoded API keys in any committed file
- [ ] Favicon updated from SE2 default
- [ ] Human-readable amounts everywhere (no raw wei)
- [ ] No duplicate h1 matching header
- [ ] Each button has its own loading state (not shared isLoading)

Give SHIP / NO-SHIP verdict.

Fix any issues by talking to the frontend-dev larva (same as Step 3 Outcome B).

Git: commit QA fixes β€” git add -A && git commit -m "fix: address frontend QA β€” <summary>"


Step 7: Walk Every User Journey on Localhost (Burner Wallet E2E)

This is where most builds currently fail. The code passes QA but the actual user experience is broken.

Larvae CAN do this step. Scaffold-ETH 2 provides burner wallets on local forks β€” no MetaMask extension needed. The larva uses its headless browser to:

  1. Open localhost:3000
  2. SE2 auto-connects a burner wallet on chains.foundry (Anvil)
  3. Walk EVERY user journey step, taking screenshots at each state
  4. Actually click buttons, submit transactions, and verify results onchain

How to Run This Step

Spawn a QA larva WITH browser access (the Docker image includes headless Chromium):

./larvae.sh spawn qa-e2e --model opus --profile qa

Copy the full project (with frontend built):

cp -r shared-workspace/frontend-dev/<project> shared-workspace/qa-e2e/

The QA larva must start the full SE2 stack inside its container, then use the browser tool to test.

⚠️ CRITICAL BROWSER NOTES (learned the hard way):

  1. Pre-warm Chromium β€” The first browser call cold-starts Chromium (15-30s). Add a "browser start" step before navigating or the first call will timeout.
  2. Don't pass target or profile β€” Let the browser tool use defaults. Passing target="sandbox" or profile="openclaw" triggers sandbox mode which doesn't work in our setup.
  3. Faucet first β€” SE2 burner wallets on Anvil start with 0 ETH. The larva needs to grab faucet funds before sending transactions. The Debug Contracts page has a faucet button, or use cast send.
  4. Debug Contracts page β€” The counter/contract interactions are on /debug not the landing page. Tell the larva to navigate there.
Read ETHSKILLS.md first β€” focus on qa and frontend-ux sections.

You have a headless Chromium browser available via the `browser` tool.
The SE2 project is in your workspace at <project>/.

Your job: START the Scaffold-ETH 2 app and walk EVERY user journey from BUILD-PLAN.md using the browser.

## Setup β€” THIS IS A SCAFFOLD-ETH 2 PROJECT. Use SE2 commands EXACTLY:

1. Start the local Anvil fork (NOT yarn chain β€” fork gives you real protocols):
   cd <project> && yarn fork --network base &
   (wait for Anvil to be ready β€” you'll see "Listening on 0.0.0.0:8545")

2. Enable block mining (REQUIRED for timestamp-dependent logic):
   cast rpc anvil_setIntervalMining 1

3. Deploy contracts to the fork (this auto-generates deployedContracts.ts):
   yarn deploy

4. Start the SE2 Next.js frontend:
   yarn start &
   (wait for localhost:3000 to be ready)

DO NOT use forge create, forge script directly, or any non-SE2 deploy method.
DO NOT build a standalone frontend. The SE2 frontend is already configured.

## Testing with Burner Wallets:

SE2 on chains.foundry auto-generates a burner wallet with a funded Anvil account.
When you open localhost:3000, the burner wallet connects automatically.

For the Depositor journey, you need the burner wallet to have CLAWD tokens.
On the Anvil fork, you can impersonate the real CLAWD holders to send tokens:

```bash
# Find a large CLAWD holder and impersonate them to fund the burner wallet
cast send --unlocked --from <whale_address> <CLAWD_token_address> \
  "transfer(address,uint256)" <burner_wallet_address> <amount> \
  --rpc-url http://localhost:8545

Walk EVERY Journey:

Viewer Journey:

  1. Open localhost:3000 in the browser (browser tool: navigate)
  2. Take a screenshot β€” verify: recipient address visible, progress bar, countdown timer
  3. Verify all read values make sense (total locked, vested, claimed, claimable)

Depositor Journey:

  1. Ensure burner wallet has CLAWD tokens (use cast impersonation above)
  2. Navigate to the app
  3. Verify burner wallet is auto-connected
  4. Enter deposit amount
  5. Click Approve β†’ take screenshot β†’ verify spinner/loading state
  6. Wait for approval to confirm β†’ take screenshot β†’ verify button changed to "Deposit"
  7. Click Deposit β†’ take screenshot β†’ verify spinner
  8. Wait for deposit to confirm β†’ take screenshot β†’ verify dashboard updated

Claimer Journey:

  1. Advance the Anvil fork time to simulate vesting: cast rpc evm_increaseTime 150 # Half the 300s test duration cast rpc evm_mine
  2. Refresh the page β†’ take screenshot β†’ verify claimable amount > 0
  3. Click Claim β†’ take screenshot β†’ verify spinner
  4. Wait for claim to confirm β†’ take screenshot β†’ verify claimed amount increased
  5. Advance time to full vesting (300s) and claim remaining

For EACH step, verify:

  • Does the UI show what the journey says it should?
  • Does the button disable + show spinner during tx?
  • Does the result appear after confirmation?
  • Are amounts human-readable (not raw wei)?
  • Is the progress bar accurate?

Report:

For each journey, report PASS/FAIL per step with screenshots. If ANY step fails, describe exactly what went wrong and what you expected. Give an overall E2E SHIP / NO-SHIP verdict.


**Common failures caught at this step:**
- Approve flow doesn't transition to action button after approval confirms
- Transfer history doesn't show new transactions until page refresh
- Amount input doesn't validate (lets you enter more than your balance)
- Error when rejecting tx in wallet (UI doesn't recover)
- Network switch doesn't actually switch (button stays)
- USD values are NaN or $0.00
- Page is blank when no wallet is connected
- Progress bar doesn't update after time passes
- Claim button visible but claimable amount is 0
- Deposit works but dashboard doesn't reflect new total

**If ANY journey step fails:** Go back to Step 5 (frontend) or even Step 2 (contract) if the issue is in the contract. Fix it. Re-test. This loop is normal and expected β€” don't skip it.

---

## Step 8: Deploy Contracts to Target Network (Phase 2)

Once all journeys work on localhost:

```bash
# Update scaffold.config.ts
targetNetworks: [chains.base]  # Switch from chains.foundry to real chain

# Generate deployer wallet
yarn generate
yarn account  # Get the address, send ETH to it

# Deploy to real Base
yarn deploy --network base

# Verify on block explorer
yarn verify --network base

Use production values now β€” real mint prices, real staking periods, real minimum amounts. Update the deploy script or constructor args.

Post-deploy checks:

  • Contract verified on BaseScan
  • All read functions return expected values
  • One small test transaction works
  • Git: commit β€” git add -A && git commit -m "deploy: contracts live on <chain> at <address>"

Step 9: Test Every Journey on Real Network with Local UI (Human + Real Wallet)

This step requires a HUMAN with a real browser and MetaMask/wallet extension. Larvae cannot do this β€” they don't have wallet extensions.

Keep the frontend on localhost but pointed at the real Base contracts. This is Phase 2 of the three-phase system.

Walk through EVERY user journey again, but now with:

  • Real wallets (not burner wallets) β€” MetaMask, Rainbow, Coinbase Wallet, etc.
  • Real tokens on Base
  • Small real amounts ($1-$10)
  • Real gas costs
For each journey in BUILD-PLAN.md:
  1. Open localhost:3000 connected to Base
  2. Walk every step with a real wallet
  3. Verify every transaction actually lands onchain
  4. Check block explorer for each tx
  5. Verify events emitted correctly
  6. Document any failures

The parent agent can assist by watching over the human's shoulder (via browser relay/screenshots) and checking on-chain state with cast or etherscan, but the human drives the wallet.

If ANY step fails: Go back to the appropriate phase:

  • Frontend bug β†’ Step 5, fix, re-test from Step 7
  • Contract bug β†’ Step 2, fix, re-test from Step 3 (re-audit!), redeploy contracts, re-test from Step 9
  • Going back is normal. Going back is good. It means you caught it before users did.

Step 10: Deploy Frontend to Production (Phase 3)

Once all journeys work on real Base with local UI:

Pre-deploy checklist:

  • onlyLocalBurnerWallet: true in scaffold.config.ts (prevents burner wallet in prod)
  • OG image created (1200x630 PNG, not the SE2 default)
  • OG image URL set to production domain (absolute URL)
  • All production values set (not testing values)
  • No secrets in committed files

Deploy to IPFS:

cd packages/nextjs
rm -rf .next out  # ALWAYS clean first

NEXT_PUBLIC_PRODUCTION_URL="https://myapp.yourname.eth.link" \
  NODE_OPTIONS="--require ./polyfill-localstorage.cjs" \
  NEXT_PUBLIC_IPFS_BUILD=true \
  NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \
  yarn build

# Verify before uploading:
ls out/*/index.html                        # Routes exist
grep 'og:image' out/index.html             # Not localhost
# If CID didn't change from last deploy, you deployed stale code!

yarn bgipfs upload out   # Save the CID

Or deploy to Vercel:

cd packages/nextjs && vercel
# Root Directory: packages/nextjs
# Install Command: cd ../.. && yarn install

Set up production URL:

  • ENS subdomain: Create subdomain on app.ens.domains β†’ set content hash to ipfs://<CID>
  • Custom domain: Point DNS to Vercel or use a gateway
  • This sometimes needs a human β€” if ENS transactions are needed, tell the human what to do

Git: commit β€” git add -A && git commit -m "deploy: frontend live at <url>"


Step 11: Test Every Journey on Live Production

The final test. Everything is live β€” real contracts, real frontend, real URL.

Walk through EVERY user journey one more time:

For each journey in BUILD-PLAN.md:
  1. Open the production URL in a browser
  2. Verify the site loads (not 404, not blank page)
  3. Check tab title (not "Scaffold-ETH 2")
  4. Check OG unfurl (share the link, see the preview)
  5. Walk every step of every journey with real wallets on Base
  6. Test on mobile too (wallet deep linking, responsive layout)
  7. Document any failures

If anything fails: Go back to the appropriate step. Redeploy as needed. This is normal.

Common Phase 3 failures:

  • Routes return 404 on IPFS (missing trailingSlash: true)
  • OG image shows localhost URL
  • Burner wallet showing in production
  • Different behavior on mobile vs desktop
  • Wallet deep linking not working (MetaMask, Rainbow)

Step 12: Redeploy with Production Values

If you used any testing overrides (smaller amounts, shorter times), now is when you set the final production values:

  • Redeploy contracts with production constructor args if needed
  • Update externalContracts.ts with new contract addresses
  • Rebuild and redeploy frontend
  • Re-test affected journeys

Step 13: Beta Testing

Share the production URL with beta testers. Give them the user journeys and ask them to walk through each one.

Collect feedback. Common beta feedback:

  • "I didn't know I needed to approve first" β†’ improve the approve button copy
  • "It looked like nothing happened" β†’ loading state not visible enough
  • "I couldn't figure out how to connect" β†’ connect button not prominent enough

Fix issues. Go back to whatever step is needed. Redeploy.


Step 14: Ship It

When beta testers can walk through every journey without confusion:

  1. Polish the README β€” Replace the SE2 default README entirely. Include:
    • What the app does (one paragraph)
    • Live URL
    • Contract addresses with block explorer links
    • How to run locally (yarn fork, yarn deploy, yarn start)
    • Architecture overview
    • Screenshots of the main flow
    • Tech stack
  2. Final git commit + push:
    git add -A && git commit -m "docs: polish README for release"
    git remote add origin <github-url>  # if not already set
    git push -u origin main
  3. Tweet the live URL β€” include a screenshot/video of the main flow
  4. Post to relevant communities β€” Farcaster, Discord, etc.
  5. Monitor β€” watch contract events on BaseScan, check for unexpected behavior
  6. Have an incident plan β€” if something goes wrong, know how to pause (if the contract supports it) and communicate

The shipped repo should be something you're proud to share. Clean commit history, polished README, no junk files. This IS the deliverable.


Archetype Reference: User Journeys

Quick-reference user journeys for common dApp types. Use these as starting points β€” customize for your specific app.

Token Launch

Archetypes: Buyer, Holder, Admin

Buyer: Connect β†’ see token info (name, symbol, price, supply) β†’ enter amount β†’ approve payment token β†’ buy β†’ see tokens in balance
Holder: Connect β†’ see balance β†’ enter recipient + amount β†’ send β†’ see updated balance + tx in history
Admin: Connect β†’ see admin panel (if owner) β†’ set price / pause / withdraw β†’ confirm tx

NFT Collection

Archetypes: Minter, Holder, Admin

Minter: Connect β†’ see collection info (name, supply, mint price, remaining) β†’ click Mint β†’ pay ETH β†’ see NFT appear in "Your NFTs"
Holder: Connect β†’ see "Your NFTs" gallery β†’ click NFT β†’ see metadata, traits, image β†’ option to transfer
Admin: Connect β†’ set base URI (reveal) β†’ withdraw mint proceeds β†’ set mint price

Staking App

Archetypes: Staker, Claimer, Admin

Staker: Connect β†’ see APY, total staked, your position β†’ enter amount β†’ approve token β†’ stake β†’ see position update
Claimer: Connect β†’ see claimable rewards β†’ click Claim β†’ rewards added to wallet
Unstaker: Connect β†’ see staked position β†’ click Unstake β†’ wait for cooldown (if any) β†’ withdraw
Admin: Connect β†’ set reward rate β†’ fund reward pool β†’ pause in emergency

DAO / Governance

Archetypes: Voter, Proposer, Delegate, Admin

Voter: Connect β†’ see active proposals β†’ read proposal β†’ vote For/Against/Abstain β†’ see vote recorded
Proposer: Connect β†’ click "New Proposal" β†’ fill in title, description, actions β†’ submit β†’ proposal goes to voting
Delegate: Connect β†’ see delegate selection β†’ enter delegate address or self β†’ confirm delegation

Marketplace

Archetypes: Seller, Buyer

Seller: Connect β†’ click "List Item" β†’ select NFT β†’ set price β†’ approve NFT β†’ list β†’ see listing appear
Buyer: Connect β†’ browse listings β†’ click item β†’ see details + price β†’ buy β†’ NFT transfers to wallet, payment to seller

The System: How Larvae Work

What We Have

  • clawd-larvae: Docker containers running OpenClaw with ephemeral AI agents
  • ethskills: 17 skills from ethskills.com baked into every larva at spawn (190KB)
  • Persistent workspaces: shared-workspace/<name>/ β€” files survive container death
  • Models: Opus 4.6 (best, ~$2/build), Sonnet 4.5 (fast/cheap), GPT 5.2 (alternative)

Commands

./larvae.sh spawn <name> --model opus --profile builder   # Hatch a larva with a profile
./larvae.sh talk <name> "message"         # Send it work
./larvae.sh list                          # See all larvae
./larvae.sh status <name>                 # Check health
./larvae.sh logs <name>                   # View container logs
./larvae.sh kill <name>                   # Kill one
./larvae.sh killall                       # Kill all

Profiles

builder   β†’ full-stack engineer: contracts + frontend + tests (all ethskills)
auditor   β†’ security-focused Solidity auditor: finds bugs, never fixes (security + testing skills)
qa        β†’ obsessive frontend QA: enforces ethskills/qa checklist to the letter (qa + frontend skills)
frontend  β†’ senior frontend dev: SE2 hooks, wallet flow, UX (frontend + qa skills)
all       β†’ generic dev with all 17 ethskills (default)

Typical Larva Team

contract-dev  --profile builder   β†’ builds contracts + tests
qa-audit      --profile auditor   β†’ audits contracts (fresh context, separate from builder)
frontend-dev  --profile frontend  β†’ builds frontend to user journey specs
qa-frontend   --profile qa        β†’ audits frontend (fresh context)

Key Rules

  • Always say "Read ETHSKILLS.md first" in every prompt
  • Always include the build plan + user journeys in prompts
  • Separate build from audit β€” never audit with the same agent that built
  • One task per talk β€” don't overload a single message
  • Copy files between workspaces when sharing (each larva has its own directory)

Known Limitations

  1. Local models can't do agent work yet β€” only cloud models (Opus, Sonnet, GPT) use tools reliably
  2. Headless browser only β€” larvae have Chromium but no display; they use the browser tool for screenshots/snapshots/interaction. No MetaMask extension β€” use SE2 burner wallets for local testing, human tests with real wallet in Phase 2/3.
  3. Single-turn talks β€” each talk is stateless; larva sees SOUL + AGENTS + ETHSKILLS + your message
  4. 190KB ethskills eats context β€” for very complex tasks, keep prompts focused
  5. File sharing is manual β€” cp -r between workspace directories
  6. Human needed for β€” ENS setup, funding deployers, real-wallet QA (Phase 2/3), production URL setup
  7. Burner wallets cover 90% of testing β€” SE2 auto-connects a burner wallet on local forks, enabling full user journey testing without extensions. Only Phase 2+ (real network, real wallet) requires human interaction.

After Every Build

Update this playbook:

  1. What journey steps failed? Add them as warnings to the relevant step.
  2. What did QA miss? Strengthen the QA prompts.
  3. What did the human have to fix? Every manual fix = playbook gap. Close it.
  4. What took too long? Find bottlenecks. Optimize.
  5. What worked great? Document it so we repeat it.