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

# StorageProof

> EIP-1186 storage slot proof for trustless contract storage verification

# StorageProof

EIP-1186 storage slot proof for trustless contract storage verification.

## Overview

StorageProof represents a proof for a single storage slot in a contract's storage trie. It enables trustless verification of contract storage values without executing transactions or trusting external providers.

## Type Definition

```typescript theme={null}
type StorageProofType = {
  /** The storage slot being proven */
  readonly key: StorageKeyType;

  /** The value stored at this slot (0 if uninitialized) */
  readonly value: StorageValueType;

  /** RLP-encoded Merkle Patricia Trie nodes (root to leaf) */
  readonly proof: readonly Uint8Array[];
};

type StorageProofLike = StorageProofType | {
  key: StorageKeyType;
  value: StorageValueType;
  proof: readonly Uint8Array[];
};
```

## Usage

### Create StorageProof

```typescript theme={null}
import * as StorageProof from './primitives/StorageProof/index.js';

const proof = StorageProof.from({
  key: 0n,  // storage slot 0
  value: 1000000000000000000n,  // stored value
  proof: [/* RLP-encoded trie nodes */],
});
```

### Compare Proofs

```typescript theme={null}
const isEqual = StorageProof.equals(proof1, proof2);
```

## API Reference

### Constructors

| Function      | Description                         |
| ------------- | ----------------------------------- |
| `from(proof)` | Create from StorageProofLike object |

### Methods

| Function       | Description                   |
| -------------- | ----------------------------- |
| `equals(a, b)` | Check if two proofs are equal |

## Obtaining Storage Proofs

Use `eth_getProof` with storage slots:

```typescript theme={null}
const result = await provider.send("eth_getProof", [
  contractAddress,
  ["0x0", "0x1", "0x2"],  // storage slots to prove
  "latest"
]);

// Extract storage proofs
const storageProofs = result.storageProof.map(sp => StorageProof.from(sp));
```

## Storage Slot Calculation

Solidity storage layout determines slot numbers:

```typescript theme={null}
// Slot 0: first state variable
const slot0 = 0n;

// Mapping: keccak256(key . slot)
import * as Hash from './primitives/Hash/index.js';
const mappingSlot = Hash.keccak256(concat(
  padLeft(key, 32),
  padLeft(slot, 32)
));

// Dynamic array: keccak256(slot) + index
const arraySlot = BigInt(Hash.toHex(Hash.keccak256(padLeft(slot, 32)))) + index;
```

## Verification Process

```typescript theme={null}
function verifyStorageProof(
  proof: StorageProofType,
  storageRoot: StateRootType
): boolean {
  // 1. Compute path = keccak256(key)
  const path = Hash.keccak256(proof.key);

  // 2. Walk Merkle Patricia Trie from root
  // 3. Verify proof nodes against path
  // 4. Extract value from leaf
  // 5. Compare with proof.value

  return true;
}
```

## Use Cases

### Verify Token Balance

```typescript theme={null}
// ERC-20 balanceOf mapping at slot 0
const balanceSlot = keccak256(concat(
  padLeft(holderAddress, 32),
  padLeft(0n, 32)  // balances mapping slot
));

const proof = await provider.send("eth_getProof", [
  tokenContract,
  [toHex(balanceSlot)],
  "latest"
]);

// Verify against trusted state root
const isValid = verifyStorageProof(
  proof.storageProof[0],
  proof.storageHash
);

console.log(`Verified balance: ${proof.storageProof[0].value}`);
```

### Cross-Chain Storage Proof

```typescript theme={null}
// Prove L1 contract storage for L2 verification
const l1Proof = await l1Provider.send("eth_getProof", [
  l1Contract,
  [storageSlot],
  blockNumber
]);

// Submit to L2 bridge contract
await l2Bridge.verifyL1Storage(
  l1Contract,
  storageSlot,
  l1Proof.storageProof[0].proof,
  l1StateRoot
);
```

### Oracle-Free Price Feeds

```typescript theme={null}
// Prove Uniswap pool reserves without oracle
const slot0 = "0x0";  // reserves slot

const proof = await provider.send("eth_getProof", [
  uniswapPool,
  [slot0],
  trustedBlockNumber
]);

// Verify and extract reserves
const reserves = decodeReserves(proof.storageProof[0].value);
```

## Proof Structure

```
Account's Storage Trie
    |
    +-- storageRoot (32 bytes)
    |
    +-- Merkle Patricia Trie
        |
        +-- keccak256(slot0) --> value0
        |       proof[0]
        |
        +-- keccak256(slot1) --> value1
        |       proof[1]
        ...
```

## Common Storage Slots

| Pattern               | Slot Calculation                           |
| --------------------- | ------------------------------------------ |
| Simple variable       | Sequential from 0                          |
| Mapping               | `keccak256(key . slot)`                    |
| Nested mapping        | `keccak256(key2 . keccak256(key1 . slot))` |
| Dynamic array length  | `slot`                                     |
| Dynamic array element | `keccak256(slot) + index`                  |

## Specification

* **EIP-1186**: [https://eips.ethereum.org/EIPS/eip-1186](https://eips.ethereum.org/EIPS/eip-1186)
* **JSON-RPC**: `eth_getProof` method

## See Also

* [StateProof](/primitives/state-proof) - Account state proofs
* [StateRoot](/primitives/state-root) - State trie root
* [Proof](/primitives/proof) - Generic Merkle proof
* [State](/primitives/state) - State primitives
