Address Details
contract

0x03232aBE800D1638B30432FeEF300581De323a4E

Contract Name
WitnetDeployer
Creator
0xf121b7–f0694d at 0xf04c16–0cda1e
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
14 Transactions
Transfers
3 Transfers
Gas Used
36,008,965
Last Balance Update
26673985
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
WitnetDeployer




Optimization enabled
true
Compiler version
v0.8.25+commit.b61c2a91




Optimization runs
200
EVM Version
paris




Verified at
2024-05-24T15:29:50.962808Z

project:/contracts/core/WitnetDeployer.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./WitnetProxy.sol";
import "../libs/Create3.sol";

/// @notice WitnetDeployer contract used both as CREATE2 (EIP-1014) factory for Witnet artifacts, 
/// @notice and CREATE3 (EIP-3171) factory for Witnet proxies.
/// @author Guillermo Díaz <guillermo@otherplane.com>

contract WitnetDeployer {

    /// @notice Use given `_initCode` and `_salt` to deploy a contract into a deterministic address. 
    /// @dev The address of deployed address will be determined by both the `_initCode` and the `_salt`, but not the address
    /// @dev nor the nonce of the caller (i.e. see EIP-1014). 
    /// @param _initCode Creation code, including construction logic and input parameters.
    /// @param _salt Arbitrary value to modify resulting address.
    /// @return _deployed Just deployed contract address.
    function deploy(bytes memory _initCode, bytes32 _salt)
        external
        returns (address _deployed)
    {
        _deployed = determineAddr(_initCode, _salt);
        if (_deployed.code.length == 0) {
            assembly {
                _deployed := create2(0, add(_initCode, 0x20), mload(_initCode), _salt)
            }
            require(_deployed != address(0), "WitnetDeployer: deployment failed");
        }
    }

    /// @notice Determine counter-factual address of the contract that would be deployed by the given `_initCode` and a `_salt`.
    /// @param _initCode Creation code, including construction logic and input parameters.
    /// @param _salt Arbitrary value to modify resulting address.
    /// @return Deterministic contract address.
    function determineAddr(bytes memory _initCode, bytes32 _salt)
        public view
        returns (address)
    {
        return address(
            uint160(uint(keccak256(
                abi.encodePacked(
                    bytes1(0xff),
                    address(this),
                    _salt,
                    keccak256(_initCode)
                )
            )))
        );
    }

    function determineProxyAddr(bytes32 _salt) 
        public view
        returns (address)
    {
        return Create3.determineAddr(_salt);
    }

    function proxify(bytes32 _proxySalt, address _firstImplementation, bytes memory _initData)
        external 
        returns (WitnetProxy)
    {
        address _proxyAddr = determineProxyAddr(_proxySalt);
        if (_proxyAddr.code.length == 0) {
            // deploy the WitnetProxy
            Create3.deploy(_proxySalt, type(WitnetProxy).creationCode);
            // settle first implementation address,
            WitnetProxy(payable(_proxyAddr)).upgradeTo(
                _firstImplementation, 
                // and initialize it, providing
                abi.encode(
                    // the owner (i.e. the caller of this function)
                    msg.sender,
                    // and some (optional) initialization data
                     _initData
                )
            );
            return WitnetProxy(payable(_proxyAddr));
        } else {
            revert("WitnetDeployer: already proxified");
        }
    }

}
        

/@openzeppelin/contracts/utils/introspection/ERC165.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
          

/@openzeppelin/contracts/utils/introspection/IERC165.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
          

/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}
          

/project:/contracts/core/WitnetProxy.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;

import "../patterns/Upgradeable.sol";

/// @title WitnetProxy: upgradable delegate-proxy contract. 
/// @author Guillermo Díaz <guillermo@otherplane.com>
contract WitnetProxy {

    /// Event emitted every time the implementation gets updated.
    event Upgraded(address indexed implementation);  

    /// Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470).
    constructor () {}

    receive() virtual external payable {}

    /// Payable fallback accepts delegating calls to payable functions.  
    fallback() external payable { /* solhint-disable no-complex-fallback */
        address _implementation = implementation();
        assembly { /* solhint-disable avoid-low-level-calls */
            // Gas optimized delegate call to 'implementation' contract.
            // Note: `msg.data`, `msg.sender` and `msg.value` will be passed over 
            //       to actual implementation of `msg.sig` within `implementation` contract.
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize())
            let result := delegatecall(gas(), _implementation, ptr, calldatasize(), 0, 0)
            let size := returndatasize()
            returndatacopy(ptr, 0, size)
            switch result
                case 0  { 
                    // pass back revert message:
                    revert(ptr, size) 
                }
                default {
                  // pass back same data as returned by 'implementation' contract:
                  return(ptr, size) 
                }
        }
    }

    /// Returns proxy's current implementation address.
    function implementation() public view returns (address) {
        return __proxySlot().implementation;
    }

    /// Upgrades the `implementation` address.
    /// @param _newImplementation New implementation address.
    /// @param _initData Raw data with which new implementation will be initialized.
    /// @return Returns whether new implementation would be further upgradable, or not.
    function upgradeTo(address _newImplementation, bytes memory _initData)
        public returns (bool)
    {
        // New implementation cannot be null:
        require(_newImplementation != address(0), "WitnetProxy: null implementation");

        address _oldImplementation = implementation();
        if (_oldImplementation != address(0)) {
            // New implementation address must differ from current one:
            require(_newImplementation != _oldImplementation, "WitnetProxy: nothing to upgrade");

            // Assert whether current implementation is intrinsically upgradable:
            try Upgradeable(_oldImplementation).isUpgradable() returns (bool _isUpgradable) {
                require(_isUpgradable, "WitnetProxy: not upgradable");
            } catch {
                revert("WitnetProxy: unable to check upgradability");
            }

            // Assert whether current implementation allows `msg.sender` to upgrade the proxy:
            (bool _wasCalled, bytes memory _result) = _oldImplementation.delegatecall(
                abi.encodeWithSignature(
                    "isUpgradableFrom(address)",
                    msg.sender
                )
            );
            require(_wasCalled, "WitnetProxy: uncompliant implementation");
            require(abi.decode(_result, (bool)), "WitnetProxy: not authorized");
            require(
                Upgradeable(_oldImplementation).proxiableUUID() == Upgradeable(_newImplementation).proxiableUUID(),
                "WitnetProxy: proxiableUUIDs mismatch"
            );
        }

        // Initialize new implementation within proxy-context storage:
        (bool _wasInitialized, bytes memory _returnData) = _newImplementation.delegatecall(
            abi.encodeWithSignature(
                "initialize(bytes)",
                _initData
            )
        );
        if (!_wasInitialized) {
            if (_returnData.length < 68) {
                revert("WitnetProxy: initialization failed");
            } else {
                assembly {
                    _returnData := add(_returnData, 0x04)
                }
                revert(abi.decode(_returnData, (string)));
            }
        }

        // If all checks and initialization pass, update implementation address:
        __proxySlot().implementation = _newImplementation;
    
        emit Upgraded(_newImplementation);

        // Asserts new implementation complies w/ minimal implementation of Upgradeable interface:
        try Upgradeable(_newImplementation).isUpgradable() returns (bool _isUpgradable) {
            return _isUpgradable;
        }
        catch {
            revert ("WitnetProxy: uncompliant implementation");
        }
    }

    /// @dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address.
    function __proxySlot() private pure returns (Proxiable.ProxiableSlot storage _slot) {
        assembly {
            // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
            _slot.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
        }
    }

}
          

/project:/contracts/libs/Create3.sol

// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity ^0.8.0;

/// @notice Deploy to deterministic addresses without an initcode factor.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)
/// @author 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)

library Create3 {

    //--------------------------------------------------------------------------------//
    // Opcode     | Opcode + Arguments    | Description      | Stack View             //
    //--------------------------------------------------------------------------------//
    // 0x36       |  0x36                 | CALLDATASIZE     | size                   //
    // 0x3d       |  0x3d                 | RETURNDATASIZE   | 0 size                 //
    // 0x3d       |  0x3d                 | RETURNDATASIZE   | 0 0 size               //
    // 0x37       |  0x37                 | CALLDATACOPY     |                        //
    // 0x36       |  0x36                 | CALLDATASIZE     | size                   //
    // 0x3d       |  0x3d                 | RETURNDATASIZE   | 0 size                 //
    // 0x34       |  0x34                 | CALLVALUE        | value 0 size           //
    // 0xf0       |  0xf0                 | CREATE           | newContract            //
    //--------------------------------------------------------------------------------//
    // Opcode     | Opcode + Arguments    | Description      | Stack View             //
    //--------------------------------------------------------------------------------//
    // 0x67       |  0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode   | bytecode               //
    // 0x3d       |  0x3d                 | RETURNDATASIZE   | 0 bytecode             //
    // 0x52       |  0x52                 | MSTORE           |                        //
    // 0x60       |  0x6008               | PUSH1 08         | 8                      //
    // 0x60       |  0x6018               | PUSH1 18         | 24 8                   //
    // 0xf3       |  0xf3                 | RETURN           |                        //
    //--------------------------------------------------------------------------------//
    
    bytes internal constant CREATE3_FACTORY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3";
    bytes32 internal constant CREATE3_FACTORY_CODEHASH = keccak256(CREATE3_FACTORY_BYTECODE);

    /// @notice Creates a new contract with given `_creationCode` and `_salt`
    /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only
    /// @param _creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address
    /// @return addr of the deployed contract, reverts on error
    function deploy(bytes32 _salt, bytes memory _creationCode)
        internal 
        returns (address)
    {
        return deploy(_salt, _creationCode, 0);
    }

    /// @notice Creates a new contract with given `_creationCode`, `_salt` and `_value`. 
    /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only
    /// @param _creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address
    /// @param _value In WEI of ETH to be forwarded to child contract
    /// @return _deployed The address of the deployed contract.
    function deploy(bytes32 _salt, bytes memory _creationCode, uint256 _value)
        internal
        returns (address _deployed)
    {
        // Get target final address
        _deployed = determineAddr(_salt);
        if (_deployed.code.length != 0) revert("Create3: target already exists");

        // Create factory
        address _factory;
        bytes memory _factoryBytecode = CREATE3_FACTORY_BYTECODE;
        /// @solidity memory-safe-assembly
        assembly {
            // Deploy a factory contract with our pre-made bytecode via CREATE2.
            // We start 32 bytes into the code to avoid copying the byte length.
            _factory := create2(0, add(_factoryBytecode, 32), mload(_factoryBytecode), _salt)
        }
        require(_factory != address(0), "Create3: error creating factory");       

        // Use factory to deploy target
        (bool _success, ) = _factory.call{value: _value}(_creationCode);
        require(_success && _deployed.code.length != 0, "Create3: error creating target");
    }

    /// @notice Computes the resulting address of a contract deployed using address(this) and the given `_salt`
    /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only
    /// @return addr of the deployed contract, reverts on error
    /// @dev The address creation formula is: keccak256(rlp([keccak256(0xff ++ address(this) ++ _salt ++ keccak256(childBytecode))[12:], 0x01]))
    function determineAddr(bytes32 _salt) internal view returns (address) {
        address _factory = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex'ff',
                            address(this),
                            _salt,
                            CREATE3_FACTORY_CODEHASH
                        )
                    )
                )
            )
        );
        return address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ _factory ++ 0x01)
                            // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
                            hex"d6_94",
                            _factory,
                            // _factory's nonce on which the target is created: 0x1
                            hex"01"
                        )
                    )
                )
            )
        );
    }

}
          

/project:/contracts/patterns/Initializable.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
          

/project:/contracts/patterns/Proxiable.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.9.0;

abstract contract Proxiable {
    /// @dev Complying with EIP-1822: Universal Upgradeable Proxy Standard (UUPS)
    /// @dev See https://eips.ethereum.org/EIPS/eip-1822.
    function proxiableUUID() virtual external view returns (bytes32);

    struct ProxiableSlot {
        address implementation;
        address proxy;
        bytes32 codehash;
    }

    function __implementation() internal view returns (address) {
        return __proxiable().implementation;
    }

    function __proxy() internal view returns (address) {
        return __proxiable().proxy;
    }

    function __proxiable() internal pure returns (ProxiableSlot storage proxiable) {
        assembly {
            // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
            proxiable.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
        }
    }
}
          

/project:/contracts/patterns/Upgradeable.sol

// SPDX-License-Identifier: MIT

/* solhint-disable var-name-mixedcase */

pragma solidity >=0.6.0 <0.9.0;

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

import "./Initializable.sol";
import "./Proxiable.sol";

abstract contract Upgradeable is Initializable, Proxiable {

    address internal immutable _BASE;
    bytes32 internal immutable _CODEHASH;
    bool internal immutable _UPGRADABLE;

    modifier onlyDelegateCalls virtual {
        require(
            address(this) != _BASE,
            "Upgradeable: not a delegate call"
        );
        _;
    }

    /// Emitted every time the contract gets upgraded.
    /// @param from The address who ordered the upgrading. Namely, the WRB operator in "trustable" implementations.
    /// @param baseAddr The address of the new implementation contract.
    /// @param baseCodehash The EVM-codehash of the new implementation contract.
    /// @param versionTag Ascii-encoded version literal with which the implementation deployer decided to tag it.
    event Upgraded(
        address indexed from,
        address indexed baseAddr,
        bytes32 indexed baseCodehash,
        string  versionTag
    );

    constructor (bool _isUpgradable) {
        address _base = address(this);
        _BASE = _base;
        _UPGRADABLE = _isUpgradable;
    }

    /// @dev Retrieves base contract. Differs from address(this) when called via delegate-proxy pattern.
    function base() public view returns (address) {
        return _BASE;
    }

    /// @dev Retrieves the immutable codehash of this contract, even if invoked as delegatecall.
    function codehash() public view returns (bytes32 _codehash) {
        address _base = _BASE;
        assembly {
            _codehash := extcodehash(_base)
        }
    }

    /// @dev Determines whether the logic of this contract is potentially upgradable.
    function isUpgradable() public view returns (bool) {
        return _UPGRADABLE;
    }

    /// @dev Tells whether provided address could eventually upgrade the contract.
    function isUpgradableFrom(address from) virtual external view returns (bool);

    /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy.    
    /// @dev Must fail when trying to upgrade to same logic contract more than once.
    function initialize(bytes memory) virtual external;

    /// @dev Retrieves human-redable named version of current implementation.
    function version() virtual public view returns (string memory); 
}
          

Compiler Settings

{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"project:/contracts/core/WitnetDeployer.sol":"WitnetDeployer"}}
              

Contract ABI

[{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"_deployed","internalType":"address"}],"name":"deploy","inputs":[{"type":"bytes","name":"_initCode","internalType":"bytes"},{"type":"bytes32","name":"_salt","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"determineAddr","inputs":[{"type":"bytes","name":"_initCode","internalType":"bytes"},{"type":"bytes32","name":"_salt","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"determineProxyAddr","inputs":[{"type":"bytes32","name":"_salt","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"contract WitnetProxy"}],"name":"proxify","inputs":[{"type":"bytes32","name":"_proxySalt","internalType":"bytes32"},{"type":"address","name":"_firstImplementation","internalType":"address"},{"type":"bytes","name":"_initData","internalType":"bytes"}]}]
              

Contract Creation Code

0x6080604052348015600f57600080fd5b506111df8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634998f038146100515780634af63f02146100805780635ba489e714610093578063d3933c29146100a6575b600080fd5b61006461005f36600461059b565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e366004610657565b6100ca565b6100646100a136600461069c565b61015b565b6100646100b4366004610657565b61029b565b60006100c4826102f7565b92915050565b60006100d6838361029b565b9050806001600160a01b03163b6000036100c457818351602085016000f590506001600160a01b0381166100c45760405162461bcd60e51b815260206004820152602160248201527f5769746e65744465706c6f7965723a206465706c6f796d656e74206661696c656044820152601960fa1b60648201526084015b60405180910390fd5b600080610167856100b9565b9050806001600160a01b03163b600003610242576101a7856040518060200161018f9061058e565b601f1982820381018352601f909101166040526103ca565b50806001600160a01b0316636fbc15e98533866040516020016101cb929190610725565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016101f7929190610725565b6020604051808303816000875af1158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a9190610767565b509050610294565b60405162461bcd60e51b815260206004820152602160248201527f5769746e65744465706c6f7965723a20616c72656164792070726f78696669656044820152601960fa1b6064820152608401610152565b9392505050565b8151602092830120604080516001600160f81b0319818601523060601b6bffffffffffffffffffffffff191660218201526035810193909352605580840192909252805180840390920182526075909201909152805191012090565b604080518082018252601081526f67363d3d37363d34f03d5260086018f360801b60209182015281516001600160f81b03198183015230606090811b6bffffffffffffffffffffffff19908116602184015260358301959095527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605580840191909152845180840390910181526075830185528051908401206135a560f21b6095840152901b9093166097840152600160f81b60ab8401528151608c81850301815260ac909301909152815191012090565b600061029483836000806103dd846102f7565b90506001600160a01b0381163b156104375760405162461bcd60e51b815260206004820152601e60248201527f437265617465333a2074617267657420616c72656164792065786973747300006044820152606401610152565b6040805180820190915260108082526f67363d3d37363d34f03d5260086018f360801b6020830190815260009291879184f591506001600160a01b0382166104c15760405162461bcd60e51b815260206004820152601f60248201527f437265617465333a206572726f72206372656174696e6720666163746f7279006044820152606401610152565b6000826001600160a01b031685876040516104dc9190610789565b60006040518083038185875af1925050503d8060008114610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b5050905080801561053857506001600160a01b0384163b15155b6105845760405162461bcd60e51b815260206004820152601e60248201527f437265617465333a206572726f72206372656174696e672074617267657400006044820152606401610152565b5050509392505050565b610a04806107a683390190565b6000602082840312156105ad57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126105db57600080fd5b813567ffffffffffffffff808211156105f6576105f66105b4565b604051601f8301601f19908116603f0116810190828211818310171561061e5761061e6105b4565b8160405283815286602085880101111561063757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561066a57600080fd5b823567ffffffffffffffff81111561068157600080fd5b61068d858286016105ca565b95602094909401359450505050565b6000806000606084860312156106b157600080fd5b8335925060208401356001600160a01b03811681146106cf57600080fd5b9150604084013567ffffffffffffffff8111156106eb57600080fd5b6106f7868287016105ca565b9150509250925092565b60005b8381101561071c578181015183820152602001610704565b50506000910152565b60018060a01b03831681526040602082015260008251806040840152610752816060850160208701610701565b601f01601f1916919091016060019392505050565b60006020828403121561077957600080fd5b8151801515811461029457600080fd5b6000825161079b818460208701610701565b919091019291505056fe6080604052348015600f57600080fd5b506109e58061001f6000396000f3fe60806040526004361061002d5760003560e01c80635c60da1b146100655780636fbc15e91461009757610034565b3661003457005b600061003e6100c7565b905060405136600082376000803683855af43d806000843e818015610061578184f35b8184fd5b34801561007157600080fd5b5061007a6100c7565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100a357600080fd5b506100b76100b2366004610791565b6100f5565b604051901515815260200161008e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60006001600160a01b0383166101525760405162461bcd60e51b815260206004820181905260248201527f5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e60448201526064015b60405180910390fd5b600061015c6100c7565b90506001600160a01b0381161561050857806001600160a01b0316846001600160a01b0316036101ce5760405162461bcd60e51b815260206004820152601f60248201527f5769746e657450726f78793a206e6f7468696e6720746f2075706772616465006044820152606401610149565b806001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610228575060408051601f3d908101601f1916820190925261022591810190610830565b60015b6102875760405162461bcd60e51b815260206004820152602a60248201527f5769746e657450726f78793a20756e61626c6520746f20636865636b207570676044820152697261646162696c69747960b01b6064820152608401610149565b806102d45760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f742075706772616461626c6500000000006044820152606401610149565b5060405133602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166335ac4b0560e11b17905251610326919061087d565b600060405180830381855af49150503d8060008114610361576040519150601f19603f3d011682016040523d82523d6000602084013e610366565b606091505b5091509150816103885760405162461bcd60e51b815260040161014990610899565b8080602001905181019061039c9190610830565b6103e85760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f7420617574686f72697a656400000000006044820152606401610149565b856001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a91906108e0565b836001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ac91906108e0565b146105055760405162461bcd60e51b8152602060048201526024808201527f5769746e657450726f78793a2070726f786961626c655555494473206d69736d6044820152630c2e8c6d60e31b6064820152608401610149565b50505b600080856001600160a01b0316856040516024016105269190610925565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161055b919061087d565b600060405180830381855af49150503d8060008114610596576040519150601f19603f3d011682016040523d82523d6000602084013e61059b565b606091505b509150915081610635576044815110156106025760405162461bcd60e51b815260206004820152602260248201527f5769746e657450726f78793a20696e697469616c697a6174696f6e206661696c604482015261195960f21b6064820152608401610149565b6004810190508080602001905181019061061c9190610938565b60405162461bcd60e51b81526004016101499190610925565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0388169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2856001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156106f5575060408051601f3d908101601f191682019092526106f291810190610830565b60015b6107115760405162461bcd60e51b815260040161014990610899565b935061071c92505050565b92915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561076157610761610722565b604052919050565b600067ffffffffffffffff82111561078357610783610722565b50601f01601f191660200190565b600080604083850312156107a457600080fd5b82356001600160a01b03811681146107bb57600080fd5b9150602083013567ffffffffffffffff8111156107d757600080fd5b8301601f810185136107e857600080fd5b80356107fb6107f682610769565b610738565b81815286602083850101111561081057600080fd5b816020840160208301376000602083830101528093505050509250929050565b60006020828403121561084257600080fd5b8151801515811461085257600080fd5b9392505050565b60005b8381101561087457818101518382015260200161085c565b50506000910152565b6000825161088f818460208701610859565b9190910192915050565b60208082526027908201527f5769746e657450726f78793a20756e636f6d706c69616e7420696d706c656d65604082015266373a30ba34b7b760c91b606082015260800190565b6000602082840312156108f257600080fd5b5051919050565b60008151808452610911816020860160208601610859565b601f01601f19169290920160200192915050565b60208152600061085260208301846108f9565b60006020828403121561094a57600080fd5b815167ffffffffffffffff81111561096157600080fd5b8201601f8101841361097257600080fd5b80516109806107f682610769565b81815285602083850101111561099557600080fd5b6109a6826020830160208601610859565b9594505050505056fea2646970667358221220e37aca81612109730c6d979a2dc30dfaa18ce29f198f4cab061b20e2116219f164736f6c63430008190033a26469706673582212206fe1b3dd8a286e7bb68c1180548cd2d9b44f0b5aad09151e5cd92359a367dcd064736f6c63430008190033

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80634998f038146100515780634af63f02146100805780635ba489e714610093578063d3933c29146100a6575b600080fd5b61006461005f36600461059b565b6100b9565b6040516001600160a01b03909116815260200160405180910390f35b61006461008e366004610657565b6100ca565b6100646100a136600461069c565b61015b565b6100646100b4366004610657565b61029b565b60006100c4826102f7565b92915050565b60006100d6838361029b565b9050806001600160a01b03163b6000036100c457818351602085016000f590506001600160a01b0381166100c45760405162461bcd60e51b815260206004820152602160248201527f5769746e65744465706c6f7965723a206465706c6f796d656e74206661696c656044820152601960fa1b60648201526084015b60405180910390fd5b600080610167856100b9565b9050806001600160a01b03163b600003610242576101a7856040518060200161018f9061058e565b601f1982820381018352601f909101166040526103ca565b50806001600160a01b0316636fbc15e98533866040516020016101cb929190610725565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016101f7929190610725565b6020604051808303816000875af1158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a9190610767565b509050610294565b60405162461bcd60e51b815260206004820152602160248201527f5769746e65744465706c6f7965723a20616c72656164792070726f78696669656044820152601960fa1b6064820152608401610152565b9392505050565b8151602092830120604080516001600160f81b0319818601523060601b6bffffffffffffffffffffffff191660218201526035810193909352605580840192909252805180840390920182526075909201909152805191012090565b604080518082018252601081526f67363d3d37363d34f03d5260086018f360801b60209182015281516001600160f81b03198183015230606090811b6bffffffffffffffffffffffff19908116602184015260358301959095527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f605580840191909152845180840390910181526075830185528051908401206135a560f21b6095840152901b9093166097840152600160f81b60ab8401528151608c81850301815260ac909301909152815191012090565b600061029483836000806103dd846102f7565b90506001600160a01b0381163b156104375760405162461bcd60e51b815260206004820152601e60248201527f437265617465333a2074617267657420616c72656164792065786973747300006044820152606401610152565b6040805180820190915260108082526f67363d3d37363d34f03d5260086018f360801b6020830190815260009291879184f591506001600160a01b0382166104c15760405162461bcd60e51b815260206004820152601f60248201527f437265617465333a206572726f72206372656174696e6720666163746f7279006044820152606401610152565b6000826001600160a01b031685876040516104dc9190610789565b60006040518083038185875af1925050503d8060008114610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b5050905080801561053857506001600160a01b0384163b15155b6105845760405162461bcd60e51b815260206004820152601e60248201527f437265617465333a206572726f72206372656174696e672074617267657400006044820152606401610152565b5050509392505050565b610a04806107a683390190565b6000602082840312156105ad57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126105db57600080fd5b813567ffffffffffffffff808211156105f6576105f66105b4565b604051601f8301601f19908116603f0116810190828211818310171561061e5761061e6105b4565b8160405283815286602085880101111561063757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561066a57600080fd5b823567ffffffffffffffff81111561068157600080fd5b61068d858286016105ca565b95602094909401359450505050565b6000806000606084860312156106b157600080fd5b8335925060208401356001600160a01b03811681146106cf57600080fd5b9150604084013567ffffffffffffffff8111156106eb57600080fd5b6106f7868287016105ca565b9150509250925092565b60005b8381101561071c578181015183820152602001610704565b50506000910152565b60018060a01b03831681526040602082015260008251806040840152610752816060850160208701610701565b601f01601f1916919091016060019392505050565b60006020828403121561077957600080fd5b8151801515811461029457600080fd5b6000825161079b818460208701610701565b919091019291505056fe6080604052348015600f57600080fd5b506109e58061001f6000396000f3fe60806040526004361061002d5760003560e01c80635c60da1b146100655780636fbc15e91461009757610034565b3661003457005b600061003e6100c7565b905060405136600082376000803683855af43d806000843e818015610061578184f35b8184fd5b34801561007157600080fd5b5061007a6100c7565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100a357600080fd5b506100b76100b2366004610791565b6100f5565b604051901515815260200161008e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60006001600160a01b0383166101525760405162461bcd60e51b815260206004820181905260248201527f5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e60448201526064015b60405180910390fd5b600061015c6100c7565b90506001600160a01b0381161561050857806001600160a01b0316846001600160a01b0316036101ce5760405162461bcd60e51b815260206004820152601f60248201527f5769746e657450726f78793a206e6f7468696e6720746f2075706772616465006044820152606401610149565b806001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610228575060408051601f3d908101601f1916820190925261022591810190610830565b60015b6102875760405162461bcd60e51b815260206004820152602a60248201527f5769746e657450726f78793a20756e61626c6520746f20636865636b207570676044820152697261646162696c69747960b01b6064820152608401610149565b806102d45760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f742075706772616461626c6500000000006044820152606401610149565b5060405133602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166335ac4b0560e11b17905251610326919061087d565b600060405180830381855af49150503d8060008114610361576040519150601f19603f3d011682016040523d82523d6000602084013e610366565b606091505b5091509150816103885760405162461bcd60e51b815260040161014990610899565b8080602001905181019061039c9190610830565b6103e85760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f7420617574686f72697a656400000000006044820152606401610149565b856001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044a91906108e0565b836001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ac91906108e0565b146105055760405162461bcd60e51b8152602060048201526024808201527f5769746e657450726f78793a2070726f786961626c655555494473206d69736d6044820152630c2e8c6d60e31b6064820152608401610149565b50505b600080856001600160a01b0316856040516024016105269190610925565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161055b919061087d565b600060405180830381855af49150503d8060008114610596576040519150601f19603f3d011682016040523d82523d6000602084013e61059b565b606091505b509150915081610635576044815110156106025760405162461bcd60e51b815260206004820152602260248201527f5769746e657450726f78793a20696e697469616c697a6174696f6e206661696c604482015261195960f21b6064820152608401610149565b6004810190508080602001905181019061061c9190610938565b60405162461bcd60e51b81526004016101499190610925565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0388169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2856001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156106f5575060408051601f3d908101601f191682019092526106f291810190610830565b60015b6107115760405162461bcd60e51b815260040161014990610899565b935061071c92505050565b92915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561076157610761610722565b604052919050565b600067ffffffffffffffff82111561078357610783610722565b50601f01601f191660200190565b600080604083850312156107a457600080fd5b82356001600160a01b03811681146107bb57600080fd5b9150602083013567ffffffffffffffff8111156107d757600080fd5b8301601f810185136107e857600080fd5b80356107fb6107f682610769565b610738565b81815286602083850101111561081057600080fd5b816020840160208301376000602083830101528093505050509250929050565b60006020828403121561084257600080fd5b8151801515811461085257600080fd5b9392505050565b60005b8381101561087457818101518382015260200161085c565b50506000910152565b6000825161088f818460208701610859565b9190910192915050565b60208082526027908201527f5769746e657450726f78793a20756e636f6d706c69616e7420696d706c656d65604082015266373a30ba34b7b760c91b606082015260800190565b6000602082840312156108f257600080fd5b5051919050565b60008151808452610911816020860160208601610859565b601f01601f19169290920160200192915050565b60208152600061085260208301846108f9565b60006020828403121561094a57600080fd5b815167ffffffffffffffff81111561096157600080fd5b8201601f8101841361097257600080fd5b80516109806107f682610769565b81815285602083850101111561099557600080fd5b6109a6826020830160208601610859565b9594505050505056fea2646970667358221220e37aca81612109730c6d979a2dc30dfaa18ce29f198f4cab061b20e2116219f164736f6c63430008190033a26469706673582212206fe1b3dd8a286e7bb68c1180548cd2d9b44f0b5aad09151e5cd92359a367dcd064736f6c63430008190033