Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xa9B327D591d3593bE33E3EEb7A7F00022754dE82
Balance 0 ETH
Nonce 2
Code Size 164 bytes
Proxy EIP-1967 Proxy Implementation: 0xB2C81d9c...848E
Indexed Transactions 0
External Etherscan · Sourcify

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