Skip to content

Instantly share code, notes, and snippets.

@Philogy
Created December 16, 2023 01:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Philogy/658d82258e7ede45f43c06d18156fda9 to your computer and use it in GitHub Desktop.
Save Philogy/658d82258e7ede45f43c06d18156fda9 to your computer and use it in GitHub Desktop.
No Assembly Solidity ERC1967 Proxy
// 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