Skip to main content

Command Palette

Search for a command to run...

Ethereum Storage & Public Data Notes

Published
2 min read
S

I write to revisit topics I’m interested in or when I’m bored and curious.

1️⃣ Storage Basics

Ethereum storage is like a massive spreadsheet. Each variable gets a 32-byte (256-bit) row, called a slot.

  • Static types (uint256, address, bool, bytes32) → stored directly in their slot.

  • Dynamic types (string, bytes, arrays, mappings) → handled differently (pointers, packing).


2️⃣ Slots & Offsets

Every variable has:

  • Slot → the “row” in storage

  • Offset → byte position inside the slot

Example – generic contract:

SlotVariableTypeNotes
0owneraddressstatic, straightforward
1namestringdynamic, inline or pointer
2balancesmappingpointer to hashed keys
3databytesdynamic, depends on length

3️⃣ Dynamic Types & Strings

Short strings / bytes (≤31 bytes) → packed directly into their slot. Solidity uses the last byte of the slot to store the length.

Long strings / bytes (>31 bytes) → slot stores a pointer:

  • Pointer = keccak256(slot_number)

  • Actual bytes stored consecutively starting at that pointer

Examples:

name = "Alice"; 
// short string → inline in slot 1

data = hex"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; 
// long bytes → slot 3 points to keccak256(3)

Arrays and mappings follow similar pointer rules:

  • uint256[] numbers → slot stores length, elements at keccak256(slot) + index

  • mapping(address => uint256) balances → element stored at keccak256(abi.encode(key, slot))


4️⃣ Private ≠ Secret

private only blocks other contracts from direct access. All storage is public on-chain.

  • Read via vm.load() in Foundry

  • Or eth_getStorageAt via RPC / ethers.js / web3.js

Public storage leaks are a goldmine for vulnerabilities. Never trust private for secrecy.


5️⃣ Reading Storage in Tests

Forge test pattern for exposing storage:

  1. Deploy the contract & set sensitive data

  2. Read static variables directly: vm.load(contract, slot_number)

  3. For short dynamic variables: decode bytes from slot, read length from last byte

  4. For long dynamic variables: compute base = keccak256(slot_number) and read consecutive slots

Arrays, mappings, and long bytes require looping or hashing to reconstruct.

Web3

Part 3 of 3

blog to qucikly revise the concepts of blockchain and web3

Start from the beginning

PoW vs PoS

1 shot concepts to revise & understand PoW & PoS