freecoding.school100% FREE · NO SIGNUP
The EVM CoreISSUE #32 of 48

storage layout · slots · mappings · arrays

SoliaVSThe Reentrancy Reaper
Solia saysSolidity computes deterministic storage slots with keccak256: mapping data at keccak(key ‖ slot), array data at keccak(slot) + index, nested mappings nest the hashes.

The Solidity compiler picks a deterministic slot layout for state variables and computes child slot positions with keccak256. Plain variables sit at fixed slots 0, 1, 2, … . A mapping(K => V) at slot s stores the value of key k at keccak256(k ‖ s). A dynamic array at slot s stores its length at s and element i at keccak256(s) + i. Nested mappings nest the hashes: m[a][b] lives at keccak256(b ‖ keccak256(a ‖ s)).

Knowing the layout lets you read storage directly with eth_getStorageAt, debug delegatecall corruption, and write efficient assembly. The demo computes slot positions with a toy hash; the rule is exactly the same under real keccak256.

Power-ups you unlock

The Reentrancy Reaper attacks — common mistakes

Boss battleCompute the storage slot for mapping(address => uint).balances[alice] at slot 5 and for arr[7] at slot 7.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// toy hash with the same DETERMINISM property as real keccak256.
const H = (...args) => { const s = args.join('|'); let h=2166136261>>>0; for(const c of s){ h^=c.charCodeAt(0); h=Math.imul(h,16777619); } return '0x' + (h>>>0).toString(16).padStart(8,'0'); };
const balancesSlot = 5;
const aliceBalSlot = H('alice', balancesSlot);
const arrSlot = 7;
const arrLenSlot = arrSlot;
const arr7Slot = H(arrSlot) + ' + 7';
const allowSlot = 6;
const allowAliceBobSlot = H('bob', H('alice', allowSlot));
document.getElementById('o').textContent = [
  'mapping(address => uint) balances; at slot 5:',
  '  balances[alice] lives at ' + aliceBalSlot,
  '',
  'uint[] arr; at slot 7:',
  '  arr.length    at slot ' + arrLenSlot,
  '  arr[i] data   at keccak(7) + i   →  arr[7] = ' + arr7Slot,
  '',
  'mapping(address => mapping(address => uint)) allowance; at slot 6:',
  '  allowance[alice][bob] at ' + allowAliceBobSlot
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Events · Indexed Topics · Log DecodingImmutable Vs Constant · Bytecode Placement ›