Skip to content

statetest: BLOCKHASH range check breaks when currentNumber > 2^63-1 #1493

@chfast

Description

@chfast

Summary

evmone-statetest diverges from geth on a valid Cancun state test when env.currentNumber is above INT64_MAX.

The test executes BLOCKHASH(currentNumber - 1) and then stores ISZERO(result).

  • geth returns non-zero BLOCKHASH (in-range lookup), so ISZERO is 0.
  • evmone-statetest returns 0x0 for the same in-range lookup, so ISZERO is 1.

This produces different post-state roots.

Reproducer

files/case12-statetest-blockhash-highnum/blockhash_highnum_state_test.json

Commands

# geth: passes
~/go/bin/evm statetest --statetest.fork Cancun files/case12-statetest-blockhash-highnum/blockhash_highnum_state_test.json

# evmone: fails
build/debug/bin/evmone-statetest files/case12-statetest-blockhash-highnum/blockhash_highnum_state_test.json

Observed:

  • geth state root: 0x27ebe6aaf81779a3f3516512f8bdd8d543be038c26b9bba4bba5d85cce73f02f (PASS)
  • evmone state root: 0x48e2b3fe41a421a38716c88d2e14ad390b55ff6301db7d3b24079e55dc01e768 (FAIL)

Trace difference

For the same bytecode (0x6780000000000000ff401560005500):

  • geth trace shows BLOCKHASH pushes non-zero.
  • evmone trace shows BLOCKHASH pushes 0x0.

Likely root cause

The statetest path stores block numbers as signed 64-bit and BLOCKHASH range checks with signed bounds:

  • test/utils/statetest_loader.cpp: currentNumber parsed via from_json<int64_t>.
  • test/state/block.hpp: BlockInfo::number is int64_t.
  • lib/evmone/instructions.hpp blockhash():
    • upper_bound = state.get_tx_context().block_number (signed)
    • lower_bound = std::max(upper_bound - 256, 0)
    • n = static_cast<int64_t>(number)
    • signed comparison path rejects what should be valid currentNumber-1 lookups above INT64_MAX.

The EVM BLOCKHASH semantics are based on unsigned block numbers modulo 2^256 on stack values, with recent-256 window check relative to the current block number. Using signed block numbers in this path causes incorrect behavior for values above 2^63-1.

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