Address Contract Verified
Address
0xa9B327D591d3593bE33E3EEb7A7F00022754dE82
Balance
0 ETH
Nonce
2
Code Size
164 bytes
Creator
Create2 Deployer at tx 0xf2c1b809...8de3ac
Proxy
EIP-1967 Proxy Implementation: 0xB2C81d9c...848E
Indexed Transactions
0
Contract Bytecode
164 bytes
0x608060405236601057600e6013565b005b600e5b6000601b6040565b90503660008037600080366000845af43d6000803e808015603b573d6000f35b3d6000fd5b600060697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b90509056fea2646970667358221220f2ada65c2a34e7e383968726c010fe72d9912c1ac79bd9e50f89695d0808dd6f64736f6c63430008130033
Verified Source Code Full Match
Compiler: v0.8.19+commit.7dd6d404
EVM: paris
Optimization: Yes (1000 runs)
Proxy.sol 109 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { ERC1967Utils } from "./libraries/ERC1967Utils.sol";
/// @dev Initial implementation of an upgradeable proxy.
/// This contract must be deployed as first proxy implementation
/// before any other implementation can be deployed.
contract InitialImplementation {
error NotInitialOwner(address caller);
/// @dev Upgrades the implementation of the proxy to `implementation` and calls `data` on it.
/// If `data` is nonempty, it's used as data in a delegate call to `implementation`.
/// If caller is not the temporary owner of the proxy (saved in the storage slot not(0)), it will revert.
/// Slot not(0) is set to 0 when the proxy is upgraded.
function upgradeTo(address implementation, bytes memory data) external {
assembly ("memory-safe") {
if iszero(eq(caller(), sload(not(0)))) {
// NotInitialOwner selector
mstore(0, 0x483ffb99)
mstore(32, caller())
revert(28, 36)
}
sstore(not(0), 0)
}
ERC1967Utils.upgradeToAndCall(implementation, data);
}
}
/// @dev This contract provides a fallback function that delegates all calls to another contract using the EVM
/// instruction `delegatecall`.
///
/// Delegation to the implementation can be triggered manually through the {_fallback} function.
///
/// The success and return data of the delegated call will be returned back to the caller of the proxy.
contract Proxy {
// =========================
// constructor
// =========================
/// @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
///
/// If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
/// encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
///
/// Requirements:
///
/// - If `data` is empty, `msg.value` must be zero.
constructor(address initialOwner) {
assembly {
sstore(not(0), initialOwner)
}
ERC1967Utils.upgradeToAndCall(address(new InitialImplementation()), bytes(""));
}
// =========================
// fallbacks
// =========================
/// @dev Fallback function that delegates calls to the address returned by `_implementation()`.
/// Will run if no other function in the contract matches the call data.
fallback() external payable {
_fallback();
}
/// @dev Fallback function that delegates calls to the address returned by `_implementation()`.
/// Will run if call data is empty.
receive() external payable {
_fallback();
}
// =========================
// private functions
// =========================
/// @dev Delegates the current call to the address returned by `_implementation()`.
/// This function does not return to its internal call site, it will return directly to the external caller.
function _fallback() private {
address implementation = _implementation();
assembly ("memory-safe") {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
/// @dev This is a function that should returns the address to which the fallback
/// function and {_fallback} should delegate.
function _implementation() private view returns (address) {
return ERC1967Utils.getImplementation();
}
}
ERC1967Utils.sol 97 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
library ERC1967Utils {
// =========================
// immutable storage
// =========================
/// @dev Storage slot with the address of the current implementation.
/// This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
// =========================
// events
// =========================
/// @dev Emitted when the implementation is upgraded.
event Upgraded(address indexed implementation);
// =========================
// errors
// =========================
/// @dev The `implementation` of the proxy is invalid.
error ERC1967_InvalidImplementation(address implementation);
/// @dev An upgrade function sees `msg.value > 0` that may be lost.
error ERC1967_NonPayable();
/// @dev A call to an address target failed. The target may have reverted.
error ERC1967_FailedInnerCall();
// =========================
// main functions
// =========================
/// @dev Returns the current implementation address.
function getImplementation() internal view returns (address implementation) {
assembly ("memory-safe") {
implementation := sload(IMPLEMENTATION_SLOT)
}
}
/// @dev Stores a new address in the EIP1967 implementation slot.
function setImplementation(address newImplementation) internal {
assembly ("memory-safe") {
if iszero(extcodesize(newImplementation)) {
// "ERC1967_InvalidImplementation(address)" selector
mstore(0, 0x4a4a0aa2)
mstore(32, newImplementation)
revert(28, 36)
}
sstore(IMPLEMENTATION_SLOT, newImplementation)
}
}
/// @dev Performs implementation upgrade with additional setup call if data is nonempty.
/// This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
/// to avoid stuck value in the contract.
///
/// Emits an {IERC1967-Upgraded} event.
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length > 0) {
(bool success, bytes memory returndata) = newImplementation.delegatecall(data);
if (!success) {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
revert(add(32, returndata), mload(returndata))
}
} else {
revert ERC1967_FailedInnerCall();
}
}
} else {
_checkNonPayable();
}
}
// =========================
// private functions
// =========================
/// @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
/// if an upgrade doesn't perform an initialization call.
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967_NonPayable();
}
}
}
Recent Transactions
No transactions found for this address