feat(bot): registry loader, registry_hash and token metadata cache #11

Merged
buddysan merged 3 commits from data/registry into main 2026-09-16 14:29:37 +00:00
Owner

Registry loader (data lane, WP 7899 / 7901)

bot/registry.py per docs/architecture.md §2.1 / §2.3:

  • total validation (duplicate pair, non-lowercase addresses, unknown kind, missing per-kind fields, v2/v3 token ordering, kind vs factory kind, per-pool fee_bps vs factories[]), every defect reported at once;
  • registry_hash = sha256(canonical pools[], sorted keys, no whitespace)[:16]; a stored hash that no longer matches pools[] is refused (hand-edit guard);
  • TokenCacheconfig/tokens.<net>.json via Multicall3 aggregate3 (allowFailure), keyed by address (symbols collide on testnet);
  • CLI validate | hash | tokens.

Tests: bot/tests/test_registry.py (24 cases, offline) with fixtures recorded from the LXC 140 node (block in filename). Finding baked into a test: Multicall3 sub-call to 0x…01 (ecrecover precompile) reports success=true with empty data — the reserves pass must key on the 96-byte return shape, not the success flag.

Envelope additions this loader understands (chain_id, factories, reserves_checked_at_block, sources, registry_hash, per-pool reserves_nonzero_at_block) are documented in §2.1 by the discovery-extension PR that follows (same-PR rule). The committed config/pools.testnet.json does not yet conform (no fee_bps); the sweep PR lands the conforming file plus a test that loads it.

🤖 Generated with Claude Code

## Registry loader (data lane, WP 7899 / 7901) `bot/registry.py` per `docs/architecture.md` §2.1 / §2.3: - total validation (duplicate `pair`, non-lowercase addresses, unknown `kind`, missing per-kind fields, v2/v3 token ordering, kind vs factory kind, per-pool `fee_bps` vs `factories[]`), every defect reported at once; - `registry_hash` = sha256(canonical `pools[]`, sorted keys, no whitespace)[:16]; a stored hash that no longer matches `pools[]` is refused (hand-edit guard); - `TokenCache` → `config/tokens.<net>.json` via Multicall3 `aggregate3` (allowFailure), keyed by address (symbols collide on testnet); - CLI `validate | hash | tokens`. Tests: `bot/tests/test_registry.py` (24 cases, offline) with fixtures recorded from the LXC 140 node (block in filename). Finding baked into a test: Multicall3 sub-call to `0x…01` (ecrecover precompile) reports `success=true` with empty data — the reserves pass must key on the 96-byte return shape, not the success flag. Envelope additions this loader understands (`chain_id`, `factories`, `reserves_checked_at_block`, `sources`, `registry_hash`, per-pool `reserves_nonzero_at_block`) are documented in §2.1 by the discovery-extension PR that follows (same-PR rule). The committed `config/pools.testnet.json` does not yet conform (no `fee_bps`); the sweep PR lands the conforming file plus a test that loads it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(bot): registry loader, registry_hash and token metadata cache (§2.1/§2.3)
All checks were successful
ci / forge-tests (pull_request) Successful in 1s
ci / python-tests (pull_request) Successful in 9s
28fb6451d1
bot/registry.py loads config/pools.<net>.json and validates it in full:
duplicate pair, non-lowercase address, unknown kind, missing per-kind
fields (v2 fee_bps / v3 fee+tick_spacing / curve pool_type+coins+A),
token ordering, pool kind vs factory kind, per-pool fee_bps vs the
factories section, and an unverified (null) v2 fee tolerated only on
pools with no reserves. registry_hash = sha256(canonical pools[] JSON)
[:16] exactly as §2.3; a stored hash that no longer matches pools[] is
refused so hand edits cannot reach search.py unnoticed.

TokenCache fills config/tokens.<net>.json through Multicall3 aggregate3
(allowFailure) — keyed by address only, because three testnet tokens
report symbol()=="ARC_TEST". Hand-rolled aggregate3 encoder/decoder is
round-tripped against a call recorded from the LXC 140 node (fixture
block in filename). Precompile finding baked into the tests: a
sub-call to 0x…01 reports success with empty data, so consumers must
key on return shape, not the success flag.

The committed config/pools.testnet.json does not yet carry fee_bps /
factories — the discovery-extension and sweep PRs that follow land the
conforming file and a test that loads it.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: BuddySan <[email protected]>
Merge branch 'main' into data/registry
All checks were successful
ci / forge-tests (pull_request) Successful in 2s
ci / python-tests (pull_request) Successful in 6s
3a7e4ce911
fortiblox-dev approved these changes 2026-09-16 14:06:28 +00:00
Dismissed
fortiblox-dev left a comment

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.

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.
buddysan force-pushed data/registry from 3a7e4ce911
All checks were successful
ci / forge-tests (pull_request) Successful in 2s
ci / python-tests (pull_request) Successful in 6s
to 466122ac89
All checks were successful
ci / forge-tests (pull_request) Successful in 2s
ci / python-tests (pull_request) Successful in 6s
2026-09-16 14:10:57 +00:00
Compare
fortiblox-dev approved these changes 2026-09-16 14:14:28 +00:00
Dismissed
fortiblox-dev left a comment

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.

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.
Merge branch 'main' into data/registry
All checks were successful
ci / forge-tests (pull_request) Successful in 2s
ci / python-tests (pull_request) Successful in 6s
6da1ef3802
fortiblox-dev approved these changes 2026-09-16 14:21:55 +00:00
Dismissed
fortiblox-dev left a comment

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.

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.
Merge branch 'main' into data/registry
All checks were successful
ci / forge-tests (pull_request) Successful in 4s
ci / python-tests (pull_request) Successful in 35s
ci / forge-tests (push) Successful in 4s
ci / python-tests (push) Successful in 36s
19019fee14
fortiblox-dev left a comment

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.

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.
buddysan deleted branch data/registry 2026-09-16 14:29:37 +00:00
Author
Owner

Auto-merged by forgejo-automerger at 2026-09-16 14:29:37 UTC. Approver: fortiblox-dev (opposite-identity rule, Option C upgrade 2026-05-13). Merger: buddysan via fast-forward-only (NOT admin force_merge). Criteria passed: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker. Branch 19019fee14 merged onto main and feature branch deleted. See project_forgejo_automerger memory for rationale.

Auto-merged by **forgejo-automerger** at 2026-09-16 14:29:37 UTC. **Approver:** `fortiblox-dev` (opposite-identity rule, Option C upgrade 2026-05-13). **Merger:** `buddysan` via `fast-forward-only` (NOT admin `force_merge`). **Criteria passed:** `mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker`. Branch `19019fee14` merged onto `main` and feature branch deleted. See `project_forgejo_automerger` memory for rationale.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
fortiblox/arc-mev-bot!11
No description provided.