Skip to content

feat(test-specs): Allow automatic transaction gas-limit#2969

Open
marioevz wants to merge 46 commits into
ethereum:forks/amsterdamfrom
marioevz:implicit-gas-limit
Open

feat(test-specs): Allow automatic transaction gas-limit#2969
marioevz wants to merge 46 commits into
ethereum:forks/amsterdamfrom
marioevz:implicit-gas-limit

Conversation

@marioevz

@marioevz marioevz commented Jun 9, 2026

Copy link
Copy Markdown
Member

🗒️ Description

Summary

While reviewing #2901 I noticed that the bulk of its test changes were simply bumping the gas_limit of transactions in tests that don't actually care about the exact gas limit — they only care that the transaction executes in full without running out of gas.

This PR makes the transaction gas_limit optional. When a test omits it, the filling/execution tooling calculates it automatically based on fork properties.

Review Plan

Tests

folder Owner
tests/amsterdam/eip7928_block_level_access_lists @raxhvl
tests/amsterdam/eip8037_state_creation_gas_cost_increase @spencer-tb
tests/amsterdam/* (others) @spencer-tb
tests/berlin @kclowes
tests/byzantium ''
tests/cancun ''
tests/common ''
tests/constantinople ''
tests/frontier ''
tests/homestead @felix314159
tests/istanbul ''
tests/osaka ''
tests/paris ''
tests/prague ''
tests/shanghai @danceratopz
tests/ported_static @spencer-tb

Testing Framework

folder Owner
packages/testing/src/execution_testing/cli/pytest_commands/plugins @leolara
packages/testing/src/execution_testing/execution @leolara
packages/testing/src/execution_testing/fixtures @leolara
packages/testing/src/execution_testing/forks @leolara
packages/testing/src/execution_testing/specs @leolara
packages/testing/src/execution_testing/test_types @leolara
packages/testing/src/execution_testing/tools @leolara

Tooling changes

Transaction.gas_limit now defaults to None instead of HexNumber(21_000).

Transaction.set_gas_limit() resolves an unset limit in place, and signing now raises ValueError("gas_limit must be set to sign a transaction") if the limit is still unset by the time the transaction is signed.

This lead to many typing issues that have now been resolved, but it can be argued that a better choice is to leave HexNumber as the type for Transaction.gas_limit and rely instead on model_fields_set to determine whether the gas limit has been set by the tester.

BlockchainTest and StateTest Fillers

For State tests (StateTest), an unset gas_limit is filled with the fork's transaction_gas_limit_cap(), falling back to the environment gas_limit when there is no cap.

For Blockchain tests (BlockchainTest), the block's remaining gas (env.gas_limit minus the gas already claimed by transactions with explicit limits) is split evenly across the transactions that leave gas_limit unset, clamped to the fork's transaction gas-limit cap. It raises a clear "test correctness" error if no gas remains.

Execute Tests

The same logic is implemented for the execute path (calculate_max_transaction_gas_limit in execution/base.py, applied in transaction_post.py and blob_transaction.py), so implicit gas limits work when running against a live client, not just during filling.

It can be argued that there's a better path to resolve the transaction gas limit in the case of execute, such as:

  • Use eth_estimateGas and use the value returned, with the minor caveat that the contracts that the transaction requires have to be already on chain before calling this RPC method.
  • Run the T8N tool interface with the transaction to obtain the gas used.

Both methods require more work and could be implemented in a future PR.

State gas reservoir (EIP-8037)

Rather than special-casing EIP-8037 (fork.is_eip_enabled(8037)), this PR introduces a fork-level concept:

  • New abstract fork method Fork.state_gas_reservoir_enabled() (alongside the existing transaction_gas_limit_cap()), defaulting to False and turned on by EIP-8037, currently in Amsterdam.
  • New Transaction.state_gas_reservoir field. When a fork enables the reservoir, the transaction gas-limit cap is treated as removed and set_gas_limit() accounts for the requested reservoir (transaction_gas_limit_cap + state_gas_reservoir) when sizing the implicit limit.
  • EIP-8037 tests were refactored to express their requirement through state_gas_reservoir instead of hand-computing gas limits (tx.state_gas_reservoir = state_gas_reservoir instead of tx.gas_limit = gas_limit_cap + state_gas_reservoir).

Test cleanup

The implicit gas limit was applied across the test suite, removing explicit gas_limit assignments from transactions wherever the precise limit was irrelevant to what the test exercises. This touches ~509 test files (net ~7,200 lines removed) spanning Frontier through Amsterdam and many individual EIPs (1153, 4844, 5656, 6780, 7516, 7708, 7843, 7928, 8024, Blake2, etc.).

Tests that should rely on the implicit gas limit are those that only need the transaction to execute fully without running out of gas. Tests that intentionally probe gas-limit behavior continue to set it explicitly.

Incidental fixes surfaced while porting tests

  • pre.fund_eoa default bumped from 10**21 to 10**27 to fix deposit tests that were under-funded.
  • EIP-7883 was not being activated in Osaka; this is now fixed.

🔗 Related Issues or PRs

Closes #2248:

✅ Checklist

  • All: Ran fast static checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    just static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.
  • All: Set appropriate labels for the changes (only maintainers can apply labels).
  • Tests: Ran mkdocs serve locally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.
  • Tests: For PRs implementing a missed test case, update the post-mortem document to add an entry the list.
  • Ported Tests: All converted JSON/YML tests from ethereum/tests or tests/static have been assigned @ported_from marker.

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@felix314159

Copy link
Copy Markdown
Contributor

i looked at the changes for homestead, istanbul, osaka, paris, prague and shanghai, they are fine.
fill of modified files still works, and almost all tests also passed consume direct against geth. the only failures were 140 failures for tests/paris/eip7610_create_collision but those are expected (i made an issue for this recently). it is a good PR, we should have done this earlier

Co-authored-by: Leo Lara <leolara@users.noreply.github.com>

@danceratopz danceratopz left a comment

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.

Hey @marioevz, this is a great addition. Here's a review of the framework changes (only covered the testing framework so far; with partial review of tests for context: tests/shanghai/, tests/amsterdam/eip7928_*). Few comments below, each links to a proposed fix; the full set, including a new unit test module for the dynamic gas-limit machinery is in marioevz#6.

Comment thread packages/testing/src/execution_testing/execution/base.py Outdated
Comment thread packages/testing/src/execution_testing/specs/blockchain.py Outdated
Comment thread packages/testing/src/execution_testing/specs/blockchain.py
Comment thread packages/testing/src/execution_testing/test_types/transaction_types.py Outdated
Comment thread packages/testing/src/execution_testing/test_types/transaction_types.py Outdated
Comment thread packages/testing/src/execution_testing/test_types/transaction_types.py Outdated
Comment thread packages/testing/src/execution_testing/test_types/transaction_types.py Outdated
@marioevz

Copy link
Copy Markdown
Member Author

@LouisTsai-Csie could you check if split_transaction from the benchmark tests still work fine?

marioevz and others added 6 commits June 11, 2026 09:12
Co-authored-by: Leo Lara <leolara@users.noreply.github.com>
Co-authored-by: Leo Lara <leolara@users.noreply.github.com>
Co-authored-by: Leo Lara <leolara@users.noreply.github.com>
Co-authored-by: danceratopz <danceratopz@gmail.com>
Co-authored-by: danceratopz <danceratopz@gmail.com>
…enabled

Co-authored-by: danceratopz <danceratopz@gmail.com>
@marioevz

Copy link
Copy Markdown
Member Author

@leolara @danceratopz pushed the fixes to all of your comments, thank you for the reviews!

@danceratopz

Copy link
Copy Markdown
Member

@leolara @danceratopz pushed the fixes to all of your comments, thank you for the reviews!

Thanks @marioevz, I think you missed the unit tests added in marioevz@ebbe563

@raxhvl raxhvl left a comment

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.

Reviewed 7928 and 7708

@kclowes kclowes left a comment

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.

Berlin-Frontier look good to me. This is such a nice change!

@leolara

leolara commented Jun 12, 2026

Copy link
Copy Markdown
Member

@marioevz I think there are places where we are setting Transaction(gas_limit=None) but setting it to a variable that can be None.

@leolara

leolara commented Jun 12, 2026

Copy link
Copy Markdown
Member

@marioevz I think there are places where we are setting Transaction(gas_limit=None) but setting it to a variable that can be None.

Like here: https://github.com/marioevz/execution-specs/blob/f82f657ed2ff7f4d0a5ecd39b3aadb4aaae41d16/tests/prague/eip7002_el_triggerable_withdrawals/helpers.py#L117

@leolara

leolara commented Jun 12, 2026

Copy link
Copy Markdown
Member

I think there are no unit tests for with_gas_limit, _calculate_implicit_gas_limit, calculate_max_gas_limit and state_gas_reservoir. Perhaps we don't need it because they are called from other tests.

@marioevz

Copy link
Copy Markdown
Member Author

@marioevz I think there are places where we are setting Transaction(gas_limit=None) but setting it to a variable that can be None.

Like here: https://github.com/marioevz/execution-specs/blob/f82f657ed2ff7f4d0a5ecd39b3aadb4aaae41d16/tests/prague/eip7002_el_triggerable_withdrawals/helpers.py#L117

Nice catch, uploaded a new commit a2e13fb. Just as a side note, I think this specific tests need an update because they are no longer really accurate (they hard-code assumed gas costs for the system contracts, which no longer hold).

@marioevz

Copy link
Copy Markdown
Member Author

Once @spencer-tb signs off we can proceed to merge.

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.

Suggestion: For tests, let the default tx gas limit be the maximum allowed value

7 participants