For Agents
Phase 2A of contract-scanner — SHIPPED 2026-05-30 (commit
536e318). Solves THE bottleneck the MVP exposed: DeFiLlama’s API exposes no contract address for small protocols, so the MVP could only scan a contract you fed it by hand (--address). Phase 2A resolves a protocol’s BSC contract addresses automatically from its DeFiLlama TVL adapter source on GitHub, so--slug(and--batch) work with zero manual address entry or web search. This note covers the resolution architecture, the empirical validation lessons (it auto-resolves ~60%, NOT ~100%), the robustness bugs fixed before building, and the deferred Phase 2.1 levers.
The bottleneck Phase 2A solves
The MVP (see contract-scanner) assumed DeFiLlama’s /protocol/{slug} endpoint would expose contract addresses for ~70% of small protocols. It doesn’t — for small protocols like EA Finance it returned [] (no addresses). The MVP could therefore only analyze a contract you supplied via --address. Phase 2A removes that manual step.
How adapter-anchored resolution works
Each DeFiLlama protocol record has a module field naming its TVL adapter — the JS/TS file in the DefiLlama/DefiLlama-Adapters GitHub repo that computes the protocol’s TVL by reading on-chain balances. That adapter contains the protocol’s contract addresses (it has to, to query them). Phase 2A mines them.
Resolution Pipeline
graph TD A["DeFiLlama protocol record<br/><i>module field</i>"] --> B["Fetch adapter source<br/>raw.githubusercontent.com/.../projects/<module>"] B -->|"404 (~36%)"| Z["needs-manual-address.csv<br/><i>no silent gap</i>"] B --> C["Regex-extract 0x addresses"] C --> D["Verify each on BSCScan<br/><i>Etherscan V2 chainid=56</i><br/>= confidence gate"] D --> E["Drop infra denylist<br/><i>Pancake router / WBNB /<br/>stables / CAKE</i>"] E --> F["Prefer Tier-1 over Tier-2<br/>+ cap per protocol"] F --> G["Resolved addresses<br/><i>carry resolution_source</i>"] G --> H["Stage 3 fetch → Slither"] style A fill:#264653,stroke:#2a9d8f,color:#fff style B fill:#264653,stroke:#2a9d8f,color:#fff style D fill:#3d2020,stroke:#c44,color:#fff style E fill:#2d2d2d,stroke:#888,color:#fff style Z fill:#3d2020,stroke:#c44,color:#fff style G fill:#1a4d2e,stroke:#4caf50,color:#fff
Steps
- Read
modulefrom the DeFiLlama protocol record. - Fetch adapter source from
raw.githubusercontent.com/.../projects/<module>(the DefiLlama-Adapters repo). - Regex-extract
0x…addresses from the adapter source. - Verify each address on BSCScan (Etherscan V2,
chainid=56). Verification is the confidence gate — only addresses that resolve to a verified contract on BSC proceed. This filters out addresses for other chains that appear in multi-chain adapters. - Drop infra denylist — known shared infrastructure that is NOT the protocol’s own code: PancakeSwap router, WBNB, common stablecoins, CAKE.
- Tier preference + cap. Prefer Tier-1 (address came from DeFiLlama’s own record) over Tier-2 (address mined from the adapter). Cap the number of addresses analyzed per protocol so one adapter can’t blow up the batch.
- Findings carry a
resolution_sourcecolumn (andcontract_name) so a human reviewer can see how each address was obtained and judge attribution. - Unresolved protocols are not dropped silently — they go to
needs-manual-address.csv(a review bucket), so coverage gaps are visible, not hidden.
Empirical validation lessons (~25-protocol sample)
Adapter resolution auto-resolves ~60%, NOT ~100%
The EA Finance example (clean, single-chain, valid adapter) was best-case. Across a ~25-protocol sample the adapter approach auto-resolves roughly 60%. The remaining 40% need the deferred Phase 2.1 levers below. Do not assume full coverage.
- ~36% of adapters 404. DeFiLlama keeps stale
modulepointers after the underlying file is deleted/renamed in the GitHub repo — the record still names a module that no longer exists. This is the single biggest coverage hole and the highest-value next lever (see Phase 2.1). - Multi-chain adapters mix addresses across chains. An adapter for a multi-chain protocol contains addresses for Ethereum, Polygon, etc., not just BSC. BSCScan verification filters most of these out (an Ethereum address won’t verify as a contract on BSC). Example: Frax — only 2 of 19 extracted addresses verify on BSC.
- 3rd-party infra verifies on BSC but isn’t the protocol’s code. Routers, token contracts, and factory contracts (e.g. ICHIVaultFactory for TheDeep) verify on BSC but belong to shared infrastructure, not the protocol under review. The denylist + per-protocol cap +
resolution_source/contract_nametransparency mitigate this. Full own-code attribution is deferred — Phase 2A accepts some infra noise in exchange for coverage, and surfaces it transparently rather than hiding it.
The spec flaw this exposed: verified ≠ protocol's-own-code
BSCScan verification proves an address is a real verified contract on BSC — it does NOT prove the contract is the protocol’s own code. A verified PancakeSwap router is verified but irrelevant. This distinction (caught in pre-implementation validation, see below) is why the denylist, cap, and
resolution_sourcetransparency exist. Attribution to own-code is an unsolved, deferred problem.
Robustness bugs fixed (Part-0 hardening)
A 3-agent pre-implementation validation (see Process learning) found these real shipped bugs in the MVP before Phase 2A was built; they were fixed as Part-0 hardening:
Four silent-failure bugs in the MVP, fixed before Phase 2A
detect_languagemisclassified Solidity as Vyper on a substring match → the contract was silently skipped (Vyper isn’t Slither-analyzed the same way). Classic silent false-negative.- Malformed DeFiLlama records crashed the whole batch — one bad record took down the entire run instead of being skipped.
run_slicelacked exception isolation — an error in one protocol’s slice aborted the batch instead of being contained to that protocol.- Proxy implementation-fetch
raisediscarded recoverable analysis — when following a proxy to its implementation failed, the code raised and threw away analysis that could still proceed.
Live results (Phase 2A, real run)
What actually shipped works end-to-end with no manual input
--slug ea-finance(NO--address, no web search) now auto-resolves the wCC vault + StakingRewardsWCC via the adapter → 16 findings.--batch --limit 8→ 116 findings across 7 protocols + 1 correctly-reported unresolved (OpenGDP, akarakmodule mismatch → went toneeds-manual-address.csv). No denylisted infra in the findings, no crash.
Deferred — Phase 2.1 (next levers, in rough priority)
Highest-value first
- Fallback for the ~36% of 404 adapters — the biggest coverage lever; lifting this is what gets resolution past ~60%.
- Chain-aware adapter parsing — parse which chain each address belongs to inside multi-chain adapters, instead of relying on BSCScan-verify to filter.
- Web / deployer-based resolution — resolve addresses from the project site or deployer EOA when the adapter path fails.
- A “fetch-failed” review bucket — separate fetch failures from genuine no-address cases.
- Multi-chain — extend beyond BSC (Stage 3 is already
chainid-parameterized).- Aderyn second-opinion — Cyfrin’s Rust analyzer for findings confirmed by both tools (also a contract-scanner Phase 2 item).
Process learning
Pre-implementation 3-agent validation caught a spec flaw AND real bugs before building — high-value pattern
Before implementing Phase 2A, a 3-agent validation was run:
- Spec audit — caught the fundamental spec flaw: verified ≠ protocol’s-own-code (BSCScan verification is a confidence gate, not an attribution proof). This reshaped the design (denylist, cap,
resolution_source).- Empirical funnel test — measured the real adapter-resolution rate (~60%, not ~100%) and the 404 rate (~36%) on a live sample before committing to the approach.
- MVP re-audit — found the four Part-0 silent-failure bugs above in already-shipped MVP code.
Lesson: spending three read-only agents to audit spec + empirically test the funnel + re-audit existing code before writing the implementation caught a design-level flaw and real bugs cheaply. Worth repeating for the next phase.
Specs / plans on disk
- Design:
/Users/levander/coding/bsc-vuln-scanner/docs/superpowers/specs/2026-05-30-phase2-address-resolution-design.md- Plan:
/Users/levander/coding/bsc-vuln-scanner/docs/superpowers/plans/2026-05-30-phase2-address-resolution.md
Related
- contract-scanner — the design doc (5-stage workflow, BSC funnel, targets, caveats)
- mvp-implementation-plan — the MVP 10-task plan Phase 2A builds on
- verified-tool-behavior — the in-process compile + per-process solc + Etherscan V2 behaviors used here
- LOG — session log
- TOPICS — theme index