Skip to content

SeismicChainHardforks::ethereum_fork_activation reports Prague as never active (off-by-one, EIP-6110/7002/7251 system calls silently skipped) #63

Description

@teyrebaz33

Describe the bug

SeismicChainHardforks::ethereum_fork_activation (crates/seismic-evm/src/hardfork.rs) reports Prague as never active:

fn ethereum_fork_activation(&self, fork: EthereumHardfork) -> ForkCondition {
    if fork < EthereumHardfork::Prague {
        // We assume that Seismic chains were launched with all forks before Prague activated.
        ForkCondition::Block(0)
    } else {
        ForkCondition::Never
    }
}

The comparison is fork < EthereumHardfork::Prague, which excludes Prague itself, so is_prague_active_at_timestamp(..) returns false at every timestamp, including genesis.

Why this is wrong

  • seismic-reth's own hardfork schedule (crates/seismic/hardforks/src/lib.rs) activates Prague at ForkCondition::Timestamp(0) — Prague is active from genesis in the real, production chainspec.
  • seismic-revm's own test (test_cancun_precompiles_in_mercury) builds Mercury's precompile set as an extension of Precompiles::prague(), i.e. Mercury is meant to include everything Prague introduces.

So SeismicChainHardforks disagrees with both the actual production hardfork schedule and with how Mercury is described/tested elsewhere in the stack.

Impact

EthBlockExecutor::finish (crates/evm/src/eth/block.rs) gates the EIP-6110 (deposits), EIP-7002 (withdrawal requests), and EIP-7251 (consolidation requests) system calls directly on self.spec.is_prague_active_at_timestamp(timestamp_seconds). With SeismicChainHardforks, that's always false, so those system calls are silently skipped and the block's requests field would never be populated.

SeismicChainHardforks is also the default Spec type parameter for the exported SeismicBlockExecutorFactory<R, Spec, EvmFactory>, and it's what this crate's own tests use to exercise the block executor (SeismicChainHardforks::seismic_mainnet() in crates/seismic-evm/src/block/mod.rs).

This does not affect seismic-reth in production — it supplies its own chainspec type instead of this default, so the actual node isn't hitting this. But any other consumer of this crate relying on the default Spec, and this crate's own test suite, would be.

Fix

I've opened a PR: fork <= EthereumHardfork::Prague (Prague inclusive), plus a regression test asserting is_prague_active_at_timestamp(0) is true.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions