Repository navigation
Random balance-helper addresses amplify upstream RPC reads on Anvil forks #1334
Description
Describe the bug
Rundler's balance helper uses a fresh random address for every get_balances call. When Rundler points to a local Anvil fork, applying the helper's code override requires loading that address's original account state. Each new address causes another uncached lookup against the fork's upstream RPC.
In a local Base fork, this contributed to repeated upstream rate-limit errors during chain synchronization and prevented us from verifying user-operation settlement. A 90-second log sample contained 1,324 account/rate-limit failures mentioning 1,237 distinct addresses. These are error-log counts, not a count of underlying upstream RPC requests.
Rundler was connected to local Anvil through a local HTTP proxy. The request path was:
Rundler -> local proxy -> local Base Anvil -> upstream Base RPC for uncached fork state
To reproduce
The following describes the environment where this was observed; a standalone reproduction has not yet been reduced:
- Run Base Anvil as a fork at a fixed Base block, with local block production enabled (2-second block time in this run).
- Point Rundler v0.11.0 at that local node and exercise chain tracking with watched account balances.
- Observe
get_balancescalls duringload_block_summary, especially while chain tracking is catching up. - With an upstream RPC that rate-limits this traffic, observe errors for continually changing helper addresses and repeated chain-sync failures. Successfully loading one address does not warm the next randomly selected address.
The rate-limit threshold is provider-dependent. The fresh-account reads are the underlying amplification concern even when a provider has enough capacity to serve them.
Expected behavior
Repeated balance reads on a local fork should not continually introduce new upstream account lookups solely for disposable helper contracts. Reads of actual uncached chain state remain expected for a fork.
Logs
Sanitized error observed during the run:
-32603: failed to get account for <random helper address>:
server returned an error response:
error code -32097: Rate limit reached
The associated tracing spans included:
rundler_provider::alloy::evm::get_balances
rundler_pool::chain::load_block_summary
load_block_summaries
sync_to_block
Runtime evidence above is from September 7, 2026. The original containers are no longer available for a fresh measurement.
Additional context
- Rundler: v0.11.0, image digest
sha256:ffdc5fca2d5566152af6fe96f88c50a4cf22ce88852bb626c591d3e8ea426178. - Base Anvil:
ghcr.io/base/base-anvil:main@sha256:68efb5875e8f7c1239b1da3abdec13032a1000970fd1ddb1617efe6d7c16b1e3. The image manifest identifies Base Anvil revision9df661bc39c6fb96ef28bfd5ff5d345931f133d3, usingalloy-evm0.38.0. - Source inspection on September 8, 2026: Rundler's
crates/provider/src/alloy/evm.rsis byte-identical between v0.11.0 and main revisionf926dd52eeae2a07923b6b2bc5fe1eff2097e2a9.
Relevant implementation:
get_balancesin Rundler createsAddress::random()and supplies a code-onlyAccountOverridebefore callingGetBalances.get_gas_usedandget_code_hashuse the same random-address pattern; the runtime evidence here is specifically fromget_balances.- Rundler chain tracking loads block summaries concurrently, with a maximum concurrency of 64. Balance-read failures propagate into chain-sync retries, which can amplify the traffic.
- Base Anvil's call implementation applies the overrides through Alloy's
apply_state_overrides. apply_account_overridein alloy-evm 0.38.0 unconditionally callsdb.basic(account)before applying the supplied fields. Supplying additional override fields alone would therefore not avoid that initial read in this implementation.
This reports an interaction between Rundler's disposable addresses and the fork backend's override handling. No helper-address reuse patch or other proposed fix has been tested.
Activity
github-actions commentedon Oct 9, 2026
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.