Skip to content

chore: upgrade to revm 40.0.3 / alloy-evm 0.36.0 - #365

Open
RealiCZ wants to merge 57 commits into
mainfrom
cz/chore/upgrade-revm-40
Open

RealiCZ wants to merge 57 commits into
mainfrom
cz/chore/upgrade-revm-40

Conversation

@RealiCZ

@RealiCZ RealiCZ commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Upgrades the workspace from revm 27 to revm 40.0.3, with op-revm / alloy-op-evm pinned to the Optimism monorepo revision wired to reth v2.3.0, and alloy-evm 0.36.0.
  • revm 40 reworked interpreter and handler internals underneath the frozen MegaETH specs; this PR re-pins the frozen semantics so observable behavior stays identical for every existing spec.
  • Includes one semantic fix surfaced while rebasing onto the cross-spec compute-gas suite (docs: specify compute gas accounting and pin it with a cross-spec test harness #358): Rex6 CALL-family first-touch pricing of preload-warm addresses (second commit).

Frozen-semantics re-pinning

  • Static-gas pre-charge: revm 40's step() deducts static gas from a per-spec gas table before the handler runs. Volatile-guarded opcodes get zeroed table entries and charge inside the wrapper at the revm-27-equivalent position; all other opcodes add the pre-charge back into the compute-gas measuring window (STATIC_GAS_TABLE).
  • Halt handling: limit-triggered halts go through set_halt_action!, which preserves remaining gas for sender refund instead of revm 40's spend_all-on-OOG and explicitly replaces pending frame actions.
  • Host entry points: the oracle SLOAD customizations (env override, forced-cold pricing, access marking) moved into sload_skip_cold_load; resident journal entries keep their own cold pricing; access-list warming only applies to entries with storage keys; CALL-family account loads distinguish the raw operand from its EIP-7702 delegate.
  • System calls: pre-REX5 system calls keep the 30M gas limit via PRE_REX5_SYSTEM_CALL_GAS_LIMIT (the upstream constant drifted to 30M + EIP-8037 reservoir) and continue to skip post_execution.
  • Precompiles: error paths normalize spent gas back to zero; the KZG fixed-rate compute-gas branch keys on bytecode_address.
  • CfgEnv: spec changes go through set_spec_and_mainnet_gas_params so GasParams follow the spec; tx_chain_id_check keeps its revm-27 default for untouched configurations (with_cfg_unpinned opts out); EIP-8037 is pinned off in every conversion.
  • Block executor: commit_transaction failures are latched and surfaced in finish(); state hooks moved onto revm's State; results carry tx_type instead of a cloned envelope.

Rex6 fix (second commit)

Before revm 40, the CALL-family host entry resolved the raw operand's EIP-7702 delegate before loading it, and that resolution materialized the operand's journal entry (cold, code hydrated) as a side effect, so a Rex6 first touch of a preload-warm address (precompile, coinbase, address-only access-list entry) was priced cold.
revm 40 resolves the delegate inside the CALL instruction; the migration's phase-based marking lost the materialization side effect, pricing such first touches warm — 2,500 gas below frozen Rex6 behavior in both EVM gas and compute gas.
The fix reproduces the materialization in load_account_info_skip_cold_load for Rex6 CALL-family raw-operand loads.
Caught by test_callcode_cold_first_touch_follows_the_spec_arc from #358.

Accepted deviation: the frozen detention window (debug-tripwired)

  • revm 27 loaded a CALL-family (and EXTCODECOPY) target before charging the opcode's own costs, so a frame that ran out of gas on those charges had already marked beneficiary access and the rest of the transaction ran detained; revm 40 charges first, so the same frame halts unmarked and the rest of the transaction runs undetained.
  • The halting frame itself is byte-identical either way — out-of-gas consumes the frame's remaining gas, the load rolls back with the frame, no logs — so the divergence is exactly the tracker mark and the detention cap it would have set for the rest of the transaction.
  • Normal traffic cannot sit in the window (a frame holding under 100 gas — under 9,100 with value — still calling the beneficiary), but sampling is not the guarantee: the release gate is a full-history replay run with debug assertions enabled.
  • This branch ships a debug-build tripwire (debug_check_frozen_detention_window) on every plain out-of-gas exit of the guarded wrappers: it fires exactly when a halt leaves the beneficiary — or, from REX6, its one-hop delegate — unmarked where revm 27 marked it. Release builds compile it out (verified absent from the release rlib; CodSpeed should report zero delta).
  • If replay ever trips it, the wrapper backfill archived in the migration notes restores the revm-27 marking exactly; until then the revm 40 order is the accepted behavior. Known blind spot: pre-REX4 CALL frames die in step()'s table pre-charge before any wrapper runs, so that era is covered by the replay gate alone.
  • Writing the tripwire tests surfaced and fixed one spec-doc error: gas-detention.md listed EXTCODECOPY among the opcodes that register volatile access before charging; its copy cost is charged before the load, so it belongs with the CALL family on the excluded side.
  • Gate executed (2026-08-10→17): zero tripwire hits across all of mainnet history. All Rex4+ blocks (13,862,189→23,718,840, ~270M txs) replayed in full, and the pre-REX4 era (blocks 1→13,862,188) — including the blind-spot window noted above — replayed in full except a ~11B-tx homogeneous swap-spam region covered by ~1.2B txs of full chunks plus spatial slice samples, with debug_assertions + overflow_checks armed throughout. The revm-40 charge order is confirmed as the accepted behavior; the archived wrapper backfill remains unused.

Output format changes (no execution change)

  • revm-inspectors 0.27 → 0.40 changes struct-log serialization: every log now carries "refund": 0 and memory words gain a 0x prefix. Gas and gasCost values in the trace fixtures are byte-identical to main — execution did not move, serialization did. Anyone diffing mega-evme run --trace output against archived traces (or geth) will see the field-level drift.

Verification

  • cargo test --workspace: 1,468 passed / 0 failed (includes the EEST state-test suite, the replay corpus, and the cross-spec compute-gas snapshot suite from docs: specify compute gas accounting and pin it with a cross-spec test harness #358).
  • Mainnet replay hard gate (2026-08-10→17): all Rex4+ history (~270M txs) plus the pre-REX4 era re-executed against on-chain receipts (status, gasUsed, logs). Every observed divergence was mechanically attributed — an EIP-7702 fresh-authority refund artifact of the RPC replay tooling (since fixed by mega-evme 36081e7) and the halt-receipt log leak this gate caught (fixed in this PR, 7156d05) — and a 92/92-chunk re-verification with both fixes confirmed zero remaining divergence.
  • cargo clippy with -D warnings, cargo fmt --check, cargo sort --check, and the riscv64imac-unknown-none-elf no_std check all pass.

Status

Marked [WIP]: a manual semantics review of the migration is still in progress; no further code changes are expected unless the review finds issues.

RealiCZ added 2 commits August 4, 2026 11:02
Upgrade the workspace from revm 27 to revm 40.0.3, with op-revm and
alloy-op-evm pinned to the Optimism monorepo revision wired to reth
v2.3.0.

revm 40 reworked several interpreter and handler internals that MegaETH's
frozen specs depend on. This change adapts the integration so that the
observable semantics of all existing specs stay identical:

- Static-gas pre-charge: step() now deducts each opcode's static gas from
  a per-spec gas table before the handler runs. Volatile-guarded opcodes
  get zeroed table entries and charge inside the wrapper at the revm-27
  equivalent position; all other opcodes add the pre-charge back into the
  compute-gas measuring window (STATIC_GAS_TABLE).
- Halt handling: limit-triggered halts go through set_halt_action!, which
  preserves remaining gas for sender refund instead of revm 40's
  spend_all-on-OOG, and explicitly replaces pending frame actions.
- Host entry points: the oracle SLOAD customizations (env override,
  forced-cold pricing, access marking) moved into sload_skip_cold_load;
  resident journal entries keep their own cold pricing; access-list
  warming only applies to entries with storage keys; CALL-family account
  loads distinguish the raw operand from its EIP-7702 delegate.
- System calls: pre-REX5 system calls keep the 30M gas limit via
  PRE_REX5_SYSTEM_CALL_GAS_LIMIT (the upstream constant drifted to
  30M + EIP-8037 reservoir) and continue to skip post_execution.
- Precompiles: error paths normalize spent gas back to zero; the KZG
  fixed-rate compute-gas branch keys on bytecode_address.
- CfgEnv: spec changes go through set_spec_and_mainnet_gas_params so
  GasParams follow the spec; tx_chain_id_check keeps its revm-27 default
  for untouched configurations (with_cfg_unpinned opts out); EIP-8037 is
  pinned off in every conversion.
- Block executor: commit_transaction failures are latched and surfaced in
  finish(); state hooks moved onto revm's State; results carry tx_type
  instead of a cloned envelope.

Verified with the full workspace test suite, the EEST state tests, the
replay corpus, and a mainnet replay of 1,222 transactions matching
on-chain receipts.
…-warm addresses

The pre-revm-40 CALL-family host entry resolved the raw operand's
EIP-7702 delegate before loading it, and that resolution materialized
the operand's journal entry (cold, code hydrated) as a side effect. The
subsequent inherited load then hit the resident branch and kept the
entry's own coldness, so a Rex6 first touch of an address whose warmth
exists only as a preload (a precompile, the coinbase, or an address-only
access-list entry) was priced cold.

revm 40 resolves the delegate inside the CALL instruction, so the
migration replaced the ahead-of-load resolution with phase-based marking
of revm's own loads — losing the materialization side effect: the first
load saw a fresh entry, honored the pre-warmed sets, and priced warm,
2,500 gas below the frozen Rex6 behavior in both EVM gas and compute
gas.

Reproduce the materialization in load_account_info_skip_cold_load for a
Rex6 CALL-family raw-operand load, before the resident-coldness read.
Caught by the cross-spec compute-gas suite's CALLCODE spec-arc test.
@RealiCZ RealiCZ added spec:stable Touches stable spec code — must not change behavior api:breaking Crate interface change — downstream users must update comp:mega-evme Changes to the `mega-evme` tool comp:core Changes to the `mega-evm` core crate labels Aug 4, 2026
@mega-maxwell

mega-maxwell Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Claude review status

Living comment — rewritten in place. The review workflow keeps this single comment up to date instead of posting a new one each round, so it always describes the latest reviewed commit and the earlier text is intentionally gone. No reply is needed here; reply to a finding in its own review thread, and answer an open question in a reply on this PR. The next review round reconciles your answer.

✅ Review clean

Last reviewed: c1de1a73..e72c6eb4 · updated 2026-08-06T07:47:11+00:00

New this round: 0 finding(s), 0 question(s) · Resolved this round: 0 · Open questions: 0

Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
Comment thread crates/mega-evm/tests/block_executor/block_limits.rs Dismissed
@RealiCZ RealiCZ added comp:misc Changes to the miscellaneous part of this repo dependencies Pull requests that update a dependency file comp:doc Changes in the documentation labels Aug 4, 2026
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

@codspeed

codspeed Bot commented Aug 4, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 2.1%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 88 improved benchmarks
❌ 83 (👁 83) regressed benchmarks
✅ 214 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
rex4/50_txs 2.8 ms 1.7 ms +60.47%
rex5/50_txs 2.8 ms 1.8 ms +59.4%
rex4/10_txs 689.4 µs 493.5 µs +39.7%
op_revm_pinned 2.9 ms 2.1 ms +39.19%
rex5/10_txs 719.9 µs 523.1 µs +37.61%
op_revm_pinned 1.5 ms 1.1 ms +36.62%
revm_pinned 2.8 ms 2.1 ms +36.09%
op_revm_pinned 5.5 ms 4.1 ms +33.39%
revm_pinned 1.5 ms 1.1 ms +33.32%
revm_pinned 1,162.4 µs 890.9 µs +30.47%
op_revm_pinned 1,170.6 µs 900.1 µs +30.05%
mini_rex/5_mixed_txs 497.6 µs 394.5 µs +26.13%
equivalence 3.3 ms 2.6 ms +25.83%
rex4/10_txs 1,220.7 µs 978.3 µs +24.78%
rex5/10_txs 1,247.1 µs 999.8 µs +24.74%
equivalence 6.2 ms 5 ms +24.43%
equivalence 1.7 ms 1.4 ms +23.84%
revm_pinned 3.4 ms 2.8 ms +22.58%
mini_rex/sstore_sload_100 384.3 µs 314.6 µs +22.15%
equivalence 1.4 ms 1.1 ms +21.44%
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing cz/chore/upgrade-revm-40 (0072855) with main (a39bd1e)

Open in CodSpeed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88c6b0439d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mega-evm/src/evm/context.rs Outdated
Comment thread crates/mega-evm/src/evm/mod.rs
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🧬 Mutation testing — ✅ PASS

Diff mutation score: 100.0% (19/19 viable mutants killed)

  • caught: 19
  • survived (real gaps): 0
  • timed out (inconclusive): 0
  • suppressed (equivalent/dead-code): 1
  • unviable: 0 · timeout total: 0

No new test gaps introduced by this change. 🎉

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🧬 Mutation testing — ✅ PASS

Diff mutation score: 100.0% (100/100 viable mutants killed)

  • caught: 100
  • survived (real gaps): 0
  • timed out (inconclusive): 0
  • suppressed (equivalent/dead-code): 1
  • unviable: 243 · timeout total: 0

No new test gaps introduced by this change. 🎉

@flyq flyq left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review summary

Verdict: not mergeable yet — one frozen-spec blocker (modexp) and two silently-accepted frozen-spec drifts that need explicit sign-off — but the migration's foundation is excellent and the hard parts are done right. Everything below was verified against both upstream trees (revm-interpreter 24↔37, revm-handler 8↔20, revm-context 8↔18, revm-precompile 25↔36, revm-state/database 7↔12/15, op-revm 8.1.0 ↔ the pinned git 20.0.0), not just by reading this repo.

Mechanisms verified as faithful re-pins: the zeroed static-gas entries equal the volatile-guarded set exactly per spec, and the add-back arithmetic reproduces revm-27 compute-gas totals with no double-count on any wrapper; set_halt_action! preserves remaining gas (vs revm 40's spend-all-on-OOG) through to try_rescue_gas on all six limit-halt sites, and both interpreter loops skip the fallback halt when an action is set; the three gas-leakage paths and the resource-limit latch protocol survive the handler rework; PRE_REX5_SYSTEM_CALL_GAS_LIMIT correctly freezes 30M against upstream's drift to 31,566,720, and run_system_call still skips validate/pre/post_execution; precompile error paths restore revm-27's no-spend halt shape and bytecode_address keying reproduces revm-27 dispatch (CALLCODE/DELEGATECALL-to-KZG identical); EIP-8037 is pinned off at every conversion, normalized before the untouched-default classification; the block executor's receipt assembly, state-hook-before-apply ordering, pre-block sequence, and interception contract are byte-equal or provably equivalent; and the resident-entry cold-pricing compensation (resident_entry_prices_cold + access_list_preloads_account) faithfully restores revm-27 journal pricing across the full warm/cold matrix — upstream's occupied path now consults the warm sets, and the new rex/precompile_access_coldness.rs + rex/access_list_resident_warming.rs files are what hold that compensation in place. The Rex6 fix commit (88c6b04) is correct on scope (CALL-family RawOperand bracket only, REX6+ only — pre-REX6 never depended on the side effect, and CALLCODE inspecting the caller instead of the target is exactly why the drift surfaced on the CALLCODE spec-arc), idempotency, delegate pricing, and EVM-gas/compute-gas symmetry.

The test migration deserves its own call-out: zero pre-existing expectations changed. A token-level sweep of the full ~8k-line tests diff found no lost constant and no deleted test (958→1020, removals = ∅), every assertion edit is a value-identical API reshape (each verified against the upstream definitions, e.g. gas_used()tx_gas_used()), and the #358 compute-gas suite + snapshot are byte-identical to main — the source was fixed to match unchanged pins, which is the right direction.

Blocking / decision items are inline comments: the unwrapped modexp OSAKA reorder (blocker, cheap wrapper fix), the CALL-family under-funded-frame detention-mark loss (accepted in a code comment + doc but undisclosed in the PR body — needs sign-off and a replay-corpus scan), the disabled-SELFDESTRUCT halt-reason drift (cheap table fix), and the tx_chain_id_check production-path default (overlaps the open codex P1).

CI notes: the spec-gate survivor is an equivalent mutant — see the inline comment at host.rs:425; a justified mutants/suppressions.toml entry is the honest fix. CodSpeed: the −20% on revm_pinned/op_revm_pinned measures the upstream 27→40 jump itself — those "control lanes" changed meaning in this one PR, while .github/scripts/bench_compare.py:278-281 still documents them as immutable and still lists the deleted revm_latest/op_revm_latest rows (:410); the number to actually track across this PR is the mega-vs-pinned overhead ratio. Non-anchorable minor: dual alloy-eip7928 (0.3.7 via alloy-eips, 0.4.5 via revm-state) in the lockfile — dormant pre-Amsterdam, but it is the one gap in the manifest comment's "single source identity" promise.

Since the PR is [WIP] pending your own semantics review: the per-mechanism list above is exactly what that review would re-derive — suggest spending the remaining effort on the corners still unaudited here: a line-diff of the remaining eth precompiles across revm-precompile 25→36 (the modexp reorder proves upstream slips semantic changes into these files), and FromRecoveredTx/FromTxWithEncoded field-by-field parity.

Merge-order: land #362 first — this PR does not touch spec.rs, and a dry-run cross-merge conflicts only on executor.rs + instructions.rs, so the cheaper rebase is on this side.

🤖 Generated with Claude Code

Comment thread crates/mega-evm/src/evm/precompiles.rs
Comment thread crates/mega-evm/src/evm/instructions.rs
Comment thread crates/mega-evm/src/evm/instructions.rs
Comment thread crates/mega-evm/src/evm/context.rs Outdated
Comment thread crates/mega-evm/src/evm/host.rs
Comment thread docs/spec/evm/gas-detention.md Outdated
Comment thread crates/mega-evm/src/block/eips.rs Outdated
Comment thread crates/mega-evm/src/evm/context.rs
false
}

fn as_invalid_tx_err(&self) -> Option<&InvalidTransaction> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[minor — needs a mega-reth-side test] Returning None here (and in the second impl below) is defensible — there is genuinely no InvalidTransaction counterpart for a Mega limit rejection — but these impls exist purely for reth's error classification and have zero in-repo callers (they are also this file's codecov-0% lines). If any reth path treats None as "internal error → abort payload building" rather than "drop this tx", a Mega limit rejection gets misclassified, and nothing in this repo would catch it. Worth one integration test on the mega-reth side pinning the intended classification.

Comment thread bin/mega-evme/tests/fixtures/test_run_trace_inline.json
The KZG fixed-cost compute-gas arm keys on bytecode_address — the address
revm dispatches precompiles by — which diverges from target_address under
DELEGATECALL and CALLCODE. The existing suite only exercised CALL, where
the two coincide, leaving the dispatch-address choice untested.

Add exact-value differential tests for both schemes. The CALLCODE variant
access-lists the precompile with a storage key so it loads warm on both
specs: REX4's CALLCODE wrapper pre-inspects the call target (cold
materialization, +2,500) while REX5's inspects the executing account, and
that unrelated arc would otherwise pollute the REX4/REX5 differential.

Also refresh a stale comment on the 30M system-call gas-limit test: since
the default entry overrides upstream's drifted constant, the literal
assertion pins MegaETH's own value, not the upstream default.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7ced8add7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/spec/evm/gas-detention.md Outdated
Comment thread Cargo.toml
Comment thread crates/mega-evm/src/evm/instructions.rs
RealiCZ added 5 commits August 4, 2026 17:25
…opt EIP-7883 in Rex7

MINI_REX adopted the Osaka / EIP-7883 ModExp schedule through the revm
implementation current at the time, which short-circuited
zero-base/zero-modulus inputs to the 500-gas minimum before computing
the formula cost. revm 40's implementation computes and charges the full
formula cost for those inputs, as the EIP text specifies (its
multiplication complexity floors at 16), and additionally halts with
PrecompileOOG when the forwarded gas covers the minimum but not the
formula cost — a receipt-level divergence on every frozen spec that
installs the Osaka schedule.

Pin the frozen specs (MINI_REX through REX6) to the historical
short-circuit with a wrapper that reproduces the old check order —
minimum gas, header parse, EIP-7823 size limits, then the short-circuit
— and defers every other input to the upstream implementation. REX7
installs upstream's implementation unwrapped, deliberately adopting the
EIP-faithful schedule as its first recorded behavior change, documented
on the Rex7 upgrade page.

EQUIVALENCE (inherited Berlin schedule) is structurally unaffected: the
Berlin formula collapses to its flat minimum for these inputs under
either ordering.

Reported in review by flyq.
… snapshot and publish blocker

Review follow-ups without behavior change:

- gas-detention.md overpromised that a halting frame's volatile access
  applies detention immediately. The frozen behavior (identical before
  and after the migration: the wrapper's cap application is skipped when
  the opcode body halts) is that the registration survives and the
  reduced cap binds at the transaction's next volatile-guarded opcode.
  State the enforcement-point semantics, switch "performs the read" to
  "registers the access" (the oracle path can bail before the actual
  load), and make the CALL-family exclusion explicit instead of implied
  by the opcode list.
- MegaEvm::mega_cfg is a construction-time snapshot; document that
  mutating the context configuration through the mutable deref desyncs
  it and that reconfiguration means rebuilding the EVM.
- The OP-family git pins reject `cargo publish`, blocking the release
  publish workflow until upstream ships revm-40-compatible registry
  releases; note it where the pins are declared.
…ity entry points

revm 40 flipped the CfgEnv::tx_chain_id_check default from false to
true. The migration first answered with a default-shape inference:
with_cfg pinned the revm-27 false back only for a configuration that was
field-for-field CfgEnv::new_with_spec, and took every configured one at
face value. Both review rounds flagged the same cliff: every production
embedder configures at least a chain id, so the face-value branch is the
one production hits, and the same embedder source that ran without the
gate on revm 27 silently inherits it after the upgrade.

Make the contract explicit instead of inferred: with_cfg and the
deprecated new_with_context pin the gate off unconditionally — they are
the compatibility entry points, and every frozen MegaETH spec ran
without the gate — while with_cfg_unpinned takes the field as provided
for embedders that enable it on purpose. The default-shape inference and
its is_untouched_revm_default_cfg helper are gone.

Also pin EIP-8037 off in new_with_shared_ext_envs, aligning the one
construction path that relied on the upstream default staying
pre-Amsterdam.

The REX5 system-tx guard tests opt into the gate deliberately; they now
re-apply it on the live context after the factory pin. A new factory
test pins the production path: a configured EvmEnv comes out of
create_evm with the gate off.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2076c8e310

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mega-evm/src/evm/instructions.rs
Comment thread tools/mutation/mutate.py Outdated
Comment thread crates/mega-evm/src/evm/host.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7027c5c2cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/mutation/mutate.py Outdated
RealiCZ added 9 commits August 8, 2026 14:15
Each oracle `cargo test` call now runs under a wall-clock ceiling. Without
one, a mutant that makes the tested path or a test loop forever hangs the
whole campaign: no result, no state progress, no journal recovery, and a
manual kill can land while the product file is still mutated.

- `--test-timeout SECONDS` overrides the ceiling; the default is derived per
  layer from the clean-tree baseline as max(300s, ceil(5 x layer baseline)),
  falling back to an absolute 1800s when no baseline wall time exists.
- On expiry the child's whole process group is killed (SIGTERM, 10s grace,
  SIGKILL) so cargo's rustc and test binaries cannot orphan onto the
  `target/` lock.
- The timeout path goes through the normal journal compare-and-restore and
  the post-restore cleanliness assert.
- The result is recorded as killed with kill_kind=timeout / timed_out /
  timeout_s (additive state fields); the report counts timeouts separately
  from assertion kills so an over-tight threshold stays visible.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b2cffd313b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mega-state-test/src/types/test_unit.rs Outdated
The gate's 20 timed-out mutants were not non-terminating: every one is detected,
but only by tests at the end of nextest's global queue, and the per-mutant test
ceiling (3x a baseline measured with the suite running alone) is smaller than the
same suite needs when `--jobs $(nproc)` siblings compete for the cores. The runs
were cut off mid-queue and reported as inconclusive.

- Pin the legacy Osaka ModExp check order and boundaries with unit tests in the
  lib target, which runs before every integration binary: minimum-gas boundary,
  each EIP-7823 length limit at and above its edge, and the zero-base/zero-modulus
  flat charge. These kill 15 of the 16 ModExp mutants within the run's first
  seconds, eight of which no test covered at all.
- Suppress the one equivalent mutant (precompiles.rs:135:49): weakening the first
  `||` only defers to upstream `osaka_run`, whose EIP-7823 check returns the
  identical halt.
- Size the timeout ceiling for the contended run so a late-queue kill is reported
  as caught rather than as a timeout, and document the failure mode.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2fe0ec4dea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/mega-evm/src/evm/host.rs
Comment thread crates/mega-evm/src/evm/host.rs
RealiCZ added 2 commits August 9, 2026 08:06
The Specification section stated the KZG and ModExp overrides without a
lower-bound declaration, silently claiming Equivalence; the code installs
them only from MiniRex.
Nothing produces the field: the local corpus never used it, current EEST
does not emit it, and it never landed in geth (EIP-7742 was withdrawn);
upstream revm's statetest Env has since removed its parent-target field
as well. Its raw gas-unit interpretation also contradicted the count the
name promises. Excess blob gas derivation now always uses the Cancun
target, and deny_unknown_fields rejects any fixture still carrying the
field instead of silently misreading it.
@RealiCZ RealiCZ changed the title [WIP] chore: upgrade to revm 40.0.3 / alloy-evm 0.36.0 chore: upgrade to revm 40.0.3 / alloy-evm 0.36.0 Aug 10, 2026
@RealiCZ
RealiCZ requested a review from flyq August 10, 2026 01:53
revm 40 moved the log list onto every ExecutionResult variant and fills it from
the journal, so "a failed transaction's receipt carries no logs" is no longer
guaranteed by the type. MegaETH rewrites an already-committed frame result into
a failure at two sites — most visibly the pre-REX5 CREATE code-deposit charge in
after_frame_run, which runs once the constructor's checkpoint is committed — and
those committed logs then reached the receipt, changing the receipts root
against on-chain history.

Clear them at execution_result, the seam every entry point converges on, so all
consumers inherit it. status, gasUsed and the post-state are unchanged.

Tests cover the REX post-commit halt, the REX4 frame-local revert rewrite, and
the REX5 pre-charge that keeps the exceed ahead of the commit.
Several comments explained an empty log list by saying revm had already rolled
the failed frame's logs back. That is false wherever a successful frame's result
is rewritten into a failure after its checkpoint was committed: revm committed
the frame and never sees the failure, so the logs survive until the transaction
result is finalized.
The log strip at the transaction result seam is unconditional only because
EIP-7708 is off: once it is active, logs are emitted outside every frame
checkpoint and a failed transaction carries them legitimately. Nothing said so,
which is the same defect this change set went and corrected elsewhere.

Name the dependency at the strip, and list at the spec-mapping test what
advancing the mapping would break — EIP-7708 here, and the EIP-7825 gas-limit
cap that would reject every system call.
The note added with the strip explained it by EIP-7708, which is not the
reason. Upstream added the log fields deliberately, to hand back logs emitted
before a failure that had been discarded until then, and marked the change
breaking.

Say what actually holds instead, and say it as a measurement rather than a
derivation: under Prague an ordinary revert and an ordinary halt both arrive
with an empty list, because the frame's checkpoint revert emptied the journal
long before the result was assembled; the one upstream path that survives a
revert is a failing precompile's logs, and no MegaETH precompile emits any. So
the only thing left to drop is what a post-commit rewrite stranded.

Record both ways that measurement can go stale — a spec mapped past Prague, or
a MegaETH precompile that emits logs — so the next reader re-measures instead
of trusting the conclusion.
@vincent-k2026

Copy link
Copy Markdown
Contributor

Reviewed as a targeted pass over the highest-risk seams (STATIC_GAS_TABLE / charge_static_gas!, set_halt_action!, the block-executor latch), not line-by-line across all 195 files. Flagging that up front so the depth of this review isn't overstated.

Genuinely good:

  • The release gate is real work. Full-history replay 2026-08-10→17, all Rex4+ (~270M txs) plus the pre-REX4 era, debug_assertions + overflow_checks armed throughout, zero tripwire hits. Guarding an accepted frozen-semantics deviation with a debug-only tripwire and then disproving it against the whole chain is the right shape — and the blind spot (pre-REX4 CALL frames die in step()'s table pre-charge before any wrapper runs) is called out by you rather than found by a reviewer.
  • set_halt_action! (instructions.rs:550-566) not using revm's halt is correctly argued: halt does spend_all on OutOfGas, which would burn gas MegaETH refunds to the sender, and it refuses to set an action while one is pending, whereas a limit abort right after a CALL/CREATE published its child NewFrame has to replace it. Both differences are named, and the comment explains why rather than what.
  • test_static_gas_table_is_spec_invariant (instructions.rs:3014) walks ALL_SPECS and asserts each builds the same table — a real drift test that goes red if a spec ever remaps its eth spec.

Blocking

1. The body says "Marked [WIP]: a manual semantics review of the migration is still in progress", but the title carries no WIP, the PR is not a draft, and it is MERGEABLE. megaeth-labs/stateless-validator#184 is blocked on this getting a tag, so the tag is the unlock condition for downstream repos — it shouldn't happen while the semantics review is open. Please align title/draft state with the body and state the completion condition for that review.

Should fix

2. MegaBlockExecutor::receipts is pub, and its correctness depends on the caller checking pending_commit_error first. Your own doc comment at block/executor.rs:64-72 writes the failure mode down:

"A caller harvesting this field (or the equivalent trait accessor) directly must consult pending_commit_error first, or let finish() fail the block; otherwise a rejected transaction silently vanishes from the block it believes it built."

Documenting it is good; leaving the latch enforceable only by that comment is not. Anywhere in mega-reth that reads receipts directly gets a block missing a transaction with no error anywhere. Structural fix: drop receipts to pub(crate) and expose fn receipts(&self) -> Result<&[R::Receipt], &BlockExecutionError> so the latch can't be bypassed.

3. Ordering note for #347. Once static gas moves into step()'s table pre-charge, any hand-inlined instruction body that keeps gas!(..., gas::VERYLOW) in the body double-charges silently. #347 currently has three of those (add, pop, push1). If it is kept, it has to land after this PR and be re-derived on top of it — details in my comment there.

Brings in #362 (single-source hardfork spec resolution). Conflicts were
resolved by keeping the revm 40 API shapes and adding the alias spec
rungs on top:

- instruction and static gas table construction groups MINI_REX_1 and
  MINI_REX_2 with their behavior targets under the three-argument
  EthInstructions::new, and the alias table test also pins the gas table
- the block executor keeps the commit-error latch and drops the
  SystemCaller field this branch had already removed
- transact_deploy_sequencer_registry_for takes the plain database like
  the rest of the file
- the partial-ladder tests install the state hook on the State database,
  where it lives on this branch
- the alias table test compares Instruction entries through Debug, as
  revm 40 wraps the fn pointer in an opaque struct
- the modexp suppression is re-anchored to its shifted line
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T04:45:22.846873Z 0072855 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Comment thread crates/mega-evm/tests/rex4/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex4/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex4/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex4/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex4/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex6/beneficiary_detention.rs Dismissed
Comment thread crates/mega-evm/tests/rex6/eip7702_authority_accounting.rs Dismissed
Comment thread crates/mega-evm/tests/rex6/eip7702_authority_accounting.rs Dismissed
Comment thread crates/mega-evm/tests/rex6/eip7702_authority_accounting.rs Dismissed
Comment thread crates/mega-evm/tests/rex6/eip7702_authority_accounting.rs Dismissed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7be3ef268a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/mutation/mutate.py
Comment thread crates/mega-evm/src/limit/limit.rs
SPEC_ORDER stays the behavior-introducing ladder; the alias rungs are parsed
from MegaSpecId::behavior and removed before the source comparison, so the
harness enumerates again now that MINI_REX_1 and MINI_REX_2 exist.
self.spec = cfg.spec;
self.inner = self.inner.with_cfg(cfg.into_op_cfg());
if intent == CfgIntent::Pinned {
self.inner.cfg.tx_chain_id_check = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Non-blocking for this PR — but I'd like point 2 tracked and picked up in a follow-up rather than dropped.

with_cfg pins tx_chain_id_check off unconditionally, and create_evm routes through it, so this is the production path too. No live impact that I can find — mega-reth never sets the flag, and its only chain-id enforcement is the pool (transaction-pool/src/validate/eth.rs:480).

Two things:

  1. An embedder that explicitly sets true now loses it silently. with_cfg_unpinned isn't reachable from EvmFactory, though a post-construction write to evm.ctx.cfg does stick — which is what system_tx_replay.rs relies on. Pre-PR the field passed through. Is silently overriding an explicit setting the intent here, as opposed to honoring it or rejecting it loudly?

  2. Since the pool is the only place this is currently enforced, anything reaching execution without traversing it is unchecked at every layer. Could we enforce it in the EVM from Rex7? It's still the unstable spec, so it can absorb the behavior change that flipping the gate on implies, where the frozen specs can't. I'd leave the shape to you — deposits and the REX5+ system-tx path are the two areas I'd want to see covered.

self.spec = cfg.spec;
self.inner = self.inner.with_cfg(cfg.into_op_cfg());
if intent == CfgIntent::Pinned {
self.inner.cfg.tx_chain_id_check = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Following up on point 2 with something concrete.

If the gate is ever enabled, the REX5+ system-tx guard at execution.rs:113 rejects chain_id: None unconditionally — but revm's canonical check, which that guard's comment says it mirrors, exempts legacy and custom types. MegaETH system txs are TxLegacy, and mega-reth builds them by inheriting tx.chain_id() from the triggering user tx (payload_executor.rs:1141), which is None for a pre-155 legacy tx the pool accepts. So the guard reads as stricter than intended.

Rex7 looks like the right place to fix both together — the guard and the gate. And if it's spec-gated (tx_chain_id_check = spec.is_enabled(REX7)), CfgIntent and with_cfg_unpinned fall out entirely: the spec answers the "did the caller mean this or is it just the upstream default" question that the bool can't. Worth considering where that gate lives — apply_cfg covers all six with_cfg call sites in the repo, on_new_tx covers everything and matches how force_amsterdam_eip8037_off already handles the same problem.

///
/// DB-dependent pre-frame usage may still be recorded later during pre-execution.
pub(crate) fn on_new_tx(&mut self) {
force_amsterdam_eip8037_off(&mut self.inner.cfg);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Non-blocking — question about the pinning strategy rather than the pin itself.

The doc on force_amsterdam_eip8037_off justifies settling this per-transaction rather than at entry points on two grounds I had trouble reproducing:

  • The re-enable path (set_spec_and_mainnet_gas_params ORs the flag on for Amsterdam+) can't fire while every MegaSpecId maps to Prague — and test_all_specs_map_to_isthmus_and_prague already forces the conversation if that ever changes. If Amsterdam does get mapped, whether EIP-8037 should be on seems like a decision to make deliberately at that point rather than one pre-answered here.
  • "a per-entry-point pin has to be re-derived every time one of them is rewired or a new path appears" — but those entry points are four bounded, in-crate sites, and entry-point pinning is exactly what tx_chain_id_check does three lines up.

Meanwhile every production path I can find — factory, the keyless-deploy sandbox (sandbox/execution.rs:622, the one construction outside the factory), mega-evme, t8n, state-test — funnels through MegaEvm::new, which already pins. Is the on_new_tx write covering something that one doesn't, beyond an embedder mutating evm.ctx.cfg on a live context? If that's a requirement it's worth stating outright; if not, a single pin would drop a per-tx config write and the second place this value is decided.

Related to the other thread: this flag and tx_chain_id_check currently use opposite strategies (choke point vs. entry points). However the Rex7 question lands, one agreed strategy for both would be easier to follow.

/// the journal still takes its resident-entry branch and still records the `account_warmed`
/// entry that re-cools the account if the frame reverts, so nothing else about the load moves.
#[inline]
fn resident_entry_prices_cold(&self, address: &Address) -> bool {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Non-blocking for this PR — a Rex7 follow-up.

The correction itself is right: I checked both versions, and revm 27's resident (Occupied) branch prices from the entry alone and never consults warm_preloaded_addresses, while revm 40 added that consultation. So this faithfully restores frozen behavior and nothing should change here.

But the behavior it preserves looks like a bug worth fixing later. Precompiles, the coinbase, and address-only access-list entries are never inserted into journal state during pre-execution — they live only in the pre-warm set, and that set is consulted exactly once, on the Vacant branch when the entry is first created. MegaETH's own bookkeeping consumes that one chance: inspect_account inserts with mark_cold(), and it runs before the opcode's own load in the SELFDESTRUCT wrapper (instructions.rs:2590), the CALL-family storage wrapper (:2003), and CREATE (:2107). Net effect: a SELFDESTRUCT to — or CALL into — a precompile or the coinbase pays the ~2,600 cold surcharge purely as an artifact of our pre-inspection, not from any intended rule. revm has a TODO next to reset_preloaded_addresses pointing at the same weakness.

The expected rule seems to be that pre-warm membership is final: warm regardless of what the journal holds. That's a real gas change, so Rex7 rather than here — could it be picked up alongside the other Rex7 items? Worth deciding whether the fix is general (drop the resident-entry correction from Rex7 so the pre-warm set wins everywhere) or narrow to the SELFDESTRUCT beneficiary.

};
Self { spec, inner: instruction_table }
}
}

/// Returns the static gas table the interpreter pre-charges from for `spec`.
///

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rex7 proposal: can the volatile-access guard concede the underfunded-frame case?

This whole mechanism — the per-spec zeroing here, charge_static_gas!, the _self_charged handler variants, and the hand-maintained volatile_guarded_opcodes() list — exists to keep the disableVolatileDataAccess guard reachable by a frame that can't afford revm 40's static pre-charge. Correct for the frozen specs, and the reasoning in the doc comments is good.

But it leaves a correspondence that has to be maintained by hand in two places, and a mismatch is silent and consensus-visible in both directions: an entry zeroed without a guard makes the opcode free, a guard whose entry stayed makes it charge twice. The test pins it today, but the list is manual.

Worth asking whether Rex7 should just let the pre-charge OOG a frame that is too poor to afford the opcode, and only run the guard when gas suffices. The conceded case is a frame holding less than 2–100 gas that was going to die anyway; in exchange the guarded opcodes go back to revm's vanilla table and the mechanism disappears for new specs.

The per-spec modules already give us the seam to do that without disturbing the frozen specs: mod rex7 could stop delegating to rex6::instruction_table() and wire its own table with gas_table(table) = table. The existing machinery stays where it is and becomes append-never, and the duplication is scoped to the handful of opcodes that actually differ.

Not for this PR — just flagging while Rex7 is still open, since it's unfixable once frozen. There's a broader version of this too: Gas is a concrete field on Interpreter, not an associated type on InterpreterTypes, which is why every opcode has to be wrapped to measure compute gas at all. Might be worth an upstream ask to revm.

fn debug_check_frozen_detention_window<H: HostExt + ?Sized>(
host: &mut H,
opcode: u8,
raw_target: Option<Address>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Blocking: this debug-only check mutates the journal, making gas depend on the build profile.

best_effort_resolve_eip7702_delegate_address takes &mut self and reaches inspect_account, whose Vacant arm does entry.insert(account) after mark_cold(). It pushes no journal entry, so a frame revert can't undo it — JournalEntry::AccountWarmed's revert only re-cools, it never removes a state entry. The account stays resident-and-cold for the rest of the transaction.

resident_entry_prices_cold then prices exactly that state as cold, exempting only access-list entries that carry storage keys. So:

  • debug: check runs → target materialized resident-cold → a later touch of it costs 2,600
  • release: the whole check is #[cfg(debug_assertions)] and absent → fresh load consults warm_precompiles / warm_coinbase_account → the same touch costs 100

REX6+ only (the || short-circuits below that), and only for an address that would otherwise be warm — a precompile, the coinbase, or an address-only access-list entry. But a REX6 CALL to a precompile that runs out of gas on the static or value-transfer charge is an ordinary path, and it leaves the two builds 2,500 gas apart in both EVM gas and compute gas.

Two consequences:

  1. cargo test is a debug build, so the whole suite exercises an EVM that charges differently from the shipped one.
  2. It defeats the check's stated purpose. The doc comment says this is "the tripwire such a replay must run with" — but debug_assert! only fires in a debug build, and a debug build is the one whose gas is wrong. The full-history replay meant to prove no transaction sits in the window would itself diverge from history, on unrelated transactions.

The check is already documented as deliberately over-approximate, so it doesn't need to resolve anything it can't see: peeking journal.state and skipping when the target isn't resident would keep the detection and drop the side effect. Worth a test pinning the same gas value under both profiles either way.

Separately, three lines down: the assert message points at REVM_40_REVIEW_GUIDE.md (wontfix #20), which isn't in the repo or anywhere in its git history. That message is the only instruction anyone gets at the moment this fires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api:breaking Crate interface change — downstream users must update comp:core Changes to the `mega-evm` core crate comp:doc Changes in the documentation comp:mega-evme Changes to the `mega-evme` tool comp:misc Changes to the miscellaneous part of this repo dependencies Pull requests that update a dependency file spec:stable Touches stable spec code — must not change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants