Skip to content

Enforce EIP-7825 per-tx gas cap on settlement#4371

Open
0xDevNinja wants to merge 5 commits intocowprotocol:mainfrom
0xDevNinja:fix/eip-7825-driver-gas-cap
Open

Enforce EIP-7825 per-tx gas cap on settlement#4371
0xDevNinja wants to merge 5 commits intocowprotocol:mainfrom
0xDevNinja:fix/eip-7825-driver-gas-cap

Conversation

@0xDevNinja
Copy link
Copy Markdown

@0xDevNinja 0xDevNinja commented Apr 30, 2026

Description

The driver caps a settlement's gas estimate at half the block gas limit (e.g. 60M on a 120M block). Fusaka introduced the EIP-7825 per-transaction gas cap of 2^24 - 1 = 16,777,215 on Mainnet; any tx exceeding this is rejected by the mempool. Without this check a solution above the cap can still be returned by /solve and forwarded to /settle, where it could never be mined. The cap is already enforced on the quote-verification path (#4261) but was never ported to settlement submission.

Note: EIP-7825 is L1 Fusaka-only and other chains pick their own per-tx limits (e.g. Arbitrum One uses 32M), so the driver reuses the existing tx_gas_limit config knob (#3780) rather than hardcoding a single value. Operators set the per-chain ceiling — 16,777,215 on Mainnet Fusaka, higher elsewhere — and Gas::new enforces min(block_limit / 2, tx_gas_limit).

Changes

  • Plumb the tx_gas_limit config value through infra::blockchain::Ethereum (new tx_gas_limit() accessor).
  • In Gas::new, cap the per-settlement maximum at min(block_limit / 2, tx_gas_limit) so over-sized solutions fail fast through the existing GasLimitExceeded error.
  • Chains with a block gas limit below 2 * tx_gas_limit keep the tighter half-block behaviour.
  • Add unit tests covering the configured-cap path, the boundary case (asserting both estimate and the clamped limit), the small-block-limit path, and the non-Fusaka case where the half-block cap binds.

How to test

cargo nextest run -p driver settlement::tests

All four new tests pass; existing driver tests are unchanged.

Fixes #4368

@0xDevNinja 0xDevNinja requested a review from a team as a code owner April 30, 2026 14:02
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@0xDevNinja
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@0xDevNinja
Copy link
Copy Markdown
Author

recheck

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements the EIP-7825 per-transaction gas cap (2^24 - 1) within the settlement domain. The Gas::new function now caps the maximum gas by taking the minimum of half the block limit and this new constant, preventing the creation of solutions that would be rejected by the mempool. Unit tests have been added to verify the cap's behavior in both large and small block limit scenarios. I have no feedback to provide.

github-actions Bot added a commit that referenced this pull request Apr 30, 2026
Copy link
Copy Markdown
Member

@AryanGodara AryanGodara left a comment

Choose a reason for hiding this comment

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

I think the PR is good to merge, just left some small follow-up questions


#[test]
fn rejects_solution_above_eip_7825_cap() {
// 120M block (well above the EIP-7825 cap of 16,777,215). Half the
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: can we rewrite this comment, so it reads more clearly.
it can be structured a little bit better 😅

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reworded in 2e4268b.

Comment thread crates/driver/src/domain/competition/solution/settlement.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/settlement.rs
0xDevNinja added 2 commits May 4, 2026 19:26
- Make EIP_7825_TX_GAS_CAP private; no external callers.
- Reword test comment for clarity.
Replace the hardcoded EIP-7825 constant in Gas::new with the existing
per-driver tx_gas_limit config knob. Operators set the cap per chain
(EIP-7825's 16,777,215 on Fusaka chains, higher elsewhere) so non-Fusaka
chains aren't over-restricted by an L1-only fork rule.
Comment thread crates/driver/src/domain/competition/solution/settlement.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/settlement.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/settlement.rs Outdated
Comment thread crates/driver/src/domain/competition/solution/settlement.rs Outdated
EIP-7825 chose 2^24-1 for Mainnet's Fusaka hardfork; other chains pick
their own per-tx limits (e.g. Arbitrum One uses 32M). Reword comments
and rename the test const to make the Mainnet scope explicit.
@0xDevNinja
Copy link
Copy Markdown
Author

0xDevNinja commented May 4, 2026

@jmg-duarte, Addressed all three suggestions in 20dba82:

  • Reworded comment at Gas::new to read "EIP-7825's 16,777,215 cap on Mainnet Fusaka".
  • Updated test const doc to mention Mainnet's Fusaka hardfork explicitly.
  • Renamed test const EIP_7825_TX_GAS_CAPEIP_7825_MAINNET_TX_GAS_CAP.

Good to know about Arb1 picking 32M — that's exactly why the cap is now driven by the per-chain tx_gas_limit config knob rather than a hardcoded value.

Copy link
Copy Markdown
Member

@AryanGodara AryanGodara left a comment

Choose a reason for hiding this comment

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

Nit: description claims hardcoded const EIP_7825_TX_GAS_CAP but that is no longer true, as it uses tx_gas_limit plumbing.
Update body to reflect the pivot.

Copy link
Copy Markdown
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

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

Two minor follow-ups, neither blocking.

PR description note: the Changes list still says the cap is exposed as Gas::EIP_7825_TX_GAS_CAP for callers and tests to share, but the final code keeps the constant private to the test module and the per-tx ceiling now comes from the existing tx_gas_limit config knob, not a hardcoded constant. Worth tightening before squash so the commit message reflects what shipped.

let block_limit = gas(120_000_000);
let tx_gas_limit = gas(EIP_7825_MAINNET_TX_GAS_CAP);
let result = Gas::new(tx_gas_limit, block_limit, tx_gas_limit).unwrap();
assert_eq!(result.estimate, tx_gas_limit);
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.

The boundary test only asserts estimate, but limit is what flows downstream into required_balance and the submitted tx's gas field. With estimate == tx_gas_limit, the 2.0× buffer would compute estimate_with_buffer = 2 * tx_gas_limit, and the min(max_gas, ...) clamp is what keeps the limit at the cap. Worth locking that in.

Suggested change
assert_eq!(result.estimate, tx_gas_limit);
assert_eq!(result.estimate, tx_gas_limit);
assert_eq!(result.limit, tx_gas_limit);

Copy link
Copy Markdown
Author

@0xDevNinja 0xDevNinja May 6, 2026

Choose a reason for hiding this comment

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

Good catch — applied in 78cbd3b. Locks in that the 2x estimate buffer can't leak past the configured cap.

When estimate == tx_gas_limit, the 2x estimate buffer would otherwise
set limit to 2 * tx_gas_limit; the min(max_gas, ...) clamp pins it back
to the configured cap. Lock that contract in.
@0xDevNinja
Copy link
Copy Markdown
Author

Updated the PR description to reflect the pivot — the cap now reads from the existing tx_gas_limit config knob, no hardcoded constant exposed. Also tightened the accepts_solution_at_tx_gas_limit test in 78cbd3b per @squadgazzz's suggestion.

@0xDevNinja 0xDevNinja requested a review from squadgazzz May 6, 2026 06:33
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.

bug: Driver doesn't enforce the EIP-7825 per-transaction gas cap

4 participants