For Agents
The contract-scanner project went designed → planned → SHIPPED all on 2026-05-30. The 10-task TDD plan was executed; the MVP is built and live-validated (commit
5be49b6, repogithub.com/wowjeeez/bsc-vuln-scanner). This note captures the planning decisions (build order + concrete tech choices) — it does NOT re-state the design doc. For the workflow architecture, the BSC discovery funnel, target picks, and honest caveats, read contract-scanner first. For what was discovered actually executing this plan — the verified tool behaviors and the false assumptions that caused silent false-negatives — read verified-tool-behavior. For the follow-on Phase 2A address-resolution work, read phase2-address-resolution.
Outcome
All 10 tasks shipped. Task 10’s live EA Finance validation (which the plan marked BLOCKED on a free Etherscan key) unblocked and passed: the user’s free Etherscan V2 key worked for BSC, and the MVP produced real leads against EA Finance’s wCC contract (
0x6050d829f5a5e0ea758d8357ddcdec1381699248) — divide-before-multiply in reward calcs and unused-return on a message inspector.
Plan file location
/Users/levander/coding/bsc-vuln-scanner/docs/superpowers/plans/2026-05-30-mvp-bsc-scanner.md10 tasks, TDD (red → green → checkpoint per task). Driven by thesuperpowers:subagent-driven-developmentskill. Each task ends at a green-test Checkpoint instead of a commit (project rule: never auto-commit).
What’s new vs the design doc
The design doc (contract-scanner) answered what to build and why. The plan answers in what order, with which exact tools, and where the gotchas are. The decisions below are the new knowledge.
Build strategy — vertical slice first
Push ONE real contract (EA Finance) through all 5 stages end-to-end (Tasks 2–7) before generalizing to the batch funnel (Task 8).
- Tasks 2–6 build each stage’s inner functions (logic + a thin I/O wrapper), unit-tested with saved fixtures.
- Task 7 wires the orchestrator for a single contract via
--slug/--address. - Task 8 generalizes the same code to the batch funnel (
ThreadPoolExecutor,--batch --limit), refactoringrun_sliceto reuse an extractedrun_slice_collect(DRY).
Rationale
Fastest path to a real Slither finding; de-risks each stage on live data one at a time instead of debugging a whole batch funnel at once. This is the design doc’s “validation play” expressed as build order — prove value on EA Finance, then scale.
Key technical decisions (with rationale)
These are the load-bearing build-time choices
Each differs from or refines the design doc. Don’t lose them in implementation.
1. Pin Python 3.12 (not system 3.14) via uv
uv init --python 3.12. Slither / slither-analyzer does not reliably support Python 3.14 yet. 3.12 also matches the eventual Docker base image (python:3.12-slim), so local and container behavior stay identical.
Gotcha
Running on the system 3.14 will break Slither. The project is pinned to 3.12 on purpose — do not “upgrade” it.
2. Etherscan V2 unified API — not legacy BscScan
Stage 3 uses the Etherscan V2 unified endpoint (https://api.etherscan.io/v2/api with chainid=56 for BSC and a single API key), not the legacy per-chain BscScan endpoint the design doc mentioned. The base URL is config-driven (config.yaml → chain.explorer_base).
Rationale
One key works across all chains, so Stage 3 is already Phase-2-multichain-ready — flipping to Ethereum/Polygon/Arbitrum/Base/Optimism is just a different
chainid, no new client. Achainidregression assertion is baked into the Task 4 fetch test.
3. Slither runtime: local uv now → whole pipeline in Docker at the end
Slither is invoked as a subprocess on PATH (slither <target> --json -), so it behaves identically whether installed locally via uv or baked into the final image. Develop locally now; Task 9 packages the entire pipeline (scanner + Slither + solc) into one Dockerfile at the end — not stage-by-stage containerization. User’s explicit preference. solc-select installs/pins the per-contract compiler version (e.g. 0.8.19).
4. API key is a placeholder until Task 10
Build and test entirely on saved fixtures (key read from ETHERSCAN_API_KEY env / .env). Live EA Finance validation is deferred to Task 10, which is explicitly BLOCKED on the user adding a free Etherscan V2 key. Task 10 is a runbook, not an automated test (depends on live third-party data).
5. Architecture refinement — pure logic split from I/O
Each stage file splits pure logic (filtering / parsing / scoring — unit-tested with fixtures) from I/O (HTTP / subprocess — thin wrappers, one light test each). Shared dataclasses (Protocol, SourceResult, Finding) live once in scanner/models.py; shared config in config.yaml + a single cfg pytest fixture. Stage 5 (triage) is confirmed the largest task (Task 6) — matches the design doc’s “half the engineering is triage” principle.
Environment / tooling facts discovered (2026-05-30)
For Agents — verified state of the dev box
- Project folder:
~/coding/bsc-vuln-scanner(hyphen) — was empty, not a git repo.uv0.10.9 available.- Docker 28.5.2 daemon running (needed for Task 9).
- Slither not previously installed — added via
uv add slither-analyzer solc-select.- No chain API keys in env — hence the placeholder approach and the Task 10 block.
Path reconciliation — hyphen, not underscore
The design doc suggested
~/coding/contract_scanner/(underscore). The actual project lives at~/coding/bsc-vuln-scanner/(hyphen) — we are using the existing hyphen folder. Ignore the design doc’s underscore path; it was a pre-implementation suggestion.
Project policy baked into the plan
- No commits — each task ends at a green-test Checkpoint, not a
git commit. - No comments — all code is comment-free / self-explanatory.
- DRY — shared config + types live in one place;
run_slicereusesrun_slice_collect. - Run via venv — prefix commands with
uv runsoslither/solc-selectresolve from.venv/bin.
Task map (at a glance)
| Task | Stage / concern | Notes |
|---|---|---|
| 1 | Scaffold + data models | uv init --python 3.12, models.py, config.yaml |
| 2 | Stage 1 Discover | filters + Binance-not-BSC regression test |
| 3 | Stage 2 Resolve | slug → BSC addresses |
| 4 | Stage 3 Fetch source | Etherscan V2 getsourcecode, unverified-skip, format parsing |
| 5 | Stage 4 Analyze | solc-select + Slither subprocess + parse (+ marked integration test) |
| 6 | Stage 5 Triage | dedupe + drop FPs + score + CSV — largest task |
| 7 | Orchestrator — vertical slice | single contract end-to-end (--slug/--address) |
| 8 | Generalize to batch funnel | ThreadPoolExecutor, --batch --limit |
| 9 | Containerize whole pipeline | one Dockerfile (scanner + Slither + solc) |
| 10 | Live EA Finance validation | BLOCKED on API key — runbook, not a test |
Related
- contract-scanner — the design doc (architecture, BSC funnel, targets, caveats); read first
- LOG — this project’s session log
- TOPICS — this project’s theme index