qa
Use when a Scaffold-ETH 2 frontend is about to ship or needs a second look: "is this ready", "check my dApp", a teammate's patch. The checks people forget: wallet flow, wrong-network gating, contract registration, theme and loading states, branding, RPC posture, mobile wallets. Best from a fresh reviewer context. Not for how the frontend behaves for its users in general, such as approvals, decimals and address parsing (`/frontend-ux`).
- License 许可
- AGPL-3.0
- 最近更新
- 2026-11-14
- Stars
- ★ 81
- Forks
- 17
01 前言 Front Matter
- name
- qa
- description
- Use when a Scaffold-ETH 2 frontend is about to ship or needs a second look: "is this ready", "check my dApp", a teammate's patch. The checks people forget: wallet flow, wrong-network gating, contract registration, theme and loading states, branding, RPC posture, mobile wallets. Best from a fresh reviewer context. Not for how the frontend behaves for its users in general, such as approvals, decimals and address parsing (`/frontend-ux`).
02 资源文件 2
- 参考文档SOURCE.md339 B
- 参考文档TRUST.auto.yaml2.2 KB
03 SKILL.md 正文
dApp QA — pre-ship audit for Scaffold-ETH 2
Read the code, then click through every flow — with no wallet, with a wallet on the wrong chain, and with a wallet on the target chain. Report each finding with severity, file, line, and the concrete fix. Only change code if the task asks you to fix rather than review.
Wallet and action flow
- Disconnected state renders a Connect Wallet button (
RainbowKitCustomConnectButton), never a paragraph telling the user to connect. This is the single most common miss. - Wrong network turns the primary CTA itself into a "Switch to [chain]" button. The header's
WrongNetworkDropdownis not enough — without a branch in the action slot, the user clicks Approve on the wrong chain and eats a silent wagmi error. - One primary action at a time: Connect → Switch → Approve → Action. Approve and Action are never both live; which one renders is driven by the current allowance.
- Writes go through
useScaffoldWriteContract. Raw wagmiuseWriteContractoutside scaffold internals resolves at the wallet signature, not at confirmation. - Lock the button on
isMining— the flaguseScaffoldWriteContractsets aroundwriteContractAsync, not theisPendingit passes through from wagmi. (isMiningtracks the async path only; the hook's synchronouswriteContractnever sets it, so a button gated on it there never locks.)isMiningis held acrosswaitForTransactionReceiptand clears in the hook'sfinallyon both confirmation and rejection;isPendingdrops when the wallet returns the hash, re-enabling the button mid-flight. If the allowance or balance refetch needs its own hold after confirmation, keep it in local state and clear it infinallytoo — never on a fixed timer. - Failed and rejected transactions surface a human-readable message next to the action (
notification+getParsedError). Acatchthat only callsconsole.erroris a silent failure.
Contracts and addresses
-
External contracts (tokens, protocols) belong in
packages/nextjs/contracts/externalContracts.ts. Entries hand-added todeployedContracts.tsare wiped on the next deploy, and scaffold hooks silently return nothing for anything unregistered. Migrate rather than flag:// packages/nextjs/contracts/externalContracts.ts import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; const externalContracts = { 8453: { USDC: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", abi: [...] }, }, } as const; export default externalContracts satisfies GenericContractsDeclaration;Then revert
deployedContracts.tsto its generated state and confirmyarn next:check-typespasses. -
Every input that accepts an address uses
<AddressInput/>, not<input type="text">— a raw input drops ENS resolution and validation, sovitalik.ethnever reaches the contract. -
Addresses render through
<Address/>(blockie, ENS, copy, explorer link), not a hand-rolledshorten(). -
The contract the user transacts with is shown on the page. Agents display the connected wallet address and forget the contract itself.
Theme and loading states
- No hardcoded dark wrapper (
bg-black,bg-[#0a0a0a],bg-zinc-900) on a page or layout root. It bypasses DaisyUI, gives light-mode users a black page, and breaks the header'sSwitchTheme. Usebg-base-200 text-base-content. Forcingdata-theme="dark"is acceptable only if<SwitchTheme/>is also removed. - DaisyUI's
loadingclass on abtnreplaces the whole button with a spinner and swallows the label. Use an inline<span className="loading loading-spinner loading-sm" />inside the button, next to visible text.
Branding
The scaffold's defaults are template scaffolding, not product decisions. Check all five: tab title in layout.tsx (not "Scaffold-ETH 2 App"), the metadata description, the footer (BuidlGuidl / fork-me / support links), the README, and the default favicon. The OG image in layout.tsx metadata is an absolute URL (https://yourdomain.com/thumbnail.jpg); a relative path breaks link previews everywhere.
Config
pollingIntervalinscaffold.config.tsis 3000 in current SE-2. A raised value (older templates used 30000) makes an L2 app feel broken; keep ~3s, or use event-driven and post-confirmation refresh.- Production RPC: shipping on SE-2's default Alchemy key, or on the bare
http()fallback transport inwagmiConfig, means silently hitting rate-limited public endpoints. Route throughrpcOverrideswith aNEXT_PUBLIC_*key. That key ships in the client bundle, so restrict it to your domain in the provider dashboard. Verify the variable is actually set on the host, not just referenced in code.
Mobile
- On WalletConnect, tapping a transaction button must get the user to their wallet app with something to sign. Test it on a phone: if nothing happens and the user has to switch apps by hand, that is a finding. Any redirect fires the write first, since navigating away before the write call means the transaction never fires. It targets the wallet the user actually connected with, and it is skipped inside a wallet's in-app browser (
window.ethereumpresent). wagmi'sconnector.idonly says"walletConnect"— find the real wallet in thewc@2:clientsession in localStorage. Use bare schemes (rainbow://,metamask://);rainbow://dapp/...reloads the page. - Phantom is not in SE-2's default RainbowKit wallet list, so Phantom users cannot connect at all. Add
phantomWallettowagmiConnectors.tsx.
If it is deployed
Every deployed contract is verified on the block explorer (yarn verify --network <chain>). Unverified bytecode reads as something to hide. yarn deploy succeeding is not the finish line.
CROPS
The report includes a CROPS Review: the chosen default, accepted compromises, who can block users, what data leaks, who controls funds/upgrades/recovery, and the user's escape path. Missing, or a one-liner on an app holding funds or user data, is a finding. Use crops/SKILL.md for the full template.
References
- Docs: https://docs.scaffoldeth.io/ · Components: https://ui.scaffoldeth.io/
04 同仓库更多 Skills
recipe-performance
Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold/warm/background-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout/paint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.
mexc-spot-websocket
MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.
mexc-spot-rest
MEXC Spot REST workflows for public data, signed account requests, orders, wallet/admin actions, and secure signing without exposing API keys.
mexc-futures-websocket
MEXC Futures WebSocket workflows for public streams, private account/order/position streams, ping/pong, subscriptions, and depth maintenance.
0xklen-version-and-refresh-sanctions-lists
暂无简介
verify-tests-cover-changed-lines
Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.