Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @title Transparent Upgradeable Proxy (EIP-1967)
/// @notice Delegates calls to an implementation; admin can upgrade.
/// @dev Admin cannot call logic functions through proxy (transparent proxy), to avoid confusion with user calls.
contract Proxy {
bytes32 private constant _IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
bytes32 private constant _ADMIN_SLOT = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1);
event Upgraded(address indexed implementation);
event AdminChanged(address previousAdmin, address newAdmin);
constructor(address logic, address admin_, bytes memory data) payable {
require(logic != address(0), "Proxy: zero logic");
require(admin_ != address(0), "Proxy: zero admin");
_setAdmin(admin_);
_setImplementation(logic);
if (data.length > 0) {
(bool ok, ) = logic.delegatecall(data);
require(ok, "Proxy: init failed");
}
}
/*/////////////// Admin-only management ///////////////*/
/// @notice Return current admin.
function admin() public view returns (address) {
return _admin();
}
/// @notice Return current implementation.
function implementation() public view returns (address) {
return _implementation();
}
/// @notice Admin-only: upgrade implementation.
function upgradeTo(address newImplementation) external ifAdmin {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/// @notice Admin-only: upgrade and then call (e.g., initialize).
function upgradeToAndCall(address newImplementation, bytes calldata data)
external
payable
ifAdmin
{
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
(bool ok, ) = newImplementation.delegatecall(data);
require(ok, "Proxy: delegate init failed");
}
/// @notice Admin-only: change admin.
function changeAdmin(address newAdmin) external ifAdmin {
require(newAdmin != address(0), "Proxy: zero newAdmin");
emit AdminChanged(_admin(), newAdmin);
_setAdmin(newAdmin);
}
/// @dev Admin gating: if caller is admin, run admin-view; otherwise delegate like normal user.
modifier ifAdmin() {
if (msg.sender == _admin()) {
_;
} else {
_delegate(_implementation());
}
}
/*//////////////////// Fallback & Receive ////////////////////*/
fallback() external payable {
_delegate(_implementation());
}
receive() external payable {
_delegate(_implementation());
}
/*//////////////////// Internal utils ////////////////////*/
function _implementation() internal view returns (address impl) {
bytes32 slot = _IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _admin() internal view returns (address adm) {
bytes32 slot = _ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
function _setImplementation(address newImpl) internal {
require(newImpl.code.length > 0, "Proxy: impl not a contract");
bytes32 slot = _IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImpl)
}
}
function _setAdmin(address newAdmin) internal {
bytes32 slot = _ADMIN_SLOT;
assembly {
sstore(slot, newAdmin)
}
}
/// @dev Delegate helper (no return to Solidity; returns/reverts using assembly).
function _delegate(address impl) internal {
assembly {
// copy calldata to memory
calldatacopy(0, 0, calldatasize())
// delegatecall to implementation
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
// copy returndata
returndatacopy(0, 0, returndatasize())
// bubble
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
Submitted on: 2025-10-21 12:18:33
Comments
Log in to comment.
No comments yet.