Batch chain-timer eth_calls via Multicall3 (#307) #488
No reviewers
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega!488
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-307-multicall-chain-timer"
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?
Summary
Implements GitLab #307: collapse the chain-timer
poll_oncefan-out (~30 sequentialeth_calls per ~1 Hz cycle) into one Multicall3aggregate3round-trip at a singleread_block_number, with duplicate-call coalescing and a sequential fallback when Multicall3 bytecode is absent.indexer/src/multicall.rs—aggregate3encode/decode, batch chunking, coalesce helperchain_timer::poll_once— Multicall3 primary path;poll_once_sequentialfallbacksale_state—sale_state_from_fieldsfor batched decode (no extra RPC for deadline)scripts/lib/anvil_multicall3.sh+ bytecode at canonical0xcA11…(wired into verify/benchmark scripts)docs/indexer/benchmarks/rpc-benchmark-20260614T053127Z.json— idlepeak_calls_10s44 (was 354)Related: parent #306 · MR !454 baseline
Acceptance checklist
poll_onceuses Multicall3 for majority of chain-timereth_callsmulticall.rs+chain_timer.rspeak_calls_10s≤ 50 (120s benchmark)BENCHMARK_SCENARIO_SEC=120 bash scripts/benchmark-indexer-rpc-anvil.shpeak_calls_10s=44by_caller.chain_timereth_call≥40% reduction vs baselinerpc-benchmark-20260610T111415Z.jsoneth_call:chain_timer/ 10s burst vs 352 (~97% reduction)GET /v1/arena/timersfreshness ≤3s (idle Anvil)read_block_numbertracks headpolled_at_msinternal only)INV-INDEXER-306-NO-REGRESSIONbash scripts/verify-podium-live-anvil.shintegration_stage2flakesarena_wallet_stats_two_epochs_and_bonus_fieldsin harness only (standalonecargo testPASS)cd indexer && cargo clippy --all-targets -- -D warnings && cargo testbash scripts/verify-indexer-rpc-metrics.shpeak_calls_10s=44docs/indexer/rpc-load-benchmark.md,invariants §307allowFailure: falseVerification for third parties
Operator note: production chains need Multicall3 at
0xcA11bde05977b3631167028862bE2a173976CA11(standard). Fresh Anvil installs it viascripts/lib/anvil_multicall3.sh.Blockers
verify-podium-live-anvil.shharness flake onarena_wallet_stats_two_epochs_and_bonus_fields(pre-existing; unrelated to multicall)Follow-ups
arena_wallet_stats_two_epochs_and_bonus_fieldsordering flake in verify harnesschanged the description
changed the description
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit
ac2b9b2871. Configure here.Failed batch never disables multicall
Medium Severity
When
poll_once_multicallfails,poll_oncelogs and falls back to sequential calls but leaves Multicall3 marked available. Each subsequent poll retries the failingaggregate3before running the full sequential fan-out, adding an extraeth_callevery cycle while Multicall3 bytecode is broken or incompatible.Reviewed by Cursor Bugbot for commit
ac2b9b2871. Configure here.Probe errors disable multicall permanently
Medium Severity
In
probe_multicall3, a failedget_code_atRPC (timeout, 5xx, or all endpoints down) is treated the same as confirmed absent bytecode:MULTICALL_MODEis set toMC_UNAVAILABLEfor the rest of the process. Later polls skip Multicall3 entirely viamulticall_batching_enabled, even after RPC recovers on chains where Multicall3 is deployed.Reviewed by Cursor Bugbot for commit
ac2b9b2871. Configure here.Security review — MR !488
Commit reviewed:
ac2b9b2871f3d57d581e2a52a946aacbdea30a2eScope: Multicall3
aggregate3batching for chain-timer head reads (indexer/src/multicall.rs,chain_timer.rs,sale_state.rs), Anvil Multicall3 bootstrap (scripts/lib/anvil_multicall3.sh+ bytecode), verify/benchmark wiring, docs/invariants.Method: Diff review; traced batch inputs (operator-configured
TimeArena/PodiumVaultsaddresses + fixed selectors) throughaggregate3encode/decode toGET /v1/arena/timerssnapshot fields. Compared trust boundaries vs pre-MR sequentialeth_callpath.Outcome: FINDINGS: 0 medium+
Notes (below severity threshold / not introduced exploit paths)
allowFailure: false+ subcallsuccesschecks reject partial/malformed aggregate results; decode errors fail the poll and fall back to sequential reads — no silent field substitution observed.read_block_numberblock tag for the batch improves head consistency vs scattered sequential calls (reduces cross-read TOCTOU), with the same RPC/chain trust model as before.MC_UNAVAILABLEon transientget_code_aterrors and failed batches do not callmark_multicall_unavailable(Bugbot threads) — these are availability/efficiency regressions, not authz bypasses or fund-impact paths; sequential fallback still serves data from the same RPC sources.scripts/lib/anvil_multicall3.shis local-dev only; skips install when bytecode already present (operator/dev trust). Committed bytecode includes standard Multicall3aggregate3selector (0x82ad56cb) and revert stringMulticall3: call failed.RPC_URL+ registry addresses; this MR does not expand attacker-controlled sinks.Inline threads: none (no medium+ findings).
Security review: no medium+ findings on this diff.
changed this line in version 2 of the diff
changed this line in version 2 of the diff
added 100 commits
mainc432cee3- Merge origin/main into issue-307-multicall-chain-timerCompare with previous version
Resolved merge conflicts with
origin/main(merge commitc432cee3).Conflicts resolved (9 files): took main's integrated #307 implementation —
MulticallBatch/aggregate3_at_blockinmulticall.rs,sale_state_from_returns, sharedyieldomega_verify_boot_indexer_stackverify bootstrap, andyieldomega_ensure_anvil_multicall3(signed deploy tx). Dropped branch-onlyMulticallRequestprobe path andanvil_setCodehelper in favor of main.Preserved from branch: benchmark artifact
docs/indexer/benchmarks/rpc-benchmark-20260614T053127Z.json.Sanity:
cargo clippy --all-targets -- -D warningsandcargo testinindexer/— PASS.changed the description
Security review — MR !488
Commit reviewed:
c432cee3fe1b58dcce2f2cc87bad8963aaf0dd44Scope: Post-merge diff vs
main(4 files): benchmark artifacts (docs/indexer/benchmarks/rpc-benchmark-20260614T053127Z.{json,md}),indexer/README.md§307 note,scripts/lib/multicall3_anvil_bytecode.hex. Surrounding #307 paths on this SHA reviewed for exploitability:indexer/src/multicall.rs,chain_timer.rs,sale_state.rs,scripts/lib/anvil_multicall3.sh(merged frommain; branch-onlyMulticallRequestprobe /anvil_setCodepath removed).Method: Diff review; traced batch inputs (operator-configured
TimeArena/PodiumVaults+ fixed selectors) throughaggregate3encode/decode toGET /v1/arena/timerssnapshot fields; verified Anvil bootstrap trust boundaries and committed bytecode surface.Outcome: FINDINGS: 0 medium+
Notes (below severity threshold / not introduced exploit paths)
allowFailure: false+ per-subcallsuccesschecks (multicall.rs) reject partial/malformed aggregate results; decode errors fail the poll andpoll_oncefalls back to sequential reads — no silent field substitution.read_block_numberblock tag for the batch improves head consistency vs scattered sequential calls; same RPC/chain trust model as pre-#307.multicall3_anvil_bytecode.hexis unreferenced in scripts/code; Anvil bootstrap uses the mds1 signed deploy tx inanvil_multicall3.sh. The hex artifact is a minimalaggregate3-only stub (0x82ad56cb, revertMulticall3: call failed) — local-dev operator trust, not a production deploy path.RPC_URL+ registry addresses; this MR does not expand attacker-controlled sinks.Inline threads: none (no medium+ findings).
Security review: no medium+ findings on this diff.
mentioned in commit
bd2d20e94b