fix(core): cap estimate_gas ceiling at EIP-7825 per-tx gas limit#3
Draft
op-will wants to merge 5 commits into
Draft
fix(core): cap estimate_gas ceiling at EIP-7825 per-tx gas limit#3op-will wants to merge 5 commits into
op-will wants to merge 5 commits into
Conversation
…ts#588) * feat: add scenario access_list with placeholder resolution Supersedes flashbots#581. Adds an `access_list` field to FunctionCallDefinition that accepts {placeholder} strings in `address` and `storageKeys`, resolved during the loose-to-strict conversion via the existing templater + DB map. Coexists with max_priority_fee_per_gas (flashbots#580) and alloy 2.0 (flashbots#561). * support scenario [env] placeholders in access list fields * chore: clippy --------- Co-authored-by: zeroXbrock <2791467+zeroXbrock@users.noreply.github.com>
…shbots#589) * feat: add spam-stream subcommand for streaming tx specs (draft) Reads newline-delimited JSON FunctionCallDefinitions from stdin or a file and spams them via the existing TestScenario pipeline. Reuses agent pools, rate limiting, nonce management, and receipt tracking. See docs/stream-mode.md for the design note and scope. * feat(spam-stream): versioned stdout envelope + drop decoy TestConfig - Address review feedback on PR flashbots#589: - #2/#3: emit structured, versioned/tagged JSON envelope on stdout (one tx_result event per spec) so the schema can evolve; default for spam-stream mode (logs stay on stderr). - flashbots#5: replace the decoy zero-address TestConfig with a direct AgentStore pool, injecting signers into the scenario and syncing nonces from the RPC. * fix(spam-stream): record run, cache gas price, surface backpressure/summary Address review gaps on the prototype: - record a real run via insert_run so dumped receipts aren't orphaned under run_id 0 (run_txs has a foreign key into runs) - cache the gas price, refreshing every 6s instead of once per tx - emit `backpressure` and a terminal `summary` event; track sent vs failed - reject blob (4844) / setCode (7702) specs up front - unify the stdin/file reader and drop dead run_id plumbing * fix(spam-stream): enable nonce sync so sends don't fail with NonceMissing TestScenario::sync_nonces() is gated on should_sync_nonces (= the sync_nonces_after_batch param). spam-stream set it false, making its two explicit sync_nonces() calls silent no-ops, so pool accounts' nonces were never loaded and prepare_tx_request failed every send with NonceMissing (surfaced as 'core error'). Stream mode sends one tx at a time and never hits the post-batch sync path, so enabling this only makes the initial pool-nonce sync run. * fix(spam-stream): reclaim nonce on failed send to avoid nonce gaps prepare_tx_request advances an account's local nonce before the send. When the send is rejected (e.g. an interop access-list filter rejecting a not-yet-valid or forged executing message), the tx never enters the mempool but the local nonce stays advanced, leaving a gap that stalls every later tx from that account behind it. Roll the nonce back by one on a failed send. The stream sends serially, so no concurrent send touched the account in between. * docs(spam-stream): clarify --tps long_help (review flashbots#589) --tps paces how fast specs are pulled off the input stream; each spec is sent exactly once, so a one-line input sends a single tx regardless of the value. Add long_help explaining this, plus tests asserting the help text is present and the clap arg config is valid (debug_assert). * feat(spam-stream): accept unit strings for --min-balance (review flashbots#589) --min-balance now parses unit-value strings ("10 eth", "0.5 ether", "100 gwei") via util::parse_value, matching the other CLI balance/value flags; a plain number is still wei. Default expressed as "0.01 ether" (unchanged 1e16 wei). Tests cover unit parsing, the wei fallback, and the default round-trip through the value_parser. * fix(spam-stream): persist seed so --skip-funding works across runs (review flashbots#589) When --seed was unset, spam-stream generated a fresh random RandSeed each invocation, so the executor pool's addresses differed every run. Funding the pool with --min-balance in one run then re-running with --skip-funding hit "insufficient funds" because the second run derived a different (unfunded) pool. Fall back to the persisted seedfile (data_dir/seed) when --seed is unset, matching spam/setup/campaign. Threads data_dir into spam_stream(). Pool addresses are now stable across invocations for a given data-dir. Test: build_pool_agent_store is deterministic per seed (same seed -> same addresses, different seed -> different). Manually verified against anvil: run 1 funds the pool + writes the seedfile; run 2 with --skip-funding and no funder key sends successfully (previously failed with insufficient funds). * style(spam-stream): cargo fmt test module (CI fmt fix) --------- Co-authored-by: brock 🤖⚡ <2791467+zeroXbrock@users.noreply.github.com>
* chore: update changelogs * chore: bump versions
On a chain that enforces EIP-7825 (Osaka), eth_estimateGas binary-searches using the block gas limit as its upper bound. When that limit exceeds the 2^24 per-tx cap, the first simulated execution is itself invalid and the node returns "intrinsic gas too high" instead of an estimate, so the call fails before any tx is sent. This aborts contract deployment during setup. Clamp the gas ceiling on the estimate request to 2^24 at the three estimate_gas sites (contract deploy, setup tx, spam tx). The returned estimate is the true gas the tx needs, so this never inflates the final gas limit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a chain that has activated EIP-7825 (the Osaka per-transaction gas-limit cap of
2^24= 16,777,216 gas),contender setupaborts during contract deployment with:Root cause
In
crates/core/src/test_scenario.rs, the contract-deploy path builds a creation tx with nogasfield and callsprovider.estimate_gas(...). On an EIP-7825 chain,eth_estimateGasbinary-searches using the block gas limit as its upper bound. Because that ceiling exceeds2^24, the first simulated execution is itself invalid, and the node returnsintrinsic gas too highinstead of an estimate — so the call fails before any transaction is ever sent.The anvil-based
simulate_setup_costpass succeeds because anvil does not enforce EIP-7825, which masks the problem until the real deploy.The same unbounded
estimate_gaspattern exists at three sites: contract deploy, setup txs, andupdate_gas_map(spam txs).Fix
Add a constant
EIP_7825_MAX_TX_GAS_LIMIT = 1 << 24and a helpercap_gas_for_estimate()that clamps a tx request'sgasceiling to the cap beforeestimate_gasis called, applied at all three sites.This keeps the node's binary search inside the valid range. The returned estimate is the true (smaller) gas the tx needs, so the final gas limit is never inflated — on chains without EIP-7825 the behavior is unchanged (the estimate already returns the real value well below
2^24).Verification
cargo build --release— succeedscargo +nightly fmt --check— cleancargo clippy -p contender_core— cleancontender setupnow deploys the contract and completes; the exact step that previously aborted withintrinsic gas too highsucceeds.