Drift-free, auto-generated ABI documentation for Foundry Solidity projects — so upstream consumers (SDKs, integrators, debuggers) get an authoritative map of every callable surface that cannot rot when the ABI changes.
Extracted from AAStarCommunity/airaccount-contract (v0.17.2-beta.4). Copy it into any Foundry repo.
docs/abi/reference.md(generated) — per-contract: every function's signature, 4-byte selector, params/returns (with NatSpec), state mutability, best-effort access control; plus events (topic0) and custom errors.docs/abi/selectors.md(generated) — flat global index: function selectors, error selectors, event topics.docs/abi/{README,capabilities,sdk-integration}.md(hand-written, from templates) — the index, a capability→function→test-script map, and an SDK integration guide.
Those render NatSpec into prose (mdBook). They do not give SDK consumers the things that matter most: 4-byte selectors, capability grouping, error/event selector tables, and a drift gate tied to the exact compiled ABI. This kit is one ~400-line Node script with one dependency (viem, only for keccak event/error topics — function selectors come from solc's methodIdentifiers).
Source of truth = Foundry's compiled artifacts out/<C>.sol/<C>.json, which already contain:
abi— fragmentsmethodIdentifiers— solc's authoritative signature → 4-byte selector mapmetadata.output.userdoc/devdoc— NatSpec (@notice/@dev/@param/@return)metadata.settings.compilationTarget— used to keep only YOURsrc/contracts (drops deps)
The generator renders these to markdown. --check regenerates in memory and diffs against the committed files (exit 1 on mismatch) — the CI drift gate. Output is a pure function of out/ + src/ (no timestamps) → byte-identical re-runs.
forge build(producesout/).- Copy
gen-abi-docs.mjs→ your repo'sscripts/. (It's path-relative toscripts/..= repo root; no edits needed for a standard Foundry layout.) - Add to
package.json(seetemplates/package-scripts.json):Ensure"gen:abi-docs": "node scripts/gen-abi-docs.mjs", "gen:abi-docs:check": "node scripts/gen-abi-docs.mjs --check"
viemis a devDependency. pnpm gen:abi-docs→ commitdocs/abi/reference.md+selectors.md.- Add the CI drift gate (see
templates/ci-abi-docs-check.yml) — runs afterforge test(reuses itsout/). - Hand-write
docs/abi/{README,capabilities,sdk-integration}.mdfromtemplates/docs-abi/— map your domain capabilities → functions → the test scripts that exercise them (your e2e/integration tests are the canonical call examples).
- Generic (copy as-is): the whole generator — artifact reader, selector computation, NatSpec extraction, access-control scraping,
--checkdrift gate, idempotent output. - Repo-specific (you write):
capabilities.md+sdk-integration.md(your domain), and optionally a contract include/exclude filter if you don't want everysrc/contract.
Doc quality = NatSpec coverage. The generator can only render the @notice/@dev/@param you wrote. Write NatSpec on your external/public functions.
gen-abi-docs.mjs— the generator (copy toscripts/).templates/package-scripts.json— the two npm scripts.templates/ci-abi-docs-check.yml— GitHub Actions drift-gate steps.templates/docs-abi/{README,capabilities,sdk-integration}.md— hand-written doc skeletons.