Skip to content

chore(l1): fix precompile tests from EIP-7702#2711

Closed
DiegoCivi wants to merge 3 commits into
mainfrom
fix_eip7702_ef_tests
Closed

chore(l1): fix precompile tests from EIP-7702#2711
DiegoCivi wants to merge 3 commits into
mainfrom
fix_eip7702_ef_tests

Conversation

@DiegoCivi

@DiegoCivi DiegoCivi commented May 8, 2025

Copy link
Copy Markdown
Contributor

Motivation

On #2586 new tests were added and some of them regarding the EIP-7702 and precompiles were failing in LEVM.

Description

  • Tests from file eip7702_set_code_tx/set_code_txs/set_code_to_precompile.json were failing because we were not transferring WEI when the target address of a delegation was one of the precompiles. As a result, balances were not updated, causing an incorrect state root.
  • Tests from file eip7702_set_code_tx/set_code_txs/set_code_to_precompile_not_enough_gas_for_precompile_execution.json were failing because when a precompile was the target of a delegation, and its execution failed a revert was returned. This caused an incorrect receipts root because if a precompile fails in this context, a success should be returned.

Closes #2691

When doing a generic call (CALL, CALLCODE, DELEGATECALL,
STATICCALL) we were first checking if it was a delegation
and if the bytecode was empty, and if this was true the
call would not continue. After that the transfer
of WEI to the account was done. When using precompiles
(which have empty code) we never reached the transfering stage,
so the change in the balance was never done and the
state root was not correct. We now first do the transfer
and the the checking of bytecode. This fixes 17 tests that were
being skipped on LEVM.
@github-actions

github-actions Bot commented May 8, 2025

Copy link
Copy Markdown

Benchmark Results Comparison

PR Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 239.7 ± 0.7 238.8 241.2 1.00
levm_Factorial 878.3 ± 5.5 874.4 893.4 3.66 ± 0.03

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.468 ± 0.074 1.400 1.620 1.00
levm_FactorialRecursive 13.260 ± 0.166 13.006 13.390 9.03 ± 0.47

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 212.8 ± 1.2 210.7 214.7 1.00
levm_Fibonacci 880.0 ± 3.6 873.8 886.1 4.14 ± 0.03

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 8.7 ± 0.1 8.5 8.9 1.00
levm_ManyHashes 18.1 ± 1.6 17.3 22.7 2.09 ± 0.19

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.271 ± 0.087 3.216 3.501 1.00
levm_BubbleSort 5.757 ± 0.052 5.704 5.851 1.76 ± 0.05

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 250.7 ± 1.5 247.3 252.5 1.00
levm_ERC20Transfer 507.5 ± 4.2 501.0 513.5 2.02 ± 0.02

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 143.4 ± 0.8 142.7 145.0 1.00
levm_ERC20Mint 323.3 ± 5.2 318.1 336.1 2.26 ± 0.04

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.057 ± 0.004 1.051 1.062 1.00
levm_ERC20Approval 1.932 ± 0.013 1.912 1.948 1.83 ± 0.01

Main Results

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Factorial 239.8 ± 0.9 238.8 241.6 1.00
levm_Factorial 823.5 ± 10.8 813.1 845.2 3.43 ± 0.05

Benchmark Results: Factorial - Recursive

Command Mean [s] Min [s] Max [s] Relative
revm_FactorialRecursive 1.468 ± 0.046 1.425 1.576 1.00
levm_FactorialRecursive 13.091 ± 0.114 13.011 13.309 8.92 ± 0.29

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
revm_Fibonacci 212.5 ± 1.0 211.4 214.2 1.00
levm_Fibonacci 819.4 ± 6.8 812.7 828.5 3.86 ± 0.04

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ManyHashes 8.8 ± 0.0 8.7 8.9 1.00
levm_ManyHashes 17.3 ± 0.3 17.1 17.9 1.97 ± 0.03

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
revm_BubbleSort 3.250 ± 0.034 3.217 3.337 1.00
levm_BubbleSort 5.616 ± 0.055 5.530 5.700 1.73 ± 0.02

Benchmark Results: ERC20 - Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Transfer 250.7 ± 1.3 248.7 252.7 1.00
levm_ERC20Transfer 500.9 ± 2.0 498.4 504.8 2.00 ± 0.01

Benchmark Results: ERC20 - Mint

Command Mean [ms] Min [ms] Max [ms] Relative
revm_ERC20Mint 141.5 ± 0.7 140.8 143.2 1.00
levm_ERC20Mint 322.5 ± 2.6 320.2 329.4 2.28 ± 0.02

Benchmark Results: ERC20 - Approval

Command Mean [s] Min [s] Max [s] Relative
revm_ERC20Approval 1.045 ± 0.010 1.033 1.061 1.00
levm_ERC20Approval 1.898 ± 0.017 1.881 1.939 1.82 ± 0.02

When a precompile is the target of the delegation in a
0x04 type transaction, its execution should return always
success. This is a possible solution that changes the
result of an ExecutionReport from a Revert to a Success
if we are in this specific case.
@github-actions

github-actions Bot commented May 9, 2025

Copy link
Copy Markdown

Lines of code report

Total lines added: 11
Total lines removed: 1
Total lines changed: 12

Detailed view
+-----------------------------------------------------+-------+------+
| File                                                | Lines | Diff |
+-----------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/hooks/default_hook.rs     | 350   | +11  |
+-----------------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/opcode_handlers/system.rs | 830   | -1   |
+-----------------------------------------------------+-------+------+

@DiegoCivi DiegoCivi added the testing Hive tests, execution-spec-tests, etc label May 9, 2025
Comment on lines 828 to 834
// Transfer value from caller to callee.
if should_transfer_value {
self.decrease_account_balance(msg_sender, value)?;
self.increase_account_balance(to, value)?;
}

let new_depth = {

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.

        let current_call_frame = self.current_call_frame_mut()?;

        let new_depth = current_call_frame
            .depth
            .checked_add(1)
            .ok_or(InternalError::ArithmeticOperationOverflow)?;

        if new_depth > 1024 {
            current_call_frame.gas_used = current_call_frame
                .gas_used
                .checked_sub(gas_limit)
                .ok_or(InternalError::GasOverflow)?;
            current_call_frame.stack.push(REVERT_FOR_CALL)?;
            return Ok(OpcodeResult::Continue { pc_increment: 1 });
        }

        // Transfer value from caller to callee.
        if should_transfer_value {
            self.decrease_account_balance(msg_sender, value)?;
            self.increase_account_balance(to, value)?;
        }

        if bytecode.is_empty() && is_delegation {
            let current_call_frame = self.current_call_frame_mut()?;
            current_call_frame.gas_used = current_call_frame
                .gas_used
                .checked_sub(gas_limit)
                .ok_or(InternalError::GasOverflow)?;
            current_call_frame.stack.push(SUCCESS_FOR_CALL)?;
            return Ok(OpcodeResult::Continue { pc_increment: 1 });
        }

What do you think about leaving it this way? Maybe we could also add a comment above the check of empty bytecode and delegation explaining what that means and why we return success.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree, it looks better that way. However I did some little changes because of problems with the borrow checker, let me know if you agree with them. 36c7a

@DiegoCivi

Copy link
Copy Markdown
Contributor Author

This was done in #2842

@DiegoCivi DiegoCivi closed this May 22, 2025
edg-l added a commit that referenced this pull request Apr 23, 2026
…nting

The zkevm@v0.3.x fixtures under eip8025_optional_proofs/ were filled against
bal@v5.6.1 (devnets/bal/3), which predates EELS PR #2711 "immutable
intrinsic_state_gas for EIP-7702". Their expected gas assumes the auth refund
still deducts from block-accounted state gas.

Our devnet-4 (bal@v5.7.0) implementation correctly keeps intrinsic_state_gas
immutable and routes the refund to the reservoir only (commit a5671c9), so
these six fixtures report GasUsedMismatch/ReceiptsRootMismatch by construction.
Skip until an upstream zkevm@v0.4.x release ships fixtures regenerated against
devnet-4.

Remaining failures after this: 0 on `make -C tooling/ef_tests/blockchain test`.
edg-l added a commit that referenced this pull request Apr 23, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request Apr 23, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request Apr 23, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 6, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 6, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 6, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
introduced in ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen
commit (ethereum/execution-specs PR #2711) is unambiguous:
"intrinsic_state_gas is immutable after validation". The refund only
flows to message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

ec5141c made ethrex match geth/besu — but those clients also have
this bug per execution-specs#2804 (cross-client bug to fix before
bal-devnet-7). The fixtures (= EELS) prove the spec-correct expectation.

Concretely fixes the 72 pointer_to_precompile parametrizations and the
~16 state_gas_set_code tests in bal-devnet-6@v1.1.0, all of which
expected block.gasUsed to include the full intrinsic_state_gas in the
state dimension.
edg-l added a commit that referenced this pull request May 6, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 6, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 6, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 6, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 6, 2026
…_used / intrinsic_state_gas_charged

Re-applies ec5141c. Lines up with EELS PR #2711 future direction
(MessageCallOutput.state_refund subtracted from tx_state_gas, mirroring
SELFDESTRUCT). Bal-devnet-6 fixtures still expect the un-subtracted
value, so the affected ef-tests will be allowlisted via the known-fails
mechanism with a citation to execution-specs commit 9b3961a65
(test_snobal_block_gas_used_inflated_by_7702_auth_refund) which locks
in the devnet-6 quirk.
edg-l added a commit that referenced this pull request May 7, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 7, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 7, 2026
…_used / intrinsic_state_gas_charged

Re-applies ec5141c. Lines up with EELS PR #2711 future direction
(MessageCallOutput.state_refund subtracted from tx_state_gas, mirroring
SELFDESTRUCT). Bal-devnet-6 fixtures still expect the un-subtracted
value, so the affected ef-tests will be allowlisted via the known-fails
mechanism with a citation to execution-specs commit 9b3961a65
(test_snobal_block_gas_used_inflated_by_7702_auth_refund) which locks
in the devnet-6 quirk.
edg-l added a commit that referenced this pull request May 7, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 7, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 7, 2026
…_used / intrinsic_state_gas_charged

Re-applies ec5141c. Lines up with EELS PR #2711 future direction
(MessageCallOutput.state_refund subtracted from tx_state_gas, mirroring
SELFDESTRUCT). Bal-devnet-6 fixtures still expect the un-subtracted
value, so the affected ef-tests will be allowlisted via the known-fails
mechanism with a citation to execution-specs commit 9b3961a65
(test_snobal_block_gas_used_inflated_by_7702_auth_refund) which locks
in the devnet-6 quirk.
edg-l added a commit that referenced this pull request May 8, 2026
Brings ethrex up to bal-devnet-4 fixture spec. Rolls up EIP-7928,
EIP-8037, EIP-7976, EIP-7981, EIP-7708 and misc BAL validation fixes
into one change set.

BAL (EIP-7928)
- Widen BlockAccessIndex and related recorder/index fields to u32.
- Shadow BAL recorder on per-tx tx_dbs in the parallel validator:
  diff touched_addresses / storage_reads against header BAL to catch
  missing pure-access entries and missing storage_reads.
- Fall back to pre-state code_hash in validate_tx_execution PART B
  when the BAL has no code_changes entry (missing_code_change).
- Stop whitelisting SYSTEM_ADDRESS from unaccessed_pure_accounts via
  system_seed / current_accounts_state scrubs; user-tx touches still
  remove it via the per-tx tracked_accounts path.

EIP-8037 (state gas 2D accounting)
- Dynamic cost_per_state_byte(block_gas_limit), Amsterdam only.
- Two-counter reservoir: state_gas_spill_outstanding +
  state_gas_credit_against_drain for correct revert math across
  nested sub-calls (PR #2733 clamp-and-spill).
- Per-tx 2D inclusion check (PR #2703) in sequential + parallel
  paths: reject with GAS_ALLOWANCE_EXCEEDED when tx.gas worst-case
  exceeds remaining block regular/state budget.
- intrinsic_state_gas immutable across the tx (PR #2711) and
  subtracted separately when deriving block-dimensional regular gas.
- CREATE collision/early/child failure refunds account state gas.
- Same-tx SELFDESTRUCT refunds state gas clamped against
  execution-only state gas (PR #2707), not total state_gas_used.
- Revert-path reservoir refill uses the PR #2733 X - Z formula.
- Top-level reservoir reset on tx failure (PR #2689).
- Zero gas_remaining on precompile exceptional halt so block
  accounting sees the full intrinsic.

Calldata / access-list floors
- TOTAL_COST_FLOOR_PER_TOKEN 10 -> 16 under Amsterdam (EIP-7976).
- Access-list data bytes fold into floor-token count (EIP-7981).

EIP-7708
- Lex-ordered burn logs, no coinbase priority-fee log, SELFDESTRUCT-
  destination coalescing.

Tests
- New levm tests for EIP-7976/7981, EIP-8037 refund/code-deposit/
  top-level-failure paths.
- Skip 6 zkevm@v0.3.0 EIP-8025 fixtures filled against bal@v5.6.1
  (re-enable once zkevm@v0.4.x ships).

Hive consume-engine amsterdam: 1339 pass, 3 remaining (withdrawal
missing-entry cases addressed by PR #6463, cherry-pick pending).
edg-l added a commit that referenced this pull request May 8, 2026
Reverts the state_gas_used and intrinsic_state_gas_charged subtractions
from ec5141c. EELS spec at the bal-devnet-6@v1.1.0 fixture-gen commit
(ethereum/execution-specs PR #2711) is explicit: "intrinsic_state_gas is
immutable after validation". The refund only flows to
message.state_gas_reservoir; block accounting computes
tx_state_gas = intrinsic_state_gas + state_gas_used WITHOUT subtracting
the refund.

Concretely fixes the 72 pointer_to_precompile parametrizations and
the state_gas_set_code family in bal-devnet-6@v1.1.0, which expect
block.gasUsed to include the full intrinsic_state_gas in the state
dimension (max(regular, state) per EIP-7778).

NOTE: future spec direction. The bal-devnet-6 spec acknowledges this as
a bug locked in for devnet verification only. See
ethereum/execution-specs commit 9b3961a65 (added a regression test
`test_snobal_block_gas_used_inflated_by_7702_auth_refund`) and its
docstring: the intended long-term fix is to add MessageCallOutput.state_refund
and subtract it from tx_state_gas, mirroring the SELFDESTRUCT refund
pattern. ec5141c was implementing that future behavior; we are
reverting it because bal-devnet-6 fixtures (current target) require the
un-subtracted value. Re-apply the subtraction when bal-devnet-7
fixtures land with the spec fix.
edg-l added a commit that referenced this pull request May 8, 2026
…_used / intrinsic_state_gas_charged

Re-applies ec5141c. Lines up with EELS PR #2711 future direction
(MessageCallOutput.state_refund subtracted from tx_state_gas, mirroring
SELFDESTRUCT). Bal-devnet-6 fixtures still expect the un-subtracted
value, so the affected ef-tests will be allowlisted via the known-fails
mechanism with a citation to execution-specs commit 9b3961a65
(test_snobal_block_gas_used_inflated_by_7702_auth_refund) which locks
in the devnet-6 quirk.
edg-l added a commit that referenced this pull request May 11, 2026
bal-devnet-6 EELS spec (`devnets/bal/6` `eoa_delegation.py`) only does
`message.state_gas_reservoir += STATE_BYTES_PER_NEW_ACCOUNT × cpsb`
on each existing-authority refund. Docstring: "no mutation of
intrinsic_state_gas".

Drops the two extra subtractions previously added in `cefdf69de` that
anticipated EELS PR #2711 / #2816 (the bal-7 `state_refund` channel).
For bal-6 the block-level `state_gas_used` intentionally stays
"inflated" by the auth refund — the refund is sender-side only in this
devnet. Block-accounting subtraction lands in bal-devnet-7 via the
separate `state_refund` channel.

Unblocks the snobal-devnet-6 EIP-7702 fixtures previously allowlisted
under "bal-devnet-6 known-failing fixtures (Amsterdam fork only)" in
tooling/ef_tests/blockchain/tests/all.rs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

testing Hive tests, execution-spec-tests, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LEVM: Fix EF blockchain tests related to EIP-7702

2 participants