Commit aa13336
authored
feat(eip8037): Amsterdam bal-devnet-7 (#3667)
* feat(gas): EIP-8037 issue #2 — 0→x→0 storage reservoir refill (#3581)
* feat(gas): implement EIP-8037 issue #2 — 0→x→0 storage reservoir refill
When a storage slot is restored to its original zero value within the
same transaction, the state gas originally charged for the 0→x
transition is now returned directly to the reservoir rather than
routed through the capped (spent/5) refund counter. This preserves
the EIP-8037 invariant that state gas consumption correlates with
actual state creation.
Changes:
- `GasTracker.state_gas_spent` becomes `i64`. A child frame's count
can legitimately go negative when it clears a slot that the parent
had set; the net is reconciled on frame return.
- New `GasTracker::refill_reservoir(amount)` and `Gas::refill_reservoir`
wrappers: add to reservoir, subtract from `state_gas_spent`.
- New `GasParams::sstore_state_gas_refill` returns `32 * CPSB` only
on 0→x→0 restoration.
- SSTORE instruction calls `refill_reservoir` when EIP-8037 is
enabled and the restoration condition matches.
- EIP-8037 table: `sstore_set_refund` drops from `32 * CPSB + 2800`
to `2800`; the state portion now flows through the reservoir refill
path rather than the refund counter.
- `handle_reservoir_remaining_gas` (frame.rs) uses saturating i64
math on both success and revert/halt paths so the parent's matching
0→x charge is correctly netted out on success, and the combined
`state_gas_spent + reservoir` is clamped to 0 on failure.
- Top-frame reconciliation (handler.rs) and `build_result_gas`
(post_execution.rs) clamp to 0 before the public `u64` surface.
- Precompile + inspector plumbing updated for the i64 switch.
Test updated: `test_eip8037_sstore_set_then_clear_refund` now
asserts `state_gas_spent == 0` and that total gas spent matches the
baseline (was asserting +200k and a strict `>` inequality). Golden
JSON regenerated.
* fix(ee-tests): adapt custom opcode test to new insert_instruction signature
`insert_instruction` gained a `gas: u16` parameter in the instruction-table
refactor (#3561), and `Instruction::new` now takes only the fn. Update the
DOUBLE opcode registration in `revm_tests.rs` so the ee-tests crate compiles.
* test(eip8037): add same-frame and cross-frame 0→x→0 restoration tests
Covers the two EIP-8037 issue #2 code paths:
- `test_eip8037_sstore_refill_same_frame`: 0→1→0 within one frame ends
with `state_gas_spent == 0`; compared against a set-only variant
that retains the full `STATE_GAS_SSTORE_SET` charge.
- `test_eip8037_sstore_refill_cross_frame`: parent SSTORE(0,1), then
DELEGATECALLs a child that does SSTORE(0,0). The refill fires in
the child frame (driving child `state_gas_spent` negative); on
frame return the parent's +200k and child's -200k net out, leaving
only the CREATE + code-deposit state gas on the books.
* feat(gas): EIP-7976 — increase calldata floor cost to 64/64 (#3597)
* feat(gas): EIP-7976 — increase calldata floor cost to 16/64 gas per byte
Introduces a new `tx_floor_token_zero_byte_weight` GasId so the floor tokens
formula becomes `zero × floor_zero_weight + nonzero × tx_token_non_zero_byte_multiplier`.
Under EIP-7623 (Prague) the weight stays at 1 — reproducing the existing
`tokens_in_calldata`-based floor. Under EIP-7976 (Amsterdam) the weight is
raised to `tx_token_non_zero_byte_multiplier`, which yields
`floor_tokens_in_calldata = (zero + nonzero) × 4` and, together with the
per-token bump from 10 to 16, a uniform 64 gas/byte floor.
* docs: correct EIP-7976 floor cost comment (64/64, not 16/64)
* perf(gas): skip zero-byte scan when floor weights match
When
(Amsterdam / EIP-7976), every calldata byte contributes the same number of
floor tokens. In that case we can use `input.len() * weight` directly and
skip the filter+count pass over the calldata.
* refactor(gas): rename tx_floor_token_zero_byte_weight to _multiplier
Matches the naming of `tx_token_non_zero_byte_multiplier`. No behavior
change.
* refactor(gas): reuse get_tokens_in_calldata in tx_floor_cost
The EIP-7623 branch (zero-byte multiplier = 1) produces exactly
`zero + nonzero * non_zero_multiplier`, which is what get_tokens_in_calldata
already computes. Delegate to it instead of re-implementing the scan inline.
The EIP-7976 uniform path keeps its `input.len() * multiplier` shortcut.
* refactor(gas): extract tx_floor_cost_with_tokens helper
* feat(gas): implement EIP-7981 access list cost increase (#3598)
* feat(gas): EIP-7976 — increase calldata floor cost to 16/64 gas per byte
Introduces a new `tx_floor_token_zero_byte_weight` GasId so the floor tokens
formula becomes `zero × floor_zero_weight + nonzero × tx_token_non_zero_byte_multiplier`.
Under EIP-7623 (Prague) the weight stays at 1 — reproducing the existing
`tokens_in_calldata`-based floor. Under EIP-7976 (Amsterdam) the weight is
raised to `tx_token_non_zero_byte_multiplier`, which yields
`floor_tokens_in_calldata = (zero + nonzero) × 4` and, together with the
per-token bump from 10 to 16, a uniform 64 gas/byte floor.
* docs: correct EIP-7976 floor cost comment (64/64, not 16/64)
* perf(gas): skip zero-byte scan when floor weights match
When
(Amsterdam / EIP-7976), every calldata byte contributes the same number of
floor tokens. In that case we can use `input.len() * weight` directly and
skip the filter+count pass over the calldata.
* refactor(gas): rename tx_floor_token_zero_byte_weight to _multiplier
Matches the naming of `tx_token_non_zero_byte_multiplier`. No behavior
change.
* refactor(gas): reuse get_tokens_in_calldata in tx_floor_cost
The EIP-7623 branch (zero-byte multiplier = 1) produces exactly
`zero + nonzero * non_zero_multiplier`, which is what get_tokens_in_calldata
already computes. Delegate to it instead of re-implementing the scan inline.
The EIP-7976 uniform path keeps its `input.len() * multiplier` shortcut.
* refactor(gas): extract tx_floor_cost_with_tokens helper
* feat(gas): implement EIP-7981 access list cost increase
Folds the per-byte data charge into the per-item access-list cost and
extends the EIP-7623/7976 floor to cover access-list bytes, both gated
on AMSTERDAM.
- tx_access_list_address_cost: 2400 -> 3680 (+20 * 64)
- tx_access_list_storage_key_cost: 1900 -> 3948 (+32 * 64)
- New GasId::tx_access_list_floor_byte_multiplier (= 4 at AMSTERDAM),
surfaced via tx_floor_tokens_in_access_list; initial_tx_gas now adds
the access-list contribution on top of the calldata floor.
* feat(gas): EIP-8037 dynamic CPSB derived from block gas limit (#3603)
* feat(gas): EIP-8037 dynamic cost_per_state_byte derived from block gas limit
Thread CPSB through state-gas accounting so state-gas charges scale with
the current block's gas limit per EIP-8037 instead of using a hard-coded
1174. State-gas table entries now store *byte counts*; helpers multiply
by CPSB at charge time via new `Cfg::cpsb` / `Host::cpsb` methods and a
`CfgEnv::cpsb_override` for tests and replay.
Also refund the parent's upfront CREATE state gas to its reservoir when
a child create reverts or halts, and split the EIP-7702 refund into
separate regular and state-bytes components (new `tx_eip7702_auth_refund_state_bytes`
GasId).
* refactor(frame): move CREATE state-gas refund into return_create
Drop the `state_gas_charged` field from `CreateOutcome` and handle the
upfront CREATE state-gas refund inside `return_create` instead of
`return_result`. The value is threaded through `CreateFrame`:
`return_create` refills it into the reservoir on entry and re-records
it on a successful commit, undoing the refund.
Revert `test_eip8037_reverted_create_child` expectations (and the
associated json testdata) back to the prior semantics, where the
parent's upfront CREATE state gas is not refunded on child revert.
* refactor(frame): derive CREATE state gas inside return_create
`return_create` now takes `&mut impl ContextTr` and derives both the
CPSB and the upfront `create_state_gas` charge from `cfg` + `block`,
removing the need to thread `state_gas_charged` (and `cpsb`) as
parameters. Drops the now-unused `state_gas_charged` fields from
`CreateInputs` and `CreateFrame`, and the corresponding tracking
in the CREATE opcode.
* perf(context): cache EIP-8037 cpsb on LocalContext
Adds a cpsb field to LocalContext exposed via LocalContextTr, populated at
the start of every execution entry point (Handler::run, run_system_call,
and their inspector variants) so the hot-path Host::cpsb is a single field
read instead of recomputing cfg.cpsb(block.gas_limit()) on each call.
* refactor(frame): use cached cpsb from local context in return_create
Reads cpsb from LocalContext (set at tx entry) instead of recomputing from
cfg+block, and simplifies the EIP-8037 gating now that the state-gas
charge is always derivable from the cached value.
* fix(frame): unwind 0→x→0 reservoir refund on sub-frame revert
Per EIP-8037, when a sub-frame reverts, any 0→x→0 reservoir refund it
performed must be rolled back. The previous formula
`parent.reservoir = child.state_gas_spent + child.reservoir` left the
parent's reservoir inflated when the child drained and refilled via a
0→x→0 restoration pattern.
Cap the child's reservoir contribution at the parent's pre-call value
(parent's reservoir isn't modified during the call, so the current value
is the pre-call value) and clamp state_gas_spent to non-negative to
preserve the parent's prior charges.
* fix(post-execution): clamp reservoir when floor gas exceeds limit budget (#3607)
* fix(post-execution): clamp reservoir when floor gas exceeds limit budget
When EIP-7623's data floor clamps `gas_used` upward and
`floor_gas + reservoir > gas.limit` (e.g. an EIP-7702 reservoir refund
pushed the reservoir above `limit - floor_gas`), the plain
`set_spent(floor_gas + reservoir)` saturates `remaining` to 0 but leaves
the reservoir intact, so `reimbursable = remaining + reservoir + refund`
overshoots by `floor_gas + reservoir - limit` gas and the caller is
over-refunded by that amount. In that branch clamp the reservoir to
`limit - floor_gas` and zero `remaining` instead.
* feat(eip8037): refund state gas for CREATE+SELFDESTRUCT and restructure CREATE upfront charge
Adds `JournalTr::eip8037_selfdestruct_state_gas_refund` (and the
`JournalInner` implementation) which sums the state gas charged during
the tx for every account that was both created and self-destructed (per
EIP-6780) — account creation, code deposit, and 0→non-zero storage slot
sets — and skips the CREATE-tx target whose creation gas is already in
`initial_state_gas`. The handler invokes it at the start of
post-execution and refills the reservoir before refund/reimbursement so
the returned gas bypasses the 1/5 refund cap.
Also moves the CREATE opcode's upfront `create_state_gas` refund out of
`return_create` and into the CREATE opcode return path in the parent
frame: the parent charged it and, on child failure (revert/halt/
early-fail with `address == None`), the parent now refunds it directly
and undoes its `state_gas_spent`. The child frame is no longer allowed
to borrow that upfront charge to cover code deposit.
* refactor(journal): iterate selfdestructed_addresses set in EIP-8037 refund
Replace full-state scan with a direct walk over the dedicated
`selfdestructed_addresses` set, hoist the per-tx `sstore_set` constant
out of the inner loop, and drop the redundant `original_value.is_zero()`
check (locally-created accounts always start with empty storage, so
every non-zero present slot was charged sstore_set).
* fix(post-execution): zero reservoir when EIP-7623 floor wins
Match execution-specs: when the floor is enforced, unused state gas is
absorbed into the floor cost, not reimbursed separately. Without this,
`reimburse_caller` (which sums `remaining + reservoir + refunded`)
over-refunds the caller and `reward_beneficiary` under-pays the
beneficiary by exactly `gas.reservoir()`.
Also drop the prior commented-out "set_spent(floor + reservoir)"
workaround — its premise that the reservoir must be added to spent
conflicted with the spec's single-counter model.
* fix(eip8037): correct CREATE state-gas refund propagation and unwind (#3614)
* fix(post-execution): clamp reservoir when floor gas exceeds limit budget
When EIP-7623's data floor clamps `gas_used` upward and
`floor_gas + reservoir > gas.limit` (e.g. an EIP-7702 reservoir refund
pushed the reservoir above `limit - floor_gas`), the plain
`set_spent(floor_gas + reservoir)` saturates `remaining` to 0 but leaves
the reservoir intact, so `reimbursable = remaining + reservoir + refund`
overshoots by `floor_gas + reservoir - limit` gas and the caller is
over-refunded by that amount. In that branch clamp the reservoir to
`limit - floor_gas` and zero `remaining` instead.
* feat(eip8037): refund state gas for CREATE+SELFDESTRUCT and restructure CREATE upfront charge
Adds `JournalTr::eip8037_selfdestruct_state_gas_refund` (and the
`JournalInner` implementation) which sums the state gas charged during
the tx for every account that was both created and self-destructed (per
EIP-6780) — account creation, code deposit, and 0→non-zero storage slot
sets — and skips the CREATE-tx target whose creation gas is already in
`initial_state_gas`. The handler invokes it at the start of
post-execution and refills the reservoir before refund/reimbursement so
the returned gas bypasses the 1/5 refund cap.
Also moves the CREATE opcode's upfront `create_state_gas` refund out of
`return_create` and into the CREATE opcode return path in the parent
frame: the parent charged it and, on child failure (revert/halt/
early-fail with `address == None`), the parent now refunds it directly
and undoes its `state_gas_spent`. The child frame is no longer allowed
to borrow that upfront charge to cover code deposit.
* refactor(journal): iterate selfdestructed_addresses set in EIP-8037 refund
Replace full-state scan with a direct walk over the dedicated
`selfdestructed_addresses` set, hoist the per-tx `sstore_set` constant
out of the inner loop, and drop the redundant `original_value.is_zero()`
check (locally-created accounts always start with empty storage, so
every non-zero present slot was charged sstore_set).
* fix(post-execution): zero reservoir when EIP-7623 floor wins
Match execution-specs: when the floor is enforced, unused state gas is
absorbed into the floor cost, not reimbursed separately. Without this,
`reimburse_caller` (which sums `remaining + reservoir + refunded`)
over-refunds the caller and `reward_beneficiary` under-pays the
beneficiary by exactly `gas.reservoir()`.
Also drop the prior commented-out "set_spent(floor + reservoir)"
workaround — its premise that the reservoir must be added to spent
conflicted with the spec's single-counter model.
* fix(eip8037): correct CREATE/CALL state-gas refund propagation
Three fixes to EIP-8037 reservoir accounting that together resolve 12
failing state tests under fixtures_bal_v570/state_tests/for_amsterdam/:
1. CREATE nonce overflow: the early-fail path returns
`InstructionResult::Return` (ok) with `address == None`, but the
upfront `create_state_gas` refund was gated on `!is_ok()`. Gate on
`address.is_none() || !is_ok()` so the refund applies.
2. 0→x→0 refill unwind on parent revert/halt: add a per-frame
`refill_amount` counter on `GasTracker` that accumulates
`refill_reservoir` calls (and now the CREATE upfront-state-gas refund
on child failure). On revert/halt, `handle_reservoir_remaining_gas`
subtracts this from the propagated reservoir so refill-driven
inflation does not leak up; on success the total is propagated so an
ancestor revert can still unwind it. The CREATE-failed refund now
uses `refill_reservoir` to participate in this tracking.
3. EIP-8037 selfdestruct refund: include the CREATE-tx contract in the
iteration (the execution-specs reference iterates all created+
destroyed accounts) and cap the aggregate refund at
`gas.state_gas_spent()` to match the per-address
`min(refund, state_gas_used)` cap from the spec.
* wip(eip8037): refactor reservoir handling and selfdestruct refund
- Refactor handle_reservoir_remaining_gas to take is_success: bool directly
- Drop is_created_locally / len != 0 guards in journal selfdestruct refund
- Add is_ok_without_selfdestruct helper on InstructionResult
- Stash WIP commented logic in handler for top-level CREATE failure refund
* fix(merge): drop duplicated CREATE state-gas refund block
The merge of origin/dev4-cpsb (00ca181) into functional kept both the
upstream `set_reservoir`/`set_state_gas_spent` block and the local
`refill_reservoir` block, causing every failed child CREATE to refund
`create_state_gas` to the parent's reservoir twice. Keep only the
`refill_reservoir` version: it handles the nonce-overflow path
(address == None with is_ok()) and registers the refund in
`refill_amount` so the parent's own revert/halt unwinds it correctly.
* chore(scripts): bump devnet fixtures to bal@v5.7.0 and enable runs
Also uncomment the devnet statetest run; the devnet btest line is left
as-is.
* test(ee-tests): update reverted CREATE child expected state gas
On child revert, both the parent's upfront CREATE state gas and the
child's SSTORE state gas are refunded to the reservoir, leaving
state_gas_spent at 0.
* fix: enable state refund on tx crate
* refactor(eip8037): drop block_gas_limit from Cfg::cpsb
CPSB is fixed at 1174 for Glamsterdam, so the block-gas-limit-derived
formula is no longer needed. Deprecate cost_per_state_byte, expose
CPSB_GLAMSTERDAM, and update callers and doc comments accordingly.
* fix(eip8037): keep eip7702 reservoir refund out of gross tx state gas
Per the spec, tx_state_gas = intrinsic_state_gas + execution_state_gas.
The EIP-7702 reservoir refund is added back to the state gas reservoir
at tx start, so it must not also be subtracted from the gross state gas
reported in the result.
* fix(eip7702): split per-auth refund into state and regular components
Under EIP-8037 the per-auth refund for existing authorities is entirely
state gas (NEW_ACCOUNT_BYTES * cpsb). apply_eip7702_auth_list was
subtracting the full per-auth state *charge* ((NEW + AUTH_BASE) * cpsb)
from initial_state_gas — overshooting the credit by AUTH_BASE_BYTES per
auth — and returning the combined refund as if it were a regular-gas
refund. Add tx_eip7702_auth_refund_{state,regular} helpers and use them
to apply each portion to the right counter, with a guard for
refund_per_auth == 0.
Also refactors InitialAndFloorGas: replace `initial_total_gas` with an
explicit `initial_regular_gas` + `initial_state_gas` pair, drop the
`eip7702_reservoir_refund` field (state credit now flows through
`initial_state_gas`), and add getter/setter/builder accessors.
* refactor(eip7702): track per-auth refund via dedicated reservoir field
Replace the in-place subtraction from `initial_state_gas` with a separate
`initial_eip7702_refund` field on `InitialAndFloorGas`. The refund is now
added to the reservoir directly in `initial_gas_and_reservoir`, while
`initial_state_gas` keeps the gross intrinsic state gas. Reporting paths
use a new `initial_state_gas_final()` accessor that subtracts the refund.
* fix(eip7702): report gross initial_state_gas in result, not refund-net
build_result_gas was summing `initial_state_gas_final()` into the
reported state gas, but per the surrounding comment the EIP-7702
reservoir refund is credited to the reservoir at tx start and must not
reduce the gross state gas spent. Switch to the raw `initial_state_gas`
field. Update gas_params tests to use the renamed accessor.
* refactor(eip8037): split halt/revert reservoir handling, rename is_error to is_halt
Distinguish halt from revert in the reservoir reconciliation paths:
- handle_reservoir_remaining_gas takes the full InstructionResult and
treats success, revert, and halt distinctly. Halt no longer touches
the parent reservoir from the child-merge path.
- last_frame_result now receives the pre-execution reservoir; on halt
it restores that value (child gas fully consumed, but the tx-level
reservoir is the pre-call snapshot) while revert keeps the existing
combined-recovery formula. State_gas_spent is zeroed on both halt
and revert.
- build_result_gas now combines initial_state_gas with execution
state_gas_spent before clamping, so a transient negative
state_gas_spent from refills doesn't underflow the addition.
Also rename `InstructionResult::is_error` / `InterpreterResult::is_error`
to `is_halt` (deprecated aliases kept) — the old name was confusable
with revert. Inspector gas accounting only spends-all on halt now,
matching the rename. Plumb the reservoir through the inspector
last_frame_result call.
* fix(eip7702): exclude initial state refund from block regular gas
Track initial EIP-7702 state refund on ResultGas and subtract it
from state_gas_spent when computing block_regular_gas_used so the
refunded portion of intrinsic state gas isn't reclassified as
regular execution gas.
* fix(eip8037): regenerate snapshots and refund state gas on top-level halt
- Add missing `refill_amount` field in `PrecompileOutput` literal in
`precompile_provider.rs` test harness (build fix after merge).
- In `last_frame_result`, fold halt into the same state-gas-refund path
used by revert (`reservoir = state_gas_spent + reservoir`), capping at
`original_reservoir + recovered` on halt to strip 0→x→0 refill
inflation. Previously halt set `reservoir = original_reservoir`,
dropping the rolled-back state gas.
- Regenerate insta snapshots for `eip8037` and `revm_tests` to include
the new `eip7702_state_refund` field.
* simplify condition check
* fix(eip8037): plumb new-account state-gas refund, bump CPSB to 1530, fix clippy
Propagate `charged_new_account_state_gas` through CallInputs/CallOutcome so
parent frames can refund the upfront EIP-8037 new-account state-gas charge on
child revert/halt, mirroring the CREATE path. Update Glamsterdam constants
(CPSB 1174→1530, SSTORE_SET_BYTES 32→64, NEW_ACCOUNT_BYTES 112→120), remove
the deprecated `cost_per_state_byte` helper, and refresh tests/snapshots to
use `state_gas_spent_final`. Also fix clippy warnings (missing-const-for-fn,
needless-else, unused variable).
* fix(eip8037): align top-level revert/halt reservoir refund with child-frame rule
Use the same excess-over-baseline formula as handle_reservoir_remaining_gas
for the top frame, so state gas spilled into regular gas is recovered while
0→x→0 refill inflation (both in-frame and propagated up from children) is
stripped on revert/halt.
Add regression tests for tx-Create collision and for a halt where state gas
stayed entirely in the reservoir.
* fix(eip8037): unwind grandchild storage-clear refund on revert/halt
`handle_reservoir_remaining_gas` and `last_frame_result` discarded the
negative branch of `state_gas_spent` when restoring the parent reservoir
on revert/halt, so a 0→x→0 refill credit accrued by a grandchild and
propagated through a successful child could survive into the parent
even after the child reverted — the underlying storage clear no longer
existed but the reservoir inflation persisted.
Use the invariant `pre_call_reservoir = reservoir + state_gas_spent`
(record_state_cost and refill_reservoir move the two symmetrically) via
`saturating_add_signed`, so the negative contribution unwinds the leaked
refill inflation. Fixes the subcall_revert and depth-chain leak tests
from the EIP-8037 reservoir suite; full Amsterdam state-test failure
count drops from 104 to 1 with no regressions.
* fix(eip8037): align bal-devnet-7 system call gas limit (#3672)
Update system calls to use the bal-devnet-7 gas limit formula instead of the legacy fixed 30M cap.
Changes:
- add SYSTEM_MAX_SSTORES_PER_CALL = 16
- derive SYSTEM_CALL_GAS_LIMIT as
30_000_000 + SSTORE_SET_BYTES * CPSB_GLAMSTERDAM * SYSTEM_MAX_SSTORES_PER_CALL
- update the system_call test to assert the new limit
- sync stale EIP-8037 docs/comments with the current bal-devnet-7 behavior
This matches tests-bal@v7.0.0, where system calls receive a dedicated state-gas reservoir on top of the 30M regular-gas budget.
* fix(eip8037): match EIP-7702 per-auth state refund to its charge
The pessimistic per-auth state gas charged in `initial_tx_gas` is
`(NEW_ACCOUNT_BYTES + AUTH_BASE_BYTES) * cpsb`, but the per-auth refund
in `apply_eip7702_auth_list` only refunded `NEW_ACCOUNT_BYTES * cpsb`,
leaving `AUTH_BASE_BYTES * cpsb` of state gas stranded on every
existing-account authorization. Set `tx_eip7702_auth_refund_state_bytes`
to `NEW_ACCOUNT_BYTES + AUTH_BASE_BYTES` so the refund fully recovers
the pessimistic charge.
* refactor(eip7702): fold state refund into state_gas_spent at result build
Drop the `eip7702_state_refund` field on `ResultGas` and subtract the
EIP-7702 per-authorization state-gas refund from `state_gas_spent` when
building the result. The stored value is now already net of the refund,
so `state_gas_spent_final()` just returns the field directly.
* refactor(eip8037): drop journal-based selfdestruct state-gas refund
Removes `eip8037_selfdestruct_state_gas_refund` from `JournalTr` /
`JournalInner` / post-execution along with the `is_ok_without_selfdestruct`
helper, and renames `InitialAndFloorGas::initial_eip7702_refund` to the
more general `state_refund` since the same field is reused for any
intrinsic state refund. The CREATE-failure unwind in `last_frame_result`
now keys off `is_ok` again instead of the selfdestruct-aware variant.
* docs: update top-level CREATE-failure comment after eip8037 refund removal
* fix(eip8037): split EIP-7702 auth refund into account and bytecode portions
Separate the per-auth state refund into two components: an account refund
(NEW_ACCOUNT_BYTES * cpsb) credited per existing-account authorization and
a bytecode refund (AUTH_BASE_BYTES * cpsb) credited per code-deposit
authorization. apply_auth_list now returns both counts so the caller can
apply each refund independently, and pre-Amsterdam paths continue to route
the regular-gas refund through the standard counter.
Also add AccountInfo::is_code_hash_empty_or_zero() helper used by the new
bytecode-refund check and by is_empty().
* refactor(eip8037): consolidate EIP-7702 state-gas accessors
Drop the dedicated `tx_eip7702_state_gas_new_account` /
`tx_eip7702_auth_refund_state_bytes` slots — both equal already-existing
state-byte constants, so reuse `new_account_state_gas` and a single new
`tx_eip7702_state_gas_bytecode` slot (`AUTH_BASE_BYTES`).
Collapse the per-auth and per-bytecode refund helpers into one
`tx_eip7702_state_refund(refunded_accounts, refunded_bytecodes, cpsb)`
that returns the total state refund, and rename
`tx_eip7702_per_auth_state_gas` → `tx_eip7702_state_gas`. Always-run the
regular per-auth refund (zero under EIP-8037) and unconditionally credit
`state_refund` to the reservoir.
* refactor(eip8037): drop is_eip8037 flag from initial_gas_and_reservoir
Apply `tx_gas_limit_cap` against the full tx limit (then subtract
`initial_regular_gas`) instead of branching on the EIP-8037 flag. The
system-call zero-gas case still bypasses the cap, and the resulting
`regular_gas_limit` / `reservoir` split is equivalent to the previous
two paths. Drop the now-unused flag and unconditionalize the
`initial_state_gas` deduction.
* chore: bump devnet fixtures to bal@v7.1.1 and fix post-merge tests
- scripts/run-tests.sh: pull devnet fixtures from
execution-specs tests-bal@v7.1.1 release (new repo + tag format)
- inspector_tests: rename gas().state_gas_spent() call to
state_gas_spent_final() to match the renamed public accessor
- eip8037 selfdestruct-after-sstore test: SSTORE state gas is no
longer refunded after dropping the journal-based selfdestruct
refund, so expect STATE_GAS_SSTORE_SET + NEW_ACCOUNT_BYTES and
refresh the snapshot
* docs: fix broken intra-doc links and unescaped backticks
- gas_params: rewrite Cfg::cpsb link to super::Cfg::cpsb and split
the tx_floor_cost formula across lines to balance backticks
- result: point state_gas_spent_final() table entry and
block_state_gas_used cross-reference at the public accessor
instead of the private field
- cfg: replace stale reference to primitives::eip8037::cost_per_state_byte
(no such item) with the actual default constant CPSB_GLAMSTERDAM
* chore: add typos to commands and fix lenght typo1 parent 57c4561 commit aa13336
45 files changed
Lines changed: 1683 additions & 369 deletions
File tree
- crates
- context
- interface/src
- cfg
- src
- ee-tests/src
- snapshots
- handler/src
- inspector/src
- interpreter/src
- instructions
- contract
- interpreter_action
- precompile/src
- primitives/src
- state/src
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
97 | 104 | | |
98 | 105 | | |
99 | 106 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
21 | 31 | | |
22 | 32 | | |
23 | 33 | | |
| |||
31 | 41 | | |
32 | 42 | | |
33 | 43 | | |
| 44 | + | |
34 | 45 | | |
35 | 46 | | |
36 | 47 | | |
| |||
79 | 90 | | |
80 | 91 | | |
81 | 92 | | |
82 | | - | |
| 93 | + | |
83 | 94 | | |
84 | 95 | | |
85 | 96 | | |
86 | 97 | | |
87 | 98 | | |
88 | | - | |
| 99 | + | |
89 | 100 | | |
90 | 101 | | |
91 | 102 | | |
| |||
125 | 136 | | |
126 | 137 | | |
127 | 138 | | |
128 | | - | |
| 139 | + | |
129 | 140 | | |
130 | 141 | | |
131 | 142 | | |
| |||
134 | 145 | | |
135 | 146 | | |
136 | 147 | | |
137 | | - | |
| 148 | + | |
138 | 149 | | |
139 | 150 | | |
140 | 151 | | |
141 | 152 | | |
142 | 153 | | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
143 | 185 | | |
144 | 186 | | |
145 | 187 | | |
| |||
233 | 275 | | |
234 | 276 | | |
235 | 277 | | |
236 | | - | |
| 278 | + | |
237 | 279 | | |
238 | 280 | | |
239 | 281 | | |
| |||
267 | 309 | | |
268 | 310 | | |
269 | 311 | | |
270 | | - | |
271 | | - | |
272 | | - | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
273 | 318 | | |
274 | 319 | | |
275 | 320 | | |
276 | 321 | | |
277 | 322 | | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
278 | 326 | | |
279 | 327 | | |
280 | 328 | | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | 329 | | |
288 | 330 | | |
289 | 331 | | |
| 332 | + | |
| 333 | + | |
290 | 334 | | |
291 | 335 | | |
292 | | - | |
| 336 | + | |
293 | 337 | | |
294 | | - | |
| 338 | + | |
295 | 339 | | |
| 340 | + | |
296 | 341 | | |
297 | | - | |
298 | 342 | | |
299 | 343 | | |
300 | 344 | | |
301 | 345 | | |
302 | 346 | | |
303 | 347 | | |
304 | | - | |
| 348 | + | |
305 | 349 | | |
306 | 350 | | |
307 | 351 | | |
308 | 352 | | |
309 | | - | |
| 353 | + | |
310 | 354 | | |
| 355 | + | |
311 | 356 | | |
312 | | - | |
313 | 357 | | |
314 | 358 | | |
315 | 359 | | |
| 360 | + | |
| 361 | + | |
316 | 362 | | |
317 | 363 | | |
318 | 364 | | |
319 | 365 | | |
320 | 366 | | |
321 | 367 | | |
322 | | - | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
323 | 431 | | |
324 | 432 | | |
325 | 433 | | |
| |||
340 | 448 | | |
341 | 449 | | |
342 | 450 | | |
343 | | - | |
344 | 451 | | |
345 | 452 | | |
346 | 453 | | |
347 | 454 | | |
348 | 455 | | |
349 | | - | |
| 456 | + | |
350 | 457 | | |
351 | | - | |
352 | | - | |
353 | 458 | | |
354 | 459 | | |
355 | 460 | | |
356 | 461 | | |
357 | | - | |
358 | | - | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
359 | 465 | | |
360 | 466 | | |
361 | 467 | | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
369 | 473 | | |
370 | 474 | | |
371 | 475 | | |
372 | 476 | | |
373 | 477 | | |
374 | | - | |
375 | | - | |
376 | | - | |
| 478 | + | |
377 | 479 | | |
378 | | - | |
| 480 | + | |
379 | 481 | | |
380 | 482 | | |
381 | 483 | | |
| |||
393 | 495 | | |
394 | 496 | | |
395 | 497 | | |
| 498 | + | |
396 | 499 | | |
397 | 500 | | |
398 | 501 | | |
399 | 502 | | |
400 | 503 | | |
401 | 504 | | |
402 | 505 | | |
| 506 | + | |
403 | 507 | | |
404 | 508 | | |
405 | 509 | | |
| |||
410 | 514 | | |
411 | 515 | | |
412 | 516 | | |
413 | | - | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
414 | 522 | | |
415 | 523 | | |
416 | 524 | | |
| |||
435 | 543 | | |
436 | 544 | | |
437 | 545 | | |
| 546 | + | |
438 | 547 | | |
439 | 548 | | |
440 | 549 | | |
| |||
0 commit comments