# storage layout must remain consistent across proxy implementation versions Because [[delegatecall executes code from another contract using the callers storage context]], all state writes from the implementation land in the proxy's storage slots. New implementation versions must only append variables to the end of the layout, never reorder, remove, or insert variables before existing ones. Violating this constraint corrupts state because variable N in the new implementation maps to the slot that held variable N in the old implementation, regardless of name or type. Three collision categories exist: (1) **proxy-implementation collisions**, where proxy state variables occupy the same slots as implementation variables (solved by [[eip-1967 reserved storage slots prevent proxy implementation address collisions]]); (2) **cross-version layout shifts**, where inserting or reordering variables in a new implementation silently reinterprets old values as different types; (3) **storage gap mismanagement**, where base contracts in inheritance chains fail to reserve or decrement `__gap` arrays correctly, shifting child contract storage (see [[storage gap mismanagement in upgradeable base contracts causes child contract storage collisions]]). **Audius (July 2022):** An upgrade added a `proxyAdmin` variable to the proxy contract's storage. The implementation layout no longer aligned, creating a storage collision that led to fund theft. **Mitigations:** Run storage layout diffs between current and new implementations before every upgrade (OpenZeppelin Upgrades plugin, `slither-check-upgradeability`, Foundry upgrade safety checks). Since [[eip-7201 namespaced storage provides structured collision avoidance for upgradeable contracts]], EIP-7201 eliminates sequential layout dependencies for complex proxy setups. Note that this layout-consistency requirement is a liveness invariant, not a security barrier. Since [[the Munchables exploit demonstrated that storage slot writes during a proxy upgrade can fabricate phantom balances that survive subsequent implementation swaps]], a clean subsequent implementation applied to deliberately corrupted storage will silently read fabricated values as legitimate state, demonstrating the deliberate-corruption counterpart to the accidental-drift case this note addresses. The mechanism enabling deliberate corruption is explicit in [[proxy contracts preserve storage values written during malicious upgrades because delegatecall reads from the proxy's own storage independently of the active implementation]]: because all implementations share the same proxy storage address space, values written by a transient malicious implementation survive any subsequent implementation swap with no sanitization. --- Relevant Notes: - [[EIP-7702 storage collision attacks occur when migrating between delegate contracts with incompatible layouts because existing EOA storage is not cleared on re-delegation]]: extends this to EOA re-delegation: the same layout consistency requirement applies but has no enforcement mechanism - [[delegatecall executes code from another contract using the callers storage context]]: the mechanism that creates this requirement - [[eip-7201 namespaced storage provides structured collision avoidance for upgradeable contracts]]: a systematic defense - [[storage gap mismanagement in upgradeable base contracts causes child contract storage collisions]]: the inheritance-specific subcategory where __gap arrays must be managed across base and child contracts - [[EIP-2535 Diamond proxy facet storage collisions occur when multiple facets write to non-namespaced storage slots]]: diamond facets face the same constraint but across facets rather than across versions - [[re-initialization vulnerabilities arise when upgrades inadvertently reset initialization state]]: storage layout shifts can inadvertently overwrite initialization state, compounding re-initialization risk - [[the Munchables exploit demonstrated that storage slot writes during a proxy upgrade can fabricate phantom balances that survive subsequent implementation swaps]]: deliberate counterpart: where this note addresses unintentional layout drift, the Munchables case documents intentional slot writes by an attacker-controlled implementation; both exploit the same layout-consistency property Topics: - [[vulnerability-patterns]] - [[evm-internals]]