Created
December 16, 2023 01:24
-
-
Save Philogy/658d82258e7ede45f43c06d18156fda9 to your computer and use it in GitHub Desktop.
No Assembly Solidity ERC1967 Proxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity 0.8.21; | |
/// @author philogy <https://github.com/philogy> | |
contract Proxy { | |
uint256 internal constant IMPL_SLOT = uint256(keccak256("eip1967.proxy.implementation")) - 1; | |
uint256 internal constant ADMIN_SLOT = uint256(keccak256("eip1967.proxy.admin")) - 1; | |
address[0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff] internal slots; | |
event Upgraded(address indexed implementation); | |
event AdminChanged(address previousAdmin, address newAdmin); | |
error Errored(bytes revertData); | |
error NotAdmin(address caller); | |
constructor(address initialImplementation, address initialAdmin) { | |
_setImplementation(initialImplementation); | |
_setAdmin(initialAdmin); | |
} | |
fallback(bytes calldata data) external payable returns (bytes memory) { | |
(bool success, bytes memory retdata) = slots[IMPL_SLOT].delegatecall(data); | |
if (success) return retdata; | |
else revert Errored(retdata); | |
} | |
function upgradeTo(address newImplementation) external { | |
if (msg.sender != slots[ADMIN_SLOT]) revert NotAdmin(msg.sender); | |
_setImplementation(newImplementation); | |
} | |
function _setAdmin(address admin) internal { | |
emit AdminChanged(slots[ADMIN_SLOT], admin); | |
slots[ADMIN_SLOT] = admin; | |
} | |
function _setImplementation(address impl) internal { | |
slots[IMPL_SLOT] = impl; | |
emit Upgraded(impl); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment