Skip to content

fix(load-tests): Base fee reservation and funder affordability - #4294

Draft
meyer9 wants to merge 5 commits into
feat/load-tests-cumulative-gps-pacingfrom
feat/load-tests-base-fee-affordability
Draft

fix(load-tests): Base fee reservation and funder affordability#4294
meyer9 wants to merge 5 commits into
feat/load-tests-cumulative-gps-pacingfrom
feat/load-tests-base-fee-affordability

Conversation

@meyer9

@meyer9 meyer9 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Enforce funder max-cost affordability before funding
  • Reserve Base transaction fees correctly (without unrelated L1 fee reserve)
  • Add builder coverage for preloaded sender nonce chains

Stack

PR 4/5. Base: feat/load-tests-cumulative-gps-pacing (#4293).

  1. feat(load-tests): open-loop generation, adaptive pacing, and B20 #4291 — open-loop core
  2. fix(load-tests): funding and nonce robustness #4292 — funding/nonce robustness
  3. feat(load-tests): pace capped runs by cumulative gas #4293 — cumulative GPS pacing
  4. fix(load-tests): Base fee reservation and funder affordability #4294 — Base fee / funder affordability ← you are here
  5. fix(load-tests): harden open-loop runtime and configuration #4295 — runtime hardening

Test plan

  • cargo test -p base-load-tests --lib
  • Builder nonce-chain coverage in base-builder-core
  • Funding fails cleanly when funder cannot cover max cost

Comment thread crates/infra/load-tests/src/runner/load_runner.rs Outdated
@meyer9
meyer9 marked this pull request as draft August 5, 2026 16:28
@meyer9
meyer9 force-pushed the feat/load-tests-cumulative-gps-pacing branch from ab1fb97 to f2aff2e Compare August 5, 2026 16:34
@meyer9
meyer9 force-pushed the feat/load-tests-base-fee-affordability branch from 910614b to ed15a94 Compare August 5, 2026 16:34
@meyer9
meyer9 force-pushed the feat/load-tests-cumulative-gps-pacing branch from f2aff2e to caacca2 Compare August 5, 2026 16:36
@meyer9
meyer9 force-pushed the feat/load-tests-base-fee-affordability branch from ed15a94 to 0a90d26 Compare August 5, 2026 16:36
Comment thread crates/infra/load-tests/src/runner/load_runner.rs Outdated
@meyer9
meyer9 force-pushed the feat/load-tests-cumulative-gps-pacing branch from caacca2 to 3eb0330 Compare August 5, 2026 17:28
@meyer9
meyer9 force-pushed the feat/load-tests-base-fee-affordability branch from 0a90d26 to 5628939 Compare August 5, 2026 17:28
Comment on lines +947 to +948
queued_funder_transactions =
queued_funder_transactions.saturating_add(queued_nonces.len());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queued_funder_transactions is accumulated with saturating_add(queued_nonces.len()) across every txpool endpoint. If multiple nodes gossip the same queued transactions, the same nonces are counted multiple times, which could inflate the total above zero even when a single node's queued set was successfully drained by the earlier drop_sender_transactions call.

Consider deduplicating nonces (e.g. collect into a HashSet) or taking the max across endpoints rather than the sum, similar to what highest_txpool_nonce already does.

@meyer9
meyer9 force-pushed the feat/load-tests-cumulative-gps-pacing branch from 3eb0330 to 99616c5 Compare August 5, 2026 18:23
@meyer9
meyer9 force-pushed the feat/load-tests-base-fee-affordability branch from 5628939 to 0ab49e4 Compare August 5, 2026 18:23
…fordability

Co-authored-by: Cursor <cursoragent@cursor.com>
.saturating_mul(MAX_FEE_BASE_FEE_MULTIPLIER)
.max(base_fee.saturating_add(priority_fee));
target.min(max_gas_price).max(priority_fee)
target.min(max_gas_price)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the .max(priority_fee) floor means submission_max_fee can now return a value less than priority_fee. This produces an invalid EIP-1559 transaction (maxFeePerGas < maxPriorityFeePerGas).

The call sites touched by this PR correctly pre-clamp priority_fee with .min(max_gas_price), but at least two existing callers do not:

  • load_runner.rs:262 (calibration path)
  • pacing.rs:1172 (batch signing path)

With the new default max_gas_price of 0.01 gwei, if base_fee exceeds 0.1 gwei then priority_fee = base_fee/10 will exceed max_gas_price, and these call sites will build transactions with maxPriorityFeePerGas > maxFeePerGas.

Either add the .min(max_gas_price) clamp to all remaining callers, or keep the .max(priority_fee) floor here as a safety net.

Comment on lines +138 to +139
queued_funder_transactions =
queued_funder_transactions.saturating_add(queued_nonces.len());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queued_funder_transactions is summed across all txpool endpoints with saturating_add. If multiple nodes gossip the same queued transactions, identical nonces are double-counted.

This matters because the check at line 153 hard-errors when the total exceeds zero. A single queued transaction visible on two nodes would report a count of 2 even if drop_sender_transactions successfully cleared one of them — the second node may just not have propagated the removal yet.

Consider deduplicating nonces (e.g. collect into a HashSet<u64>) or taking the max count across endpoints rather than the sum, similar to the highest_txpool_nonce logic.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Summary

Changes reviewed: Enforce funder max-cost affordability, clamp priority_fee to max_gas_price, separate pending/queued txpool nonces, add builder nonce-chain test.

Findings

1. submission_max_fee floor removal creates invalid EIP-1559 txs at unclamped call sites (correctness)
submission.rs:515 — The .max(priority_fee) floor was removed from submission_max_fee, but two existing callers (load_runner.rs:262, pacing.rs:1172) do not pre-clamp priority_fee with .min(max_gas_price). With the new 0.01 gwei default cap, any base_fee > 0.1 gwei will produce maxPriorityFeePerGas > maxFeePerGas, which is an invalid EIP-1559 transaction.

2. Queued funder transaction count inflated by multi-node double-counting (correctness)
funding.rs:138-139queued_funder_transactions is summed across all txpool endpoints. If the same queued nonce is visible on multiple nodes (normal gossip), the count inflates and the hard-error at line 153 may fire spuriously. Should deduplicate nonces or take max per-endpoint, consistent with how highest_txpool_nonce works.

Other notes

  • The sender_transaction_nonces refactor to return (pending, queued) tuple is clean.
  • The builder test (test_preloaded_nonce_chain_available_after_pruning_head) is well-structured and covers a meaningful scenario.
  • Import hoisting in best_txs.rs test module follows project conventions correctly.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Base Std historical fork tests

Fork Result Passed Failed Skipped base/base base-anvil base-std
Beryl pass 616 0 13 a9918116 6d744e03 4658f1b7
Cobalt pass 709 0 14 a9918116 ae7557c4 8f88bf3e

View run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant