Skip to content

Derive pre-block system-contract and EIP gates from the resolved spec (revm-style ordinal inclusion) #353

Description

@RealiCZ

Summary

The EVM layer derives every behavior gate from one resolved spec via ordinal inclusion (MegaSpecId::is_enabled, same design as revm's SpecId::is_enabled_in), so spec additivity is structural there.
The block layer deviates: pre-block system-contract deploys and EIP gates consult per-fork hardfork registration (is_X_active_at_timestamp) instead of the resolved spec.

With a partial-ladder hardfork config (e.g. a genesis scheduling rex6Time without rex5Time), spec_id(timestamp) resolves REX6 but the Rex5-gated pre-block setup is silently skipped: the EIP-2935/EIP-4788 fail-closed checks, the SequencerRegistry deployment/updates, and the Rex5 oracle bytecode selection.
Every canonical schedule (mainnet/testnet/all-activated constants, real genesis files) carries the complete ladder, where both gating styles are bit-for-bit equivalent — so this is unreachable on well-formed configs and purely a robustness gap.

Raised by Codex review on #348: #348 (comment)

Affected gate sites

  • block/executor.rs:179,244 — is_rex_5_active_at_timestamp (EIP-2935/4788 fail-closed + SequencerRegistry deploy/update)
  • block/eips.rs:62,131 — is_rex_5_active_at_timestamp (result handling variants)
  • system/oracle.rs:61,69,72,119 — MiniRex deploy gate + Rex5/Rex2 bytecode selection
  • system/keyless_deploy.rs:62 — Rex2
  • system/control.rs:64, system/limit_control.rs:43 — Rex4
  • system/sequencer_registry.rs:144 — Rex5

Proposed fix

Resolve spec_id(block_timestamp) once at the pre-block entry point and gate the sites above on spec.is_enabled(MegaSpecId::X).

  • On complete-ladder configs the change is observationally identical (each is_X_active_at_timestamp(ts) ⇔ spec_id(ts).is_enabled(X) when the ladder is complete with monotone times), so stable-spec behavior and replay are unaffected.
  • On partial-ladder configs, additivity becomes structural again: a Rex6-only config deploys all lower-spec system contracts at the Rex6 activation block and enforces the fail-closed checks.

Add a partial-ladder regression test: a config registering only Rex6 must deploy the registry/oracle and enforce the EIP-2935/4788 fail-closed checks at activation.

Related (separate repo)

mega-reth's MegaethChainSpec::from_genesis performs no ladder-completeness validation either (absent forks silently become ForkCondition::Never); a load-time predecessor check there is the matching defense-in-depth.

Activity

  1. added
    comp:coreChanges to the `mega-evm` core crate
    rustPull requests that update rust code
    on Jul 23, 2026
  2. added
    spec:stableTouches stable spec code — must not change behavior
    api:unchangedNo change to the public interface or API
    on Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api:unchangedNo change to the public interface or APIcomp:coreChanges to the `mega-evm` core craterustPull requests that update rust codespec:stableTouches stable spec code — must not change behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions