feat(bot): extend discover_pools.py to v3/Curve, verify v2 fee_bps per factory #18
No reviewers
Labels
No labels
auto-merge
auto-merge
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
fortiblox/arc-mev-bot!18
Loading…
Reference in a new issue
No description provided.
Delete branch "data/discover-v3-curve"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Discovery extension: v3/Curve + per-factory fee verification (data lane, WP 7901)
Extends
bot/discover_pools.pyfrom v2-only to a full sweep:PoolCreateddecoded and cross-checked against realslot0()/liquidity()/tickSpacing()reads on chain.TokenExchange-emitter pass + on-chain probe (coins/A/fee/ABI shape — one is a uint256-ABI Solidity stableswap distinct from the 16 int128-ABI NG-style pools).other_venues), not registry kinds.Per-factory v2
fee_bpsverified two independent ways that must agree: swap-event reconstruction (exact integer match to the UniswapV2 formula) andeth_callsimulation (pair.swap()with a state override ontoken0, binary-searching the accepted fee). Result: every UniswapV2-interface factory is 30 bps except one at 50 bps. TwoPairCreated-emitting factories turned out to have noswap(uint256,uint256,address,bytes)selector in their pair bytecode — not UniswapV2 pairs regardless of the event — excluded frompools[]intoexcluded_factories(one is a 4,069-pool launchpad).Sweep is resumable (checkpoint:
next_block, per-source segments, topic counts) via an endpoint pool that prefers the local node and pages paced public providers for the pruned prefix (local node: logs only from block 62,000,000,eth_getLogs≤ 100,000 blocks; public providers: full history but ≤ 10,000 blocks and a handful of req/s — all measured, seedocs/discovery.md). No range is ever skipped.config/pools.testnet.jsonregenerated from a live run over the local node full servable window (62,300,000–62,413,526): 229 pools (129 v2, 83 v3, 17 curve; 4,074PairCreatedpools correctly excluded),reserves_nonzero_at_blockfrom a final Multicall3 pass.config/tokens.testnet.jsonfollows (215 addresses). This is still a sample window, not full history — WP 7902 (full genesis sweep, running now on LXC 140) lands thescanned_from=0file in the next PR.docs/architecture.mdupdated in this PR (the one exception its own change-control rule allows) — §2.1 envelope/fields, §2.2 v3/curve verified, §7 fee_bps and v3/Curve-exists rows corrected. Conflict-resolved against revenue-director's and security-director's facts that landed onmainmeanwhile; both preserved.Tests:
bot/tests/test_discover_pools.py, 26 new cases — real recorded-log decoding for every event family, v2 fee math against a reference value + a 120-swap real pair, every provider error class seen during grounding, kill/resume idempotency.🤖 Generated with Claude Code
Two corrections to the previous commit, both found before merge: 1. --rpc previously defaulted to the three public testnet endpoints, so a bare 'sweep --from 0 --to head' (the exact WP 7902 full-sweep invocation) would quietly page the public RPC for the entire 0-62,000,000 prefix -- directly contradicting the brief ('the public RPC is rate-limited and must not be used for the sweep'). --rpc now has no default; the sweep is local-node-only unless a public endpoint is passed explicitly, and logs plainly when that leaves a prune-boundary gap unscanned. A regression test pins the no-default behavior. docs/discovery.md §8 documents the rationale and the two narrower cases --rpc remains useful for (a bounded dev/sample run below the prune boundary; the enrichment pass's getCode-based creation-block lookup, which is O(dozens) of calls per pool, not a log sweep). 2. Replacing config/pools.testnet.json with the 229-pool sample broke revenue-director's pinned bot/tests/fixtures/cycles/testnet_registry_usdc.json (Tier A CI is require-all, so this blocked merge regardless of which lane caused it) -- reverted config/pools.testnet.json to its committed state and dropped config/tokens.testnet.json from this PR. The full registry replacement + a coordinated fixture regeneration lands together in the WP 7902 PR. docs/discovery.md §9 records the sample run's real numbers as evidence without committing the file here. make test: 217/217 (was 213/216 before this fix -- 3 cycles.py failures caused by point 2). Co-Authored-By: Claude Fable 5.1 <[email protected]> Signed-off-by: BuddySan <[email protected]>Fix-forward pushed (no rebase): (1)
--rpcno longer defaults to the public endpoints — the WP 7902 full sweep brief says the public RPC must not be used for the sweep, and my earlier default silently violated that for any baresweep --from 0 --to headrun; now local-node-only unless--rpcis passed explicitly, with a regression test pinning it. (2) Revertedconfig/pools.testnet.jsonto its committed state and droppedconfig/tokens.testnet.jsonfrom this PR — replacing the registry here brokebot/tests/test_cycles.py's pinned fixture (outside my file set), which is a real cross-lane regression on a Tier A require-all repo. The 229-pool sample-run evidence is recorded indocs/discovery.md§9 instead; the actual registry replacement + a coordinated fixture regen lands in the WP 7902 PR.make test: 217/217 green now (was 213/216).Found and fixed the real cause of the python-tests failure (not a flake): my own test passed
/dev/nullas a throwaway checkpoint path, andsave_checkpoint()legitimatelyos.replace()s onto it — works by luck on some filesystems, raisesOSError: [Errno 16] Device or resource busyon a real one. Reproduced on LXC 140's Python 3.12.3 (did not reproduce in my dev sandbox's 3.13.5 — good reminder to verify on the fleet's pinned version, not just locally). Fixed with a real tempfile path; verified 218/218 on both. The forge-tests failure on the same run looks unrelated to this lane (nocontracts/files touched) — will keep an eye on it but not touching that code.automerger v2 auto-approved: all 7 gates pass. Approver: fortiblox-dev (opposite-identity rule). Gates: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker.
Auto-merged by forgejo-automerger at 2026-09-16 16:02:01 UTC. Approver:
fortiblox-dev(opposite-identity rule, Option C upgrade 2026-05-13). Merger:buddysanviafast-forward-only(NOT adminforce_merge). Criteria passed:mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker. Branch1f3882bcb5merged ontomainand feature branch deleted. Seeproject_forgejo_automergermemory for rationale.