Ethereum doesn’t care about your variables

Why storage slots are just dumb bytes and Solidity does the slicing


Ethereum storage slots are just 32 raw bytes, a 256-bit word, usually shown as 64 hex characters with a 0x prefix. Slots don’t know types, addresses, or numbers. It’s the Solidity compiler and ABI that define how those bytes are sliced and interpreted. Once you see it this way, common misconceptions about packing and layout disappear.

The Misconception

When developers first start out they might think that the slot is aware it contains an address or a uint96 etc. In reality the Ethereum storage is blind. At first glance, you might think a slot is just one big integer, or that the EVM somehow “knows” an address sits in these 20 bytes and a uint96 in the next 12. But it doesn’t.

What storage really is

Each contract gets a key -> value mapping:

  • Key: slot index (256-bit)
  • Value: 32-byte word

In EVM terms, a “word” is always 32 bytes. That word is just a chunk of data. What it means depends entirely on the compiler and ABI. Example hex dump…

0x000000102030405060708090aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

So what turns this raw blob into meaningful variables? Not the EVM but the Solidity compiler.


Who decides the meaning? (The compiler)

Solidity lays out your variables in the order you declare them. The EVM just sees a 32-byte word. Solidity decides how to slice it.

  • address -> rightmost 20 bytes
  • uint86 -> the remaining 12 bytes in that slot

On SSTORE, the compiler packs those fields and writes the raw 32 bytes. On SLOAD, it reads the word back and slices it according to the types.

[000000102030405060708090][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
   uint96 (12B, left)            address (20B, right)

Think of it like a database row: on disk it’s just bytes; the schema tells you what each slice means.

Why it matters

Prevents misreading raw storage dumps and explains why packing saves gas: fewer slots touched. Understanding this is essential for debugging, auditing storage layouts and writing upgradable contracts.


Common Pitfalls

“The slot knows its type.”
It doesn’t. A slot is 32 raw bytes. Types live in the compiler/ABI, not in storage.

Reading storage like one big integer.
Don’t “sum” or treat the whole word as a single number when fields are packed. Slice by byte offset and width, then decode per type.

“The slot knows its type.”
It doesn’t. A slot is 32 raw bytes. Types live in the compiler/ABI, not in storage.

Trusting the 0x prefix to mean anything on-chain.
0x is display sugar. Storage is bytes. The prefix isn’t stored.

Forgetting right-alignment of small types.
Small values (i.e, bool, uint8,uint96) sit in the low-order ->rightmost bytes of the 32-byte word. That’s where to look.


Conclusion

The EVM stores bytes; the compiler gives them meaning. Once you see storage as a 32-byte word and remember Solidity slices types into the low-order bytes, packing rules and gas costs stop being mysterious. Group small fields, isolate full-slot types, treat mappings/arrays as boundaries, and guard writes in hot paths. If you’re reading raw storage, bring the layout, it’s the difference between guessing and knowing.



By Burt Snyder

Writing about interesting things and sharing ideas.

1 comment

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.