Repository navigation
fix(evm): close evm2 parity gaps for Ethereum and Tempo - #17740
Merged
Merged
Conversation
The master merge ported most of #17719 but missed two spots: eth_call still lifted the tx gas limit cap under Amsterdam, and a memory reset rebuilt the cfg without set_cfg_spec. Both dropped the EIP-8037 state gas reservoir. Restore the four master tests the merge dropped from Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com> #17716, #17719 and #17731.
evm2 now starts isolated calls at the initial call depth (OSS-1191), so the isolate-dependent depth from master holds again. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Port #17732 to evm2. Cheatcodes now get a gas tracker that is returned to the caller, and deployCode charges it as the CREATE and CREATE2 opcodes do: create and EIP-3860 initcode costs with the initcode size limit, EIP-8037 create state gas for an empty destination, 63/64 forwarding, and the create frame's unused gas and reservoir. Isolated snapshot corrections apply at the cheatcode caller's depth. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Master returns every Tempo transaction validation error as an internal error prefixed with 'tempo transaction error', not only the value transfer one. Restore that mapping and master's cast assertion.
Master isolates depth-1 calls and creates as nested transactions whose kind replaces the test transaction's, so its missing-contract revert diagnostic compares against the isolated call's target and is skipped inside an isolated create. evm2 nested transactions have no kind, so the cheatcodes only knew the root call target and diagnosed calls made from constructors. Track the isolated transaction's target instead. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
The evm2 lifecycle resumed a selected or rolled fork with only the base warm set, so accounts and slots the running transaction had warmed paid cold costs again. Port REVM's per-fork journal warmth: a selected fork resumes with the warmth it had earlier in the transaction plus the persistent accounts', a rolled fork warms every account the transaction loaded (with slots for persistent and created ones), and isolated calls that switch forks keep the outer transaction's warmth. Isolation cooling before static calls still cools carried warmth. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
As on master, a state snapshot restores only the context that was active when it was taken, together with the environment, journal and active fork selection. Other forks keep the writes made on them after the snapshot, so a revert from another fork first parks the running state in its own context. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Tempo's handler increments a 2D nonce, emitting the NonceManager event, while it validates the transaction, before the root frame starts. evm2 reports that log to the inspectors, and the tracer, which has no call to attach it to yet, panicked. As on master, where REVM only reports logs of running frames, the tracer now only sees logs while the root frame runs; the transaction still records the log. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
When revertToState runs while another fork than the snapshot's is active, master replaces the running journal without storing it back, so that fork keeps only what reached its fork database. Do the same instead of parking the running transaction's changes in the fork's context. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
deployCode charges its caller the EIP-8037 account-creation state gas before running the create frame, but an isolated synthetic create did not pass that charge to the nested transaction, which charged it again. As master does with charged_create_state_gas, carry the charge into the synthetic create so the nested transaction credits it. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
When an isolated call switches forks, master replaces the running transaction's state with the nested transaction's, so the running transaction's own warmth does not survive and the nested transaction's does only if it succeeds. The stack instead reinstated the outer warmth even when the call reverted, which made selecting the original fork back 4500 gas cheaper than on master in Fork2.t.sol. Keep the nested transaction's warmth, captured when its root frame succeeds, and none from the running transaction. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
A context that resumed with warmth from earlier in the transaction holds it in the state's prewarm set, not in loaded accounts, so suspending it again without touching that warmth dropped it: switching A, B, A, B, A turned a warm non-persistent account or slot cold. Keep the warmth a context resumed with when it is suspended again, as master's per-fork journals do. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Keeping a context's restored warmth across suspensions also handed it to the next fork as the warmth of persistent accounts, which made an account created by an isolated CREATE and then made persistent warm on the other fork, 2500 gas below master in Fork2's testMarkPersistent. Persistent accounts again carry only the warmth the suspended visit touched; the context itself still keeps its restored warmth. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
An isolated call that switches forks and then reverts left the slots it had accessed before switching cold, because only a successful call's warmth is installed. As on master, where the switch moved those slots into the new fork's journal beyond the reach of the revert, they now stay warm while the call's accounts stay cold. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
When a deployCode constructor returned code that could not be deposited, for example because too little gas was left for the code deposit, evm2 drops the returned output and the cheatcode reverted with no data. As on master, where REVM kept the output, the cheatcode now reverts with the code the constructor returned. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
An isolated deployCode runs its create as the root of a nested transaction, where master reports a failed code deposit with no revert data. The returned-code fallback applied there too and reverted with the constructor's code. It now applies only when the create did not start its own isolated transaction. Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a16369-8789-707c-b8fe-668c73ac7ed1 Co-authored-by: Amp <amp@ampcode.com>
mablr
marked this pull request as ready for review
October 22, 2026 16:31
mablr
requested review from
0xrusowsky,
DaniPopes,
figtracer,
grandizzy,
mattsse and
stevencartavia
as code owners
October 22, 2026 16:31
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.
Stacked on #17541. Restores master behavior on master's own Ethereum and Tempo tests where the evm2 migration had drifted, without changing master's assertions.
It restores the four anvil tests the master merge dropped (#17716, #17719, #17731) and the two #17719 changes they exposed:
eth_callunder Amsterdam keeps the transaction gas cap, and a memory reset keeps the EIP-8037 state gas reservoir. The storage hook depth test gets master'svm.isIsolateMode() ? 1024 : 1023back.deployCodecharges its caller as in #17732, with CREATE/CREATE2, initcode and EIP-8037 state gas charged once even when isolated, and reverts with the constructor's code on a failed code deposit, except as the root of an isolated transaction. Anvil reports Tempo validation errors as-32603, and the fork revert diagnostic compares against the isolated transaction's target again.On the lifecycle side, fork switches, rolls and isolated fork-switching calls keep warmth as REVM's per-fork journals did, so
Fork2.t.solgas now matches a master build in both isolation modes. Snapshots capture and revert only the fork active when they were taken, and tracing a Tempo AA transaction no longer panics on the nonce log emitted before the root frame. The remaining warmth differences are listed as known gaps indocs/dev/evm2-migration.md.Closes OSS-1192. Refs OSS-1155, OSS-1157, OSS-1158 (only the Tempo trace panic; step semantics remain open) and OSS-1180.