Skip to content

feat(generator): support fuzzing max_priority_fee_per_gas#580

Open
op-will wants to merge 1 commit intoflashbots:mainfrom
op-will:addPriorityFeeFuzzing
Open

feat(generator): support fuzzing max_priority_fee_per_gas#580
op-will wants to merge 1 commit intoflashbots:mainfrom
op-will:addPriorityFeeFuzzing

Conversation

@op-will
Copy link
Copy Markdown

@op-will op-will commented May 9, 2026

Motivation

The generator currently lets you fuzz function-call arguments and the tx
value, but there is no way to set or fuzz max_priority_fee_per_gas per
tx — every tx falls back to the global gas_price / 10 default.

Solution

  • FunctionCallDefinition::max_priority_fee_per_gas: Option<String> — new
    field on the user-facing scenario definition, plumbed through
    FunctionCallDefinitionStrict and the templater so it lands on the
    TransactionRequest.
  • FuzzParam::max_priority_fee_per_gas: Option<bool> — a flag that mirrors
    the existing FuzzParam::value flag, opting the priority-fee field into
    fuzzing for that entry. Mutually exclusive with param and value; the
    conflict is caught at scenario load time in parse_map_key.
  • TestScenario now honors a per-tx priority fee if one is set
    (statically or via the fuzz path), falling back to the existing
    gas_price / 10 default otherwise.
  • complete_tx_request raises max_fee_per_gas to match
    max_priority_fee_per_gas when the priority fee exceeds the sampled
    cap, preserving the max_fee_per_gas >= max_priority_fee_per_gas
    invariant. Without this, a high fuzzed tip on a low-fee chain would
    produce an invalid tx.

Example

[spam.tx]
to = "{SpamMe2}"
from_pool = "redpool"
signature = "consumeGas(uint256 gasAmount)"
args = ["3000000"]
fuzz = [
    { param = "gasAmount", min = "1000000", max = "3000000" },
    { max_priority_fee_per_gas = true, min = "0x2540be400", max = "0x4a817c800" },
]

Or pin a static priority fee:

max_priority_fee_per_gas = "10000000000"  # 10 gwei

See docs/creating_scenarios.md for the full documentation.

Breaking changes

Minor breaking change for downstream library users that construct
FuzzParam or FunctionCallDefinitionStrict via struct literal:

  • FuzzParam gains a max_priority_fee_per_gas: Option<bool> field.
  • FunctionCallDefinitionStrict gains a
    max_priority_fee_per_gas: Option<String> field.

FunctionCallDefinition is unaffected for builder-style users
(FunctionCallDefinition::new(..).with_*(..)); the new field has a
default in the builder constructor.

Tests

  • function_def.rs: parses static max_priority_fee_per_gas, parses the
    fuzz flag, and confirms the param+max_priority_fee_per_gas
    combination parses (so the runtime check in parse_map_key has a
    chance to run).
  • trait.rs: parse_map_key routes param/value/max_priority_fee_per_gas
    to the correct fuzz-map keys and rejects every conflicting combination.
  • util.rs: complete_tx_request uses gas_price when the priority
    fee is lower, raises max_fee_per_gas when it's higher, handles the
    equal case, and the Eip4844 path inherits the same invariant.

PR Checklist

  • Added Tests
  • Added Documentation (docs/creating_scenarios.md)
  • Ran cargo +nightly clippy --workspace --lib --examples --tests --benches --all-features --locked (-D warnings clean)
  • Ran cargo +nightly fmt --all
  • Note breaking changes in PR description, if applicable — see "Breaking changes" above
  • update changelogs
    • crates/core/CHANGELOG.md updated under ## [0.11.0] (matching the version already in Cargo.toml)
    • root CHANGELOG.md — skipped per the note at the top of that file ("contender is now versioned by crate. This file will no longer be updated.")

Adds a per-tx EIP-1559 priority fee that can be set statically or
fuzzed via the existing fuzz mechanism:

- new field FunctionCallDefinition::max_priority_fee_per_gas (Option<String>,
  may be a {placeholder}); plumbed through FunctionCallDefinitionStrict and
  the templater
- new FuzzParam::max_priority_fee_per_gas (Option<bool>), mirroring the
  existing FuzzParam::value flag; mutually exclusive with `param` and
  `value`, with the conflict caught at scenario load time in parse_map_key
- complete_tx_request now raises max_fee_per_gas to match the priority fee
  when the priority fee exceeds the sampled cap, preserving the EIP-1559
  invariant
- docs/creating_scenarios.md documents both the static and fuzzed forms
- crates/core/CHANGELOG.md updated under [0.11.0]
@op-will op-will force-pushed the addPriorityFeeFuzzing branch from c4aa6b6 to ce92122 Compare May 9, 2026 14:36
@op-will op-will marked this pull request as ready for review May 9, 2026 14:41
@op-will op-will requested a review from zeroXbrock as a code owner May 9, 2026 14:41
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