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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions