โ†
Previous Module
Event Subscription Demo

โš ๏ธ Storage Collisions: Don't Break State

Learn how to avoid catastrophic storage layout errors

Learn upgradeable smart contract patterns

๐Ÿ’ฅ The Storage Layout Trap

Storage collisions are the #1 cause of catastrophic upgrade failures. When Logic V2 uses different storage layout than V1, variables overwrite each other. Example: V1 has address owner at slot 0. V2 adds uint256 fee at slot 0. After upgrade, fee overwrites owner. Contract bricked. Storage layout must be append-only.

๐ŸŽฎ Interactive: Storage Collision Simulator

Toggle between safe and unsafe upgrades to see how storage layout changes cause collisions. Watch variables overwrite each other when layout rules are violated.

โœ“ Correct: Append-Only Storage
Logic V1 Storage
slot 0:address token= 0xabcd...
slot 1:uint256 fee= 100
slot 2:bool paused= false
Logic V2 Storage (Upgraded)
slot 0:address token= 0xabcd...
slot 1:uint256 fee= 100
slot 2:bool paused= false
slot 3:uint256 newFeature= 0NEW โœ“
Why This Works:

V2 keeps all V1 variables in same slots (0-2). New variable added at slot 3. No overwrites. All existing data preserved. Append-only is safe.

๐Ÿ“ Storage Layout Rules

โœ“DO: Add new variables at the end
โœ“DO: Keep existing variables in same order
โœ—DON'T: Delete variables from middle
โœ—DON'T: Change variable types
โœ—DON'T: Reorder variables

๐Ÿ›ก๏ธ Storage Collision Prevention

๐Ÿ”
Use Storage Gaps

Add uint256[50] __gap at end of contracts. Reserves 50 slots for future variables. Can shrink gap when adding new variables. OpenZeppelin standard.

uint256[50] private __gap; // Reserve slots
๐Ÿงช
Validate with Tools

Use OpenZeppelin Upgrades Plugin or Hardhat Upgrades. They compare storage layouts before upgrade. Detect collisions automatically. Fail deployment if unsafe.

npx hardhat verify:upgrade <proxy> <newImpl>
๐Ÿ“
Document Storage Layout

Maintain STORAGE_LAYOUT.md showing slot assignments. Update on every version. Reviewers can spot collisions before deployment.

๐Ÿ”’
Unstructured Storage (Proxy Variables)

Proxy's own variables (implementation address, admin) use random storage slots calculated from keccak256(string). This prevents Logic from accidentally overwriting Proxy state.

bytes32 IMPL_SLOT = keccak256("proxy.implementation");

โš ๏ธ Real Collision Disasters

Parity Multisig Wallet (2017, $150M+)

Not exactly storage collision, but related: library contract (shared logic) was made ownable by accident. Attacker became owner, self-destructed library. All wallets using it became unusable. 300+ wallets frozen permanently.

Audius Governance Attack (2022, $6M)

Upgrade added new storage variables without gap. Overwrote critical governance parameters. Attacker exploited collision to pass malicious proposal. Funds drained. Storage validation would have prevented this.

๐Ÿ’ก Key Insight

Storage collisions are silent killers. Your upgrade transaction succeeds. No error messages. But data is corrupted. owner variable now contains a random number. totalSupply overwritten with false. Contract appears to work but behaves unpredictably. Prevention is mandatory, not optional. Use storage gaps, validate with tools, document layouts, and review every upgrade. One collision can brick a billion-dollar protocol.

โ† Proxy Patterns