ERC-1967
ERC-1967: Proxy Storage Slots¶
ERC-1967 is a standard for how to safely store specific data in proxy contracts, designed to avoid storage collisions.
Problem Addressed¶
In the proxy pattern for upgradeable contracts, the proxy contract uses delegatecall to forward calls to the implementation (logic) contract. This means the logic contract's code runs in the proxy contract's storage context. If the proxy contract and logic contract use the same storage slot (for example, the proxy stores the logic contract address at slot 0, while the logic contract also stores the owner variable at slot 0), a storage collision occurs, causing data to overwrite each other and leading to serious vulnerabilities. To solve this problem, the proxy contract needs to store its specific state variables (such as logic contract address, admin address) in locations that the logic contract will never use.
Mechanism and Principles¶
ERC-1967 defines specific, pseudo-random storage slot locations calculated through hashing algorithms, positioned so far apart that they practically cannot conflict with normal state variables assigned by the Solidity compiler.
The storage slots defined by the standard are:
-
Implementation Slot (Logic Contract Address):
- Stores the address of the implementation contract.
- Formula:
bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) - Value:
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
-
Admin Slot (Admin Address):
- Stores the address of the admin authorized to upgrade the contract.
- Formula:
bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1) - Value:
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
-
Beacon Slot (Beacon Address):
- Used in the Beacon Proxy pattern, stores the address of the Beacon contract.
- Formula:
bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1) - Value:
0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50
Key Features¶
- Standardization: Block explorers (such as Etherscan) can recognize these slots, automatically detecting whether a contract is a proxy and displaying "Read as Proxy" and "Write as Proxy" functionality.
- Security: Ensures that the proxy contract's critical configuration cannot be accidentally overwritten by the logic contract.
- Unstructured Storage: This pattern is called "unstructured storage" because these variables are not declared in Solidity's regular storage layout.