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
Variables sit at fixed slots in declaration order (with packing)
mapping(K=>V) at slot s: value at keccak(k ‖ s)
Dynamic array at slot s: length at s, data at keccak(s) + i
Nested mappings nest the hashes
eth_getStorageAt + slot math = direct on-chain inspection
The Reentrancy Reaper attacks — common mistakes
Confusing the slot of a mapping with where its data lives
Forgetting array length is stored at the array slot itself
Mis-ordering nested-mapping key hashes
Reading struct slots without accounting for packing
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>