Skip to main content

Overview

BeaconBlockRoot represents a 32-byte beacon chain block root hash. Introduced in EIP-4788 (Dencun upgrade), these roots are now available in the EVM, enabling trustless access to consensus layer data from smart contracts. Type: Uint8Array & { readonly [brand]: "BeaconBlockRoot"; length: 32 }

Key Concepts

  • Size: Exactly 32 bytes
  • EIP-4788: Available in EVM via BLOCKHASH opcode for recent slots
  • Ring buffer: Stored in contract at 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02
  • History: 8191 most recent roots accessible on-chain

Methods

BeaconBlockRoot.from(value)

Create BeaconBlockRoot from hex string or bytes.
import { BeaconBlockRoot } from '@tevm/primitives';

const root1 = BeaconBlockRoot.from('0x1234...');
const root2 = BeaconBlockRoot.from(new Uint8Array(32));

BeaconBlockRoot.fromHex(hex)

Create BeaconBlockRoot from hex string.
const root = BeaconBlockRoot.fromHex(
  '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
);

BeaconBlockRoot.fromBytes(bytes)

Create BeaconBlockRoot from Uint8Array.
const bytes = new Uint8Array(32);
const root = BeaconBlockRoot.fromBytes(bytes);

BeaconBlockRoot.toHex(root)

Convert BeaconBlockRoot to hex string.
const root = BeaconBlockRoot.from(new Uint8Array(32));
const hex = BeaconBlockRoot.toHex(root); // "0x0000..."

BeaconBlockRoot.equals(a, b)

Check if two beacon block roots are equal.
const a = BeaconBlockRoot.from('0x1234...');
const b = BeaconBlockRoot.from('0x1234...');
BeaconBlockRoot.equals(a, b); // true

Usage Examples

Access beacon roots in smart contracts

// EIP-4788 beacon roots contract
address constant BEACON_ROOTS = 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02;

contract BeaconRootConsumer {
    function getParentBeaconBlockRoot() public view returns (bytes32) {
        // Get beacon root for current block's parent
        (bool success, bytes memory data) = BEACON_ROOTS.staticcall(
            abi.encode(block.timestamp - 12)
        );
        require(success, "Failed to get beacon root");
        return abi.decode(data, (bytes32));
    }
}

Verify beacon chain data

import { BeaconBlockRoot, Slot } from '@tevm/primitives';

interface BeaconBlock {
  slot: Slot;
  root: BeaconBlockRoot;
  parentRoot: BeaconBlockRoot;
  stateRoot: BeaconBlockRoot;
}

const block: BeaconBlock = {
  slot: Slot.from(1000000n),
  root: BeaconBlockRoot.from('0x1234...'),
  parentRoot: BeaconBlockRoot.from('0x5678...'),
  stateRoot: BeaconBlockRoot.from('0x9abc...'),
};

Build Merkle proofs

import { BeaconBlockRoot } from '@tevm/primitives';

interface MerkleProof {
  leaf: BeaconBlockRoot;
  proof: BeaconBlockRoot[];
  root: BeaconBlockRoot;
}

function verifyMerkleProof(proof: MerkleProof): boolean {
  let current = proof.leaf;

  for (const sibling of proof.proof) {
    // Hash current with sibling (implementation depends on hashing)
    current = hash(current, sibling);
  }

  return BeaconBlockRoot.equals(current, proof.root);
}
  • Slot - Beacon roots indexed by timestamp
  • Hash - Generic 32-byte hash type
  • Withdrawal - References beacon chain state

References