EEVM.SystemContracts.BeaconRoots (eevm v0.1.0)

Copy Markdown View Source

EIP-4788 beacon block root contract (activated in Cancun).

Installs the canonical EIP-4788 deployed bytecode at 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02 and drives it through the normal executor. At the start of every block the execution layer performs a system call (caller = SYSTEM_ADDRESS 0xff..fe) with the parent beacon-block root as calldata; the contract keys it by block.timestamp in a ring buffer of HISTORY_BUFFER_LENGTH = 8191 slots. User contracts read past roots back via a plain CALL with a 32-byte timestamp.

Storage layout (per the EIP):

  • storage[timestamp % 8191] = timestamp
  • storage[(timestamp % 8191) + 8191] = beacon_root

On read, the contract verifies the timestamp slot matches the queried timestamp (so ring-buffer collisions return empty rather than a stale root).

API

  • install/1 — place the deployed bytecode into a Database.
  • commit/3 — perform the block-start system call that stores a root. Returns {:ok, db} on success and {:error, reason, db} on execution failure.
  • lookup/2 — read a stored root directly from storage ({:ok, root} when the timestamp slot matches, :not_found otherwise).

Summary

Functions

Canonical deployment address of the beacon-roots contract.

Executes the block-start system call that records the 32-byte beacon_root under block.timestamp. An integer beacon_root is deprecated but still accepted for one minor version.

Returns the exact deployed bytecode that the EIP specifies.

Ring-buffer size for beacon-root history (constant, 8191).

Installs the beacon-roots contract into db at the canonical address.

Installs only if EIP-4788 is active in the given hardfork config. Callers setting up a pre-Cancun genesis get a no-op.

Reads a previously-committed beacon root by timestamp, directly from the contract's storage slots.

Caller address used by the execution layer's block-start system call.

Functions

address()

@spec address() :: non_neg_integer()

Canonical deployment address of the beacon-roots contract.

commit(db, block, beacon_root)

@spec commit(EEVM.Database.t(), EEVM.BlockEnv.t(), <<_::256>> | non_neg_integer()) ::
  {:ok, EEVM.Database.t()} | {:error, atom(), EEVM.Database.t()}

Executes the block-start system call that records the 32-byte beacon_root under block.timestamp. An integer beacon_root is deprecated but still accepted for one minor version.

Uses SYSTEM_ADDRESS as the caller so the contract takes its storage branch, and runs the code deployed at the contract address; when none is deployed yet (the fork's first blocks, before the deployment transaction), the call is a no-op. Returns the updated database, or an error tuple if the call reverted (which should never happen with the canonical bytecode, but we surface it rather than swallow it).

deployed_bytecode()

@spec deployed_bytecode() :: binary()

Returns the exact deployed bytecode that the EIP specifies.

history_buffer_length()

@spec history_buffer_length() :: pos_integer()

Ring-buffer size for beacon-root history (constant, 8191).

install(db)

@spec install(EEVM.Database.t()) :: EEVM.Database.t()

Installs the beacon-roots contract into db at the canonical address.

Idempotent — re-installing leaves storage untouched and only ensures the code is present.

install_if_enabled(db, config)

@spec install_if_enabled(EEVM.Database.t(), EEVM.HardforkConfig.t()) ::
  EEVM.Database.t()

Installs only if EIP-4788 is active in the given hardfork config. Callers setting up a pre-Cancun genesis get a no-op.

lookup(db, timestamp)

@spec lookup(EEVM.Database.t(), non_neg_integer()) ::
  {:ok, non_neg_integer()} | :not_found

Reads a previously-committed beacon root by timestamp, directly from the contract's storage slots.

Returns {:ok, root}, the stored storage word, when the slot at timestamp % 8191 matches timestamp (i.e. no ring-buffer collision), and :not_found otherwise.

system_address()

@spec system_address() :: non_neg_integer()

Caller address used by the execution layer's block-start system call.