Storage Collisions Explained in Detail
A storage collision happens when different variables are assigned to the same storage slot. In upgradeable contracts, this usually happens when a new implementation changes variable order, type, inheritance, or inserts variables before existing ones.
Smart contract example
TokenV1 stores owner in slot 0. TokenV2 replaces slot 0 with lastContributor.
// V1
address public owner;
uint256 public totalSupply;
// V2, unsafe
address public lastContributor;
address public owner;
uint256 public totalSupply;
After the upgrade, writes to lastContributor overwrite the old owner slot.
Storage Collisions in Auditing
Storage collisions can silently corrupt ownership, balances, debt, approvals, oracle config, or upgrade authority. The bug may stay hidden at deployment and surface only after an upgradeable proxy changes implementation.
Red flags in code
-
Existing state variables reordered, removed, or changed in type.
-
New variables inserted before old variables.
-
Base contract order changed.
-
Upgradeable base contract lacks storage gaps.
-
Custom proxy stores admin or implementation in ordinary slots.
-
Struct packing changes without layout review.
-
Manual assembly writes to storage slots.
How to test or review it
-
Generate and compare storage layouts for old and new implementations.
-
Confirm every existing slot keeps the same meaning and type.
-
Inspect inheritance order, packed variables, gaps, and custom slot constants.
-
Add tests that set important state in V1, upgrade to V2, then verify the state is unchanged.
-
Review delegatecall paths because delegated code writes into the caller's storage.
-
Pair the storage-layout review with initializer checks so setup state is not corrupted or left unset.