76301 bc insight base flashblocks eth simulatev1 pending state expansion enables remote node dos
Submitted on May 3rd 2026 at 18:58:35 UTC by @z41zen for Audit Comp | Base Azul
Report ID: #76301
Report Type: Blockchain/DLT
Report severity: Insight
Target: https://github.com/base/base/tree/v0.8.0-rc.28
Impacts:
Shutdown of greater than or equal to 30% of network processing nodes without brute force actions, but does not shut down the network
Increasing network processing node resource consumption by at least 30% without brute force actions, compared to the preceding 24 hours
Description
Brief/Intro
Base Flashblocks eth_simulateV1 expands the full Flashblocks pending state override into every requested simulated block before delegating to reth. A remote JSON-RPC client can send valid eth_simulateV1 requests using the pending block tag and force the node to clone and materialize the server-side pending state many times.
The request itself can be very small and can remain within reth's accepted max_simulate_blocks = 256 limit. In a controlled five-node fleet, six concurrent valid pending-state simulations against each target node made two independent nodes unreachable. That is 2/5 nodes, or 40% of the measured fleet.
Vulnerability Details
The affected code is in crates/execution/flashblocks/src/rpc/eth.rs.
When eth_simulateV1 is called with the pending block tag, Base reads the current Flashblocks pending state:
Base then prepends that pending state to every requested simulated block:
This creates O(number_of_requested_blocks * pending_state_size) server-side work before reth processes the request.
Reth does enforce a maximum number of simulated blocks:
However, the Base wrapper creates the expanded SimulatePayload before this reth validation is reached. For requests at the limit, such as 256 blocks, reth accepts the request and the node still performs the full pending-state expansion and simulation work.
The method is exposed on Base preconf endpoints. A benign over-limit request confirms that the public endpoints route to reth's eth_simulateV1 limit check:
Heavy measurements were performed only against controlled local targets.
Impact Details
The attacker does not need to send the large state. The expensive data is the server-side Flashblocks pending state, which Base copies into every requested simulated block.
At the maximum accepted block count, the JSON-RPC request body is only about 3.4 KiB:
Controlled five-node fleet measurement:
Observed concurrency threshold:
The 6-concurrent case satisfies the impact class for shutdown of greater than or equal to 30% of network processing nodes in the controlled fleet. I am not claiming total Base network shutdown.
Link to Proof of Concept
https://gist.github.com/s-zaizen/8f982dc21ed74ac3cc473e4f869a4497
Proof of Concept
The PoC is provided as a secret Gist:
https://gist.github.com/s-zaizen/8f982dc21ed74ac3cc473e4f869a4497
To reproduce the lightweight confirmation:
The lightweight PoC confirms that Base materializes pending-state copies before reth's over-limit rejection:
The external-node availability harness used for the 30%+ fleet measurement is included in:
To reproduce the external-node path, use a separate checkout of Base at the target commit:
Single-node availability command:
For the 30%+ impact reproduction, run the same command on five independent nodes and monitor each node externally. The measured critical case used five independent nodes and made two nodes unreachable.
Observed Verification
Observed controlled-fleet output:
Selected node A output from the 6-concurrent case:
Selected node B output from the 6-concurrent case:
Observed single-node threshold output:
Observed local-node over-limit measurement highlights:
References
Base Flashblocks
eth_simulateV1wrapper:crates/execution/flashblocks/src/rpc/eth.rshttps://github.com/base/base/blob/b7f44d73a3e353f3f0024d2fc55b9a48099c79f4/crates/execution/flashblocks/src/rpc/eth.rs
Lightweight pending-state materialization PoC:
main.rsrun_poc.shpayload_size.py
External availability measurement harness:
simulate_v1_external_node.rsmeasure_external_node.pyrun_independent_node.sh
Critical controlled-fleet measurement log:
controlled-fleet-critical-measurement.log
Secret Gist containing the runnable PoC and evidence:
https://gist.github.com/s-zaizen/8f982dc21ed74ac3cc473e4f869a4497
Was this helpful?