alloy-op-evm: don't rebate inner CREATE warming - #22098
Open
nonsense wants to merge 3 commits into
Open
Conversation
nonsense
force-pushed
the
ae/sdm/fm17-inner-create-warming-rebate
branch
from
July 29, 2026 10:30
1dabc40 to
2b62eb5
Compare
An inner (depth > 0) CREATE/CREATE2 claimed the 2500-gas SDM warm-account rebate for the address it created, even though the creating transaction never paid an EIP-2929 cold-account access for it: SDMWarmingInspector::create suppressed the rebate only `if top_level`. CREATE and CREATE2 are not EIP-2929-metered opcodes. The create path in revm-interpreter-41.0.0 (src/instructions/contract.rs:23-110) charges initcode_cost + create_cost/create2_cost + memory (+ EIP-8037 state gas) and never a cold-account-access surcharge, so there is no cold->warm delta to return at any depth. The rebate refunded a cost the EVM never levied, over-debiting the fee vaults on legitimate CREATE2 factory traffic. Insert the created address into intrinsic_warm_accounts unconditionally and keep the observe_account_touch call, so the address is still recorded in the block-warm set and a later tx that genuinely cold-accesses it still earns its rebate. The change only ever adds to the per-tx suppression set, so it cannot introduce an over-refund. Also correct the created_address memoization comment, which had the revm ordering backwards: inspect_frame_init dispatches Inspector::create through frame_start before calling frame_init, so this hook seeds the OnceCell and revm reuses our value rather than the reverse. The journal nonce read is load-bearing, not a fallback. The CreateScheme match arms are enumerated so a future nonce-dependent scheme cannot silently seed the cell with nonce 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…remes
Closes the max-input saturation gap the SDM FMA flags as NON-BLOCKING under
FM2. Nothing pinned that the saturating arithmetic in post_exec_settlement_deltas
cannot silently truncate a settlement leg and break value conservation under
the widest inputs a hostile producer can reach.
Sweeps base_fee in {0, 1, 1e9, u64::MAX} x refund in {1, 21k, u64::MAX/2,
u64::MAX} x effective_gas_price in {basefee, basefee+1, u128::MAX}, asserting
each leg against its exact closed form as well as the conservation identity
sender == beneficiary + base_fee + operator_fee. Checking the legs individually
matters: the identity alone still holds if two legs clamp by offsetting
amounts. All of them hold exactly, so no saturation engages — the widest
product is ~2^192, well inside U256.
Only effective_gas_price >= basefee is exercised: below-basefee txs never reach
settlement (revm rejects them with GasPriceLessThanBasefee upstream), which is
the precondition the beneficiary_gas_price saturating_sub relies on.
This is coverage only; no behavior change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nonsense
force-pushed
the
ae/sdm/fm17-inner-create-warming-rebate
branch
from
July 29, 2026 10:31
2b62eb5 to
5390fbe
Compare
nonsense
commented
Jul 29, 2026
nonsense
commented
Jul 29, 2026
nonsense
commented
Jul 29, 2026
nonsense
marked this pull request as ready for review
July 29, 2026 14:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Inner
CREATE/CREATE2operations could claim a 2,500-gas SDM warm-account rebate for the created address. These opcodes warm that address but do not pay EIP-2929's cold-account surcharge, so there is no cold-to-warm delta to refund.The excess refund over-debited fee vaults. Verifiers apply the producer's refund rather than recomputing it, so affected blocks remained valid.
Fix
Mark created addresses as non-refundable at every depth while still recording them in the block-warm set. A later transaction that genuinely cold-accesses the address can therefore still claim its rebate.
The same hook seeds revm's cached created address before frame initialization. Its comment now reflects that ordering, missing creator state fails closed, and
CreateSchemevariants are matched explicitly.Tests
CREATE2over-refund.cargo nextest run -p alloy-op-evm: 82 passedcargo clippy -p alloy-op-evm --all-features --all-targets -- -D warnings: cleanKnown limitation
Per-transaction warming sets are not journal-revert-aware. A reverted inner create can therefore suppress a later valid rebate in the same transaction. This is an under-refund and is left for a separate change.
Companion PR
ethereum-optimism/optimism-premium#98 applies the same fix to
BlockWarmingPolicy. The premium repository's monorepo pin is unchanged; this PR lands first.