This repository contains a minimal proxy contract that implements EIP-1967 storage slots.
🚨 This contract is NOT intended for production use—it is purely for educational and referential purposes.
This repository showcases the implementation of an upgradeable proxy contract that follows EIP-1967: Standard Proxy Storage Slots.
It leverages OpenZeppelin's delegatecall approach using low-level assembly for efficiency.
- Minimalistic proxy contract structure
- EIP-1967 standard slots for
admin
andimplementation
- Delegatecall-based execution flow
- Admin-controlled upgradability
- OpenZeppelin-inspired assembly implementation
A proxy contract is a smart contract that delegates calls to an implementation contract.
This allows upgradability, meaning the logic can change without modifying the storage.
- Prevents storage collision between proxy and implementation contracts.
- Defines a predictable location for storing
implementation
andadmin
addresses. - Ensures compatibility across different upgradeable patterns.
Slot Name | Value |
---|---|
IMPLEMENTATION_SLOT |
keccak256("eip1967.proxy.implementation") - 1 |
ADMIN_SLOT |
keccak256("eip1967.proxy.admin") - 1 |
🔗 Reference: EIP-1967
- The proxy contract does not contain logic but forwards calls via
delegatecall()
. - It stores the implementation contract address in the EIP-1967 slot.
- The admin can call
upgradeTo(newImplementation)
. - The proxy updates the implementation contract address.
- Storage remains unchanged, but the contract logic is updated.
- Any function calls go to
_delegate()
, executing them in the implementation contract's context.
This contract uses inline assembly (delegatecall
) from OpenZeppelin's Proxy.sol.
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}