> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
> Use this file to discover all available pages before exploring further.

# EIP-2935: Historical Block Hash Storage

> Implementation of EIP-2935 for reliable historical block hash access in smart contracts

EIP-2935 provides standardized access to historical block hashes through contract storage, enabling smart contracts to reliably access block hashes beyond the traditional 256-block limit.

## Overview

### What is EIP-2935?

EIP-2935 introduces a system contract that stores block hashes in contract storage, making them accessible to smart contracts for extended periods. This enables protocols requiring verifiable randomness, block-based logic, or historical verification.

### Key Benefits

* **Extended History:** Access up to 8192 block hashes (configurable)
* **Reliable Access:** No longer limited to recent 256 blocks
* **Smart Contract Compatibility:** Works with existing `BLOCKHASH` opcode
* **Verifiable Randomness:** Enable protocols requiring historical entropy

## Implementation Details

### Block Hash Storage Mechanism

Cosmos EVM implements EIP-2935 by storing block hashes in a special system contract storage:

```
Contract Address: 0x0aae40965e6800cd9b1f4b05ff21581047e3f91e (EIP-2935 system contract)
Storage Layout:   block_number % HISTORY_SERVE_WINDOW → block_hash
```

### Configuration Parameter

The `history_serve_window` parameter controls how many historical block hashes are stored:

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "vm": {
    "params": {
      "history_serve_window": 8192  // Default: 8192 blocks
    }
  }
}
```

**Parameter Details:**

* **Type:** `uint64`
* **Default:** `8192` ([source](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L46))
* **Range:** Must be > 0, recommended ≤ 8192
* **Storage Impact:** Higher values increase storage requirements linearly

## Comparison with Ethereum

### Similarities

* **Same storage contract address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e`
* **Same storage layout:** Ring buffer using modulo arithmetic
* **Same opcode behavior:** `BLOCKHASH` queries contract storage
* **Same gas costs:** Standard SLOAD costs apply (2100 gas for cold access)

### Differences

* **Configurable window:** Cosmos EVM allows custom `history_serve_window` (vs fixed 8192 in Ethereum)
* **Instant activation:** Available immediately on upgrade (not block-based activation)
* **No fork logic:** Uses consensus parameter instead of fork activation
* **Performance tuning:** Can be optimized per chain requirements
* **Traditional 256-block limit:** Ethereum's original `BLOCKHASH` opcode only provided access to the most recent 256 blocks; EIP-2935 extends this significantly

## Usage in Smart Contracts

### Basic Block Hash Access

```solidity Basic Block Hash Access expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
pragma solidity ^0.8.0;

contract BlockHashExample {
    function getRecentBlockHash(uint256 blockNumber)
        external
        view
        returns (bytes32)
    {
        // Works for blocks within history_serve_window range
        return blockhash(blockNumber);
    }

    function getCurrentBlockNumber() external view returns (uint256) {
        return block.number;
    }

    function getHistoricalRange() external view returns (uint256) {
        // Can access block hashes for last 8192 blocks (default)
        return 8192;
    }
}
```

### Verifiable Randomness Protocol

```solidity Verifiable Randomness Protocol expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
contract VerifiableRandomness {
    struct RandomnessCommit {
        bytes32 blockHash;
        uint256 blockNumber;
        uint256 timestamp;
        bool revealed;
    }

    mapping(bytes32 => RandomnessCommit) public commits;

    function commitRandomness(bytes32 commitment) external {
        // Commit to using future block hash as randomness source
        uint256 revealBlock = block.number + 10; // Reveal 10 blocks later

        commits[commitment] = RandomnessCommit({
            blockHash: bytes32(0), // Will be filled during reveal
            blockNumber: revealBlock,
            timestamp: block.timestamp,
            revealed: false
        });
    }

    function revealRandomness(
        bytes32 commitment,
        uint256 nonce
    ) external returns (bytes32 randomness) {
        RandomnessCommit storage commit = commits[commitment];
        require(!commit.revealed, "Already revealed");
        require(block.number >= commit.blockNumber, "Too early to reveal");

        // Get block hash from historical storage (EIP-2935)
        bytes32 blockHash = blockhash(commit.blockNumber);
        require(blockHash != bytes32(0), "Block hash not available");

        commit.blockHash = blockHash;
        commit.revealed = true;

        // Generate verifiable randomness
        randomness = keccak256(abi.encodePacked(
            blockHash,
            commitment,
            nonce
        ));

        return randomness;
    }
}
```

### Block-Based State Transitions

```solidity Block-Based State Transitions expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
contract BlockBasedLogic {
    uint256 public constant EPOCH_LENGTH = 1000; // blocks
    mapping(uint256 => bytes32) public epochSeeds;

    function updateEpochSeed() external {
        uint256 currentEpoch = block.number / EPOCH_LENGTH;

        if (epochSeeds[currentEpoch] == bytes32(0)) {
            // Use block hash from start of epoch as seed
            uint256 epochStartBlock = currentEpoch * EPOCH_LENGTH;
            bytes32 seedHash = blockhash(epochStartBlock);

            require(seedHash != bytes32(0), "Epoch seed block not available");
            epochSeeds[currentEpoch] = seedHash;
        }
    }

    function getEpochSeed(uint256 epoch) external view returns (bytes32) {
        return epochSeeds[epoch];
    }
}
```

## Configuration Examples

### High Compatibility (Default)

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "vm": {
    "params": {
      "history_serve_window": 8192
    }
  }
}
```

**Use Case:** Full EIP-2935 compatibility for protocols requiring extended block history
**Storage:** \~256KB additional storage (32 bytes × 8192 blocks)
**Performance:** Standard performance, suitable for most chains

### Performance Optimized

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "vm": {
    "params": {
      "history_serve_window": 1024
    }
  }
}
```

**Use Case:** Resource-constrained nodes or chains prioritizing performance
**Storage:** \~32KB additional storage (32 bytes × 1024 blocks)
**Trade-off:** Shorter historical access but better performance

### Extended History

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "vm": {
    "params": {
      "history_serve_window": 16384
    }
  }
}
```

**Use Case:** Protocols requiring very long historical access
**Storage:** \~512KB additional storage (32 bytes × 16384 blocks)
**Performance:** Higher storage overhead but maximum compatibility

## Technical Implementation

### BLOCKHASH Opcode Behavior

**Before EIP-2935:**

```
blockhash(n) → Returns hash only if (block.number - 257) < n < block.number
               Returns 0x0 for older blocks
```

**After EIP-2935:**

```
blockhash(n) → Returns hash if (block.number - history_serve_window) < n < block.number
               Uses contract storage for historical hashes
               Returns 0x0 only if outside window or invalid
```

### Storage Layout

The EIP-2935 system contract uses a simple storage mapping:

```
Key:   block_number % history_serve_window
Value: block_hash
```

**Example with history\_serve\_window = 8192:**

```
Storage[0] = hash(block 0, 8192, 16384, ...)
Storage[1] = hash(block 1, 8193, 16385, ...)
...
Storage[8191] = hash(block 8191, 16383, 24575, ...)
```

### Integration with EVM

The implementation integrates seamlessly with the EVM:

1. **Block Processing:** Each new block stores its hash in the system contract
2. **BLOCKHASH Opcode:** Modified to query contract storage for historical hashes
3. **Gas Costs:** Uses standard SLOAD gas costs for historical access
4. **Compatibility:** Maintains full backward compatibility

## Comparison with Ethereum

### Similarities

* **Same storage contract address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e`
* **Same storage layout:** Ring buffer using modulo arithmetic
* **Same opcode behavior:** `BLOCKHASH` queries contract storage
* **Same gas costs:** Standard SLOAD costs apply

### Differences

* **Configurable window:** Cosmos EVM allows custom `history_serve_window`
* **Instant activation:** Available immediately on upgrade (not block-based)
* **No fork logic:** Uses consensus parameter instead of fork activation
* **Performance tuning:** Can be optimized per chain requirements

## References

* **EIP-2935 Specification:** [https://eips.ethereum.org/EIPS/eip-2935](https://eips.ethereum.org/EIPS/eip-2935)
* **Implementation PR:** [cosmos/evm#407](https://github.com/cosmos/evm/pull/407)
* **System Contract Address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e`
* **Related Documentation:** [VM Module Parameters](../cosmos-sdk/modules/vm#parameters)
