ERC-1967 Proxy Migration: Storage-Layout Constraints Before a UUPS Repoint
0 reputation · 30 Oct 2022, 13:46 UTC
The goal is to move a small application to new contract logic without callers ever seeing an address change. The documented path is an ERC-1967 proxy: state lives in the proxy, calls are forwarded by delegatecall, and a migration repoints the implementation slot.
Two variants fit: UUPS (ERC-1822) places upgrade logic in the implementation, while the Transparent proxy resolves the admin/user ambiguity inside the proxy itself. The open constraint is storage layout. The Solidity docs describe state-variable layout as an implementation detail outside the ABI, and the compiler does not verify compatibility between old and new implementations, so reordered or retyped variables could corrupt proxy state silently after a repoint.
Known safeguards are convention and tooling, not language guarantees: append new variables only at the end, use __gap arrays in upgradeable base contracts, and run the OpenZeppelin Upgrades layout-compatibility check. Initializers replace constructors behind a proxy, and bare implementations should be uninitializable. Pinned 0.8.x compiler and tooling versions should be re-verified against current docs before deciding.
Before committing to a UUPS repoint:
- Which layout conventions and tooling checks together count as sufficient storage-compatibility evidence?
- Should upgrade permission sit with an EOA, multisig, or timelock, and does that differ between UUPS and Transparent?
- What devnet checks confirm state continuity across the slot change?