Amoy Testnet

Contract

0x210b6CB2062BF231E43A5D2A7B3be7AeC65F51f0

Overview

POL Balance

Polygon PoS Chain Amoy LogoPolygon PoS Chain Amoy LogoPolygon PoS Chain Amoy Logo0 POL

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
141276452024-11-07 9:06:28138 days ago1730970388  Contract Creation0 POL
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WitPriceFeedsUpgradable

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 47 : WitPriceFeedsUpgradable.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "../WitPriceFeeds.sol";
import "../core/WitnetUpgradableBase.sol";

import "../data/WitPriceFeedsDataLib.sol";

import "../interfaces/IWitFeedsAdmin.sol";
import "../interfaces/IWitFeedsLegacy.sol";
import "../interfaces/IWitPriceFeedsSolverFactory.sol";
import "../interfaces/IWitOracleLegacy.sol";

import "../patterns/Ownable2Step.sol";

/// @title WitPriceFeeds: Price Feeds live repository reliant on the Wit/oracle blockchain.
/// @author Guillermo Díaz <[email protected]>

contract WitPriceFeedsUpgradable
    is
        Ownable2Step,
        WitPriceFeeds,
        WitnetUpgradableBase,
        IWitFeedsAdmin,
        IWitFeedsLegacy,
        IWitPriceFeedsSolverFactory
{
    using Witnet for bytes;
    using Witnet for Witnet.DataResult;
    using Witnet for Witnet.QueryResponse;
    using Witnet for Witnet.QuerySLA;
    using Witnet for Witnet.ResultStatus;


    function class() virtual override public view returns (string memory) {
        return type(WitPriceFeedsUpgradable).name;
    }

    WitOracle immutable public override witOracle;
    WitOracleRadonRegistry immutable internal __registry;

    Witnet.QuerySLA private __defaultRadonSLA;
    uint16 private __baseFeeOverheadPercentage;
    
    constructor(
            WitOracle _witOracle,
            bytes32 _versionTag,
            bool _upgradable
        )
        Ownable(address(msg.sender))
        WitnetUpgradableBase(
            _upgradable,
            _versionTag,
            "io.witnet.proxiable.feeds.price"
        )
    {
        _require(
            address(_witOracle).code.length > 0,
            "inexistent oracle"
        );
        _require(
            _witOracle.specs() == (
                type(IWitAppliance).interfaceId
                    ^ type(IWitOracle).interfaceId
            ), "uncompliant oracle"
        );
        witOracle = _witOracle;
    }

    function _registry() virtual internal view returns (WitOracleRadonRegistry) {
        return witOracle.registry();
    }

    // solhint-disable-next-line payable-fallback
    fallback() override external {
        if (
            msg.sig == IWitPriceFeedsSolver.solve.selector
                && msg.sender == address(this)
        ) {
            address _solver = WitPriceFeedsDataLib.seekRecord(bytes4(bytes8(msg.data) << 32)).solver;
            _require(
                _solver != address(0),
                "unsettled solver"
            );
            assembly {
                let ptr := mload(0x40)
                calldatacopy(ptr, 0, calldatasize())
                let result := delegatecall(gas(), _solver, ptr, calldatasize(), 0, 0)
                let size := returndatasize()
                returndatacopy(ptr, 0, size)
                switch result
                    case 0 { revert(ptr, size) }
                    default { return(ptr, size) }
            }
        } else {
            _revert("not implemented");
        }
    }


    // ================================================================================================================
    // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------

    /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy.
    function __initializeUpgradableData(bytes memory _initData) virtual override internal {
        if (__proxiable().codehash == bytes32(0)) {
            __defaultRadonSLA = Witnet.QuerySLA({
                witCommitteeCapacity: 10,
                witCommitteeUnitaryReward: 2 * 10 ** 8,
                witResultMaxSize: 16,
                witCapability: Witnet.QueryCapability.wrap(0)
            });
            // settle default base fee overhead percentage
            __baseFeeOverheadPercentage = 10;
        
        } else {
            // otherwise, store beacon read from _initData, if any
            if (_initData.length > 0) {
                (uint16 _baseFeeOverheadPercentage, Witnet.QuerySLA memory _defaultRadonSLA) = abi.decode(
                    _initData, (uint16, Witnet.QuerySLA)
                );
                __baseFeeOverheadPercentage = _baseFeeOverheadPercentage;
                __defaultRadonSLA = _defaultRadonSLA;
            } else if (!__defaultRadonSLA.isValid()) {
                // possibly, an upgrade from a previous branch took place:
                __defaultRadonSLA = Witnet.QuerySLA({
                    witCommitteeCapacity: 10,
                    witCommitteeUnitaryReward: 2 * 10 ** 8,
                    witResultMaxSize: 16,
                    witCapability: Witnet.QueryCapability.wrap(0)
                });
            }
        }
        for (uint _ix = 0; _ix < __storage().ids.length; _ix ++) {
            bytes4 _feedId = __storage().ids[_ix];
            WitPriceFeedsDataLib.Record storage __record = WitPriceFeedsDataLib.seekRecord(_feedId);
            __record.lastValidQueryId = Witnet.QueryId.wrap(0);
            __record.latestUpdateQueryId = Witnet.QueryId.wrap(0);
        }
    }


    /// Tells whether provided address could eventually upgrade the contract.
    function isUpgradableFrom(address _from) external view override returns (bool) {
        address _owner = owner();
        return (
            // false if the WRB is intrinsically not upgradable, or `_from` is no owner
            isUpgradable()
                && _owner == _from
        );
    }


    // ================================================================================================================
    // --- Implements 'IWitFeeds' -------------------------------------------------------------------------------------

    function defaultRadonSLA()
        override
        public view
        returns (Witnet.QuerySLA memory)
    {
        return __defaultRadonSLA;
    }

    function estimateUpdateBaseFee(uint256 _evmGasPrice) virtual override public view returns (uint256) {
        return estimateUpdateRequestFee(_evmGasPrice);
    }
    
    function estimateUpdateRequestFee(uint256 _evmGasPrice)
        virtual override
        public view
        returns (uint)
    {
        return (IWitOracleLegacy(address(witOracle)).estimateBaseFee(_evmGasPrice, 32)
            * (100 + __baseFeeOverheadPercentage)
        ) / 100; 
    }
    
    /// @notice Returns unique hash determined by the combination of data sources being used
    /// @notice on non-routed price feeds, and dependencies of routed price feeds.
    /// @dev Ergo, `footprint()` changes if any data source is modified, or the dependecy tree
    /// @dev on any routed price feed is altered.
    function footprint() 
        virtual override
        public view
        returns (bytes4 _footprint)
    {
        if (__storage().ids.length > 0) {
            _footprint = _footprintOf(__storage().ids[0]);
            for (uint _ix = 1; _ix < __storage().ids.length; _ix ++) {
                _footprint ^= _footprintOf(__storage().ids[_ix]);
            }
        }
    }

    function hash(string memory caption)
        virtual override
        public pure
        returns (bytes4)
    {
        return WitPriceFeedsDataLib.hash(caption);
    }

    function lookupCaption(bytes4 feedId)
        override
        public view
        returns (string memory)
    {
        return WitPriceFeedsDataLib.seekRecord(feedId).caption;
    }

    function supportedFeeds()
        virtual override
        external view
        returns (bytes4[] memory _ids, string[] memory _captions, bytes32[] memory _solvers)
    {
        return WitPriceFeedsDataLib.supportedFeeds();
    }
    
    function supportsCaption(string calldata caption)
        virtual override
        external view
        returns (bool)
    {
        bytes4 feedId = hash(caption);
        return hash(WitPriceFeedsDataLib.seekRecord(feedId).caption) == feedId;
    }
    
    function totalFeeds() 
        override 
        external view
        returns (uint256)
    {
        return __storage().ids.length;
    }

    function lastValidQueryId(bytes4 feedId)
        override public view
        returns (Witnet.QueryId)
    {
        return WitPriceFeedsDataLib.lastValidQueryId(witOracle, feedId);
    }

    function lastValidQueryResponse(bytes4 feedId)
        override public view
        returns (Witnet.QueryResponse memory)
    {
        return witOracle.getQueryResponse(
            WitPriceFeedsDataLib.lastValidQueryId(witOracle, feedId)
        );
    }

    function latestUpdateQueryId(bytes4 feedId)
        override public view
        returns (Witnet.QueryId)
    {
        return WitPriceFeedsDataLib.seekRecord(feedId).latestUpdateQueryId;
    }

    function latestUpdateQueryRequest(bytes4 feedId)
        override external view 
        returns (Witnet.QueryRequest memory)
    {
        return witOracle.getQueryRequest(latestUpdateQueryId(feedId));
    }

    function latestUpdateQueryResult(bytes4 feedId)
        override external view
        returns (Witnet.DataResult memory)
    {
        return witOracle.getQueryResult(latestUpdateQueryId(feedId));
    }

    function latestUpdateQueryResultStatus(bytes4 feedId)
        override public view
        returns (Witnet.ResultStatus)
    {
        return WitPriceFeedsDataLib.latestUpdateQueryResultStatus(witOracle, feedId);
    }

    function latestUpdateQueryResultStatusDescription(bytes4 feedId) 
        override external view
        returns (string memory)
    {
        return witOracle.getQueryResultStatusDescription(
            latestUpdateQueryId(feedId)
        );
    }

    function lookupWitOracleRequestBytecode(bytes4 feedId)
        override public view
        returns (bytes memory)
    {
        WitPriceFeedsDataLib.Record storage __record = WitPriceFeedsDataLib.seekRecord(feedId);
        _require(
            __record.radHash != 0,
            "no RAD hash"
        );
        return _registry().bytecodeOf(__record.radHash);
    }

    function lookupWitOracleRequestRadHash(bytes4 feedId)
        override public view
        returns (bytes32)
    {
        return WitPriceFeedsDataLib.seekRecord(feedId).radHash;
    }

    function lookupWitOracleRadonRetrievals(bytes4 feedId)
        override external view
        returns (Witnet.RadonRetrieval[] memory _retrievals)
    {
        return _registry().lookupRadonRequestRetrievals(
            lookupWitOracleRequestRadHash(feedId)
        );
    }

    function requestUpdate(bytes4 feedId)
        external payable
        virtual override
        returns (uint256)
    {
        return __requestUpdate(feedId, __defaultRadonSLA);
    }
    
    function requestUpdate(bytes4 feedId, Witnet.QuerySLA calldata updateSLA)
        public payable
        virtual override
        returns (uint256)
    {
        _require(
            updateSLA.equalOrGreaterThan(__defaultRadonSLA),
            "unsecure update request"
        );
        return __requestUpdate(feedId, updateSLA);
    }
    

    /// ===============================================================================================================
    /// --- IWitFeedsLegacy -------------------------------------------------------------------------------------------
    
    function latestUpdateResponse(bytes4 feedId) 
        override external view 
        returns (Witnet.QueryResponse memory)
    {
        return witOracle.getQueryResponse(latestUpdateQueryId(feedId));
    }

    function latestUpdateResponseStatus(bytes4 feedId)
        override public view
        returns (IWitOracleLegacy.QueryResponseStatus)
    {
        return IWitOracleLegacy(address(witOracle)).getQueryResponseStatus(
            Witnet.QueryId.unwrap(latestUpdateQueryId(feedId))
        );
    }

    function latestUpdateResultError(bytes4 feedId)
        override external view 
        returns (IWitOracleLegacy.ResultError memory)
    {
        return IWitOracleLegacy(address(witOracle)).getQueryResultError(Witnet.QueryId.unwrap(latestUpdateQueryId(feedId)));
    }

    function lookupWitnetBytecode(bytes4 feedId) 
        override external view
        returns (bytes memory)
    {
        return lookupWitOracleRequestBytecode(feedId);
    }
    
    function requestUpdate(bytes4 feedId, IWitFeedsLegacy.RadonSLA calldata updateSLA)
        external payable
        virtual override
        returns (uint256)
    {
        return __requestUpdate(
            feedId, 
            Witnet.QuerySLA({
                witCommitteeCapacity: updateSLA.witCommitteeCapacity,
                witCommitteeUnitaryReward: updateSLA.witCommitteeUnitaryReward,
                witResultMaxSize: __defaultRadonSLA.witResultMaxSize,
                witCapability: Witnet.QueryCapability.wrap(0)
            })
        );
    }

    function witnet() virtual override external view returns (address) {
        return address(witOracle);
    }


    // ================================================================================================================
    // --- Implements 'IWitFeedsAdmin' -----------------------------------------------------------------------------

    function owner()
        virtual override (IWitFeedsAdmin, Ownable)
        public view 
        returns (address)
    {
        return Ownable.owner();
    }
    
    function acceptOwnership()
        virtual override (IWitFeedsAdmin, Ownable2Step)
        public
    {
        Ownable2Step.acceptOwnership();
    }

    function baseFeeOverheadPercentage()
        virtual override
        external view
        returns (uint16)
    {
        return __baseFeeOverheadPercentage;
    }

    function pendingOwner() 
        virtual override (IWitFeedsAdmin, Ownable2Step)
        public view
        returns (address)
    {
        return Ownable2Step.pendingOwner();
    }
    
    function transferOwnership(address _newOwner)
        virtual override (IWitFeedsAdmin, Ownable2Step)
        public 
        onlyOwner
    {
        Ownable.transferOwnership(_newOwner);
    }

    function deleteFeed(string calldata caption) virtual override external onlyOwner {
        try WitPriceFeedsDataLib.deleteFeed(caption) {
        
        } catch Error(string memory _reason) {
            _revert(_reason);

        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function deleteFeeds() virtual override external onlyOwner {
        try WitPriceFeedsDataLib.deleteFeeds() {
        
        } catch Error(string memory _reason) {
            _revert(_reason);

        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function settleBaseFeeOverheadPercentage(uint16 _baseFeeOverheadPercentage)
        virtual override
        external
        onlyOwner 
    {
        __baseFeeOverheadPercentage = _baseFeeOverheadPercentage;
    }

    function settleDefaultRadonSLA(Witnet.QuerySLA calldata defaultSLA)
        override public
        onlyOwner
    {
        _require(defaultSLA.isValid(), "invalid SLA");
        __defaultRadonSLA = defaultSLA;
    }
    
    function settleFeedRequest(string calldata caption, bytes32 radHash)
        override public
        onlyOwner
    {
        _require(
            _registry().lookupRadonRequestResultDataType(radHash) == dataType,
            "bad result data type"
        );
        try WitPriceFeedsDataLib.settleFeedRequest(caption, radHash) {

        } catch Error(string memory _reason) {
            _revert(_reason);
        
        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function settleFeedRequest(string calldata caption, WitOracleRequest request)
        override external
        onlyOwner
    {
        settleFeedRequest(caption, request.radHash());
    }

    function settleFeedRequest(
            string calldata caption,
            WitOracleRequestTemplate template,
            string[][] calldata args
        )
        override external
        onlyOwner
    {
        settleFeedRequest(caption, template.verifyRadonRequest(args));
    }

    function settleFeedSolver(
            string calldata caption,
            address solver,
            string[] calldata deps
        )
        override external
        onlyOwner
    {
        _require(
            bytes6(bytes(caption)) == bytes6(__prefix),
            "bad caption prefix"
        );
        _require(
            solver != address(0),
            "no solver address"
        );
        try WitPriceFeedsDataLib.settleFeedSolver(caption, solver, deps) {
        
        } catch Error(string memory _reason) {
            _revert(_reason);
        
        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }


    // ================================================================================================================
    // --- Implements 'IWitPriceFeeds' -----------------------------------------------------------------------------

    function lookupDecimals(bytes4 feedId) 
        override 
        external view
        returns (uint8)
    {
        return WitPriceFeedsDataLib.seekRecord(feedId).decimals;
    }
    
    function lookupPriceSolver(bytes4 feedId)
        override
        external view
        returns (IWitPriceFeedsSolver _solverAddress, string[] memory _solverDeps)
    {
        return WitPriceFeedsDataLib.seekPriceSolver(feedId);
    }

    function latestPrice(bytes4 feedId)
        virtual override
        public view
        returns (IWitPriceFeedsSolver.Price memory)
    {
        try WitPriceFeedsDataLib.latestPrice(
            witOracle, 
            feedId
        ) returns (IWitPriceFeedsSolver.Price memory _latestPrice) {
            return _latestPrice;
        
        } catch Error(string memory _reason) {
            _revert(_reason);
        
        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function latestPrices(bytes4[] calldata feedIds)
        virtual override
        external view
        returns (IWitPriceFeedsSolver.Price[] memory _prices)
    {
        _prices = new IWitPriceFeedsSolver.Price[](feedIds.length);
        for (uint _ix = 0; _ix < feedIds.length; _ix ++) {
            _prices[_ix] = latestPrice(feedIds[_ix]);
        }
    }


    // ================================================================================================================
    // --- Implements 'IWitPriceFeedsSolverFactory' ---------------------------------------------------------------------

    function deployPriceSolver(bytes calldata initcode, bytes calldata constructorParams)
        virtual override external
        onlyOwner
        returns (address)
    {
        try WitPriceFeedsDataLib.deployPriceSolver(
            initcode, 
            constructorParams
        ) returns (
            address _solver
        ) {
            emit NewPriceFeedsSolver(
                _solver, 
                _solver.codehash, 
                constructorParams
            );
            return _solver;
        
        } catch Error(string memory _reason) {
            _revert(_reason);

        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function determinePriceSolverAddress(bytes calldata initcode, bytes calldata constructorParams)
        virtual override public view
        returns (address _address)
    {
        return WitPriceFeedsDataLib.determinePriceSolverAddress(initcode, constructorParams);
    }


    // ================================================================================================================
    // --- Implements 'IERC2362' --------------------------------------------------------------------------------------
    
    function valueFor(bytes32 feedId)
        virtual override
        external view
        returns (int256 _value, uint256 _timestamp, uint256 _status)
    {
        IWitPriceFeedsSolver.Price memory _latestPrice = latestPrice(bytes4(feedId));
        return (
            int(uint(_latestPrice.value)),
            Witnet.ResultTimestamp.unwrap(_latestPrice.timestamp),
            (_latestPrice.latestStatus == IWitPriceFeedsSolver.LatestUpdateStatus.Ready
                ? 200
                : (_latestPrice.latestStatus == IWitPriceFeedsSolver.LatestUpdateStatus.Awaiting
                    ? 404 
                    : 400
                )
            )
        );
    }


    // ================================================================================================================
    // --- Internal methods -------------------------------------------------------------------------------------------

    function _footprintOf(bytes4 _id4) virtual internal view returns (bytes4) {
        if (WitPriceFeedsDataLib.seekRecord(_id4).radHash != bytes32(0)) {
            return bytes4(keccak256(abi.encode(_id4, WitPriceFeedsDataLib.seekRecord(_id4).radHash)));
        } else {
            return bytes4(keccak256(abi.encode(_id4, WitPriceFeedsDataLib.seekRecord(_id4).solverDepsFlag)));
        }
    }

    function _validateCaption(string calldata caption)
        internal view returns (uint8)
    {
        _require(
            bytes6(bytes(caption)) == bytes6(__prefix),
            "bad caption prefix"
        );
        try WitPriceFeedsDataLib.validateCaption(caption) returns (uint8 _decimals) {
            return _decimals;
        
        } catch Error(string memory _reason) {
            _revert(_reason);

        } catch (bytes memory) {
            _revertWitPriceFeedsDataLibUnhandledException();
        }
    }

    function _revertWitPriceFeedsDataLibUnhandledException() internal view {
        _revert(_revertWitPriceFeedsDataLibUnhandledExceptionReason());
    }

    function _revertWitPriceFeedsDataLibUnhandledExceptionReason() internal pure returns (string memory) {
        return string(abi.encodePacked(
            type(WitPriceFeedsDataLib).name,
            ": unhandled assertion"
        ));
    }

    function __requestUpdate(bytes4[] memory _deps, Witnet.QuerySLA memory sla)
        virtual internal
        returns (uint256 _evmUsedFunds)
    {
        uint _evmUnitaryUpdateRequestFee = msg.value / _deps.length;
        for (uint _ix = 0; _ix < _deps.length; _ix ++) {
            _evmUsedFunds += this.requestUpdate{
                value: _evmUnitaryUpdateRequestFee
            }(
                _deps[_ix], 
                sla
            );
        }
    }

    function __requestUpdate(
            bytes4 feedId, 
            Witnet.QuerySLA memory querySLA
        )
        virtual internal
        returns (uint256)
    {
        if (WitPriceFeedsDataLib.seekRecord(feedId).radHash != 0) {
            uint256 _evmUpdateRequestFee = msg.value;
            try WitPriceFeedsDataLib.requestUpdate(
                witOracle,
                feedId,
                querySLA,
                _evmUpdateRequestFee
            
            ) returns (
                Witnet.QueryId _latestQueryId,
                uint256 _evmUsedFunds
            
            ) {
                if (_evmUsedFunds < msg.value) {
                    // transfer back unused funds:
                    payable(msg.sender).transfer(msg.value - _evmUsedFunds);
                }
                // solhint-disable avoid-tx-origin:
                emit PullingUpdate(tx.origin, _msgSender(), feedId, _latestQueryId);
                return _evmUsedFunds;
            
            } catch Error(string memory _reason) {
                _revert(_reason);

            } catch (bytes memory) {
                _revertWitPriceFeedsDataLibUnhandledException();
            }
        
        } else if (WitPriceFeedsDataLib.seekRecord(feedId).solver != address(0)) {
            return __requestUpdate(
                WitPriceFeedsDataLib.depsOf(feedId),
                querySLA
            );

        } else {
            _revert("unknown feed");
        }
    }

    function __storage() internal pure returns (WitPriceFeedsDataLib.Storage storage) {
        return WitPriceFeedsDataLib.data();
    }
}

File 2 of 47 : 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;
    function __initializeUpgradableData(bytes memory _initData) virtual internal;

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

File 3 of 47 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

File 4 of 47 : 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
        }
    }
}

File 5 of 47 : Ownable2Step.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert("Ownable2Step: caller is not the new owner");
        }
        _transferOwnership(sender);
    }
}

File 6 of 47 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";

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

File 8 of 47 : WitnetCBOR.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./WitnetBuffer.sol";

/// @title A minimalistic implementation of “RFC 7049 Concise Binary Object Representation”
/// @notice This library leverages a buffer-like structure for step-by-step decoding of bytes so as to minimize
/// the gas cost of decoding them into a useful native type.
/// @dev Most of the logic has been borrowed from Patrick Gansterer’s cbor.js library: https://github.com/paroga/cbor-js
/// @author The Witnet Foundation.

library WitnetCBOR {

  using WitnetBuffer for WitnetBuffer.Buffer;
  using WitnetCBOR for WitnetCBOR.CBOR;

  /// Data struct following the RFC-7049 standard: Concise Binary Object Representation.
  struct CBOR {
      WitnetBuffer.Buffer buffer;
      uint8 initialByte;
      uint8 majorType;
      uint8 additionalInformation;
      uint64 len;
      uint64 tag;
  }

  uint8 internal constant MAJOR_TYPE_INT = 0;
  uint8 internal constant MAJOR_TYPE_NEGATIVE_INT = 1;
  uint8 internal constant MAJOR_TYPE_BYTES = 2;
  uint8 internal constant MAJOR_TYPE_STRING = 3;
  uint8 internal constant MAJOR_TYPE_ARRAY = 4;
  uint8 internal constant MAJOR_TYPE_MAP = 5;
  uint8 internal constant MAJOR_TYPE_TAG = 6;
  uint8 internal constant MAJOR_TYPE_CONTENT_FREE = 7;

  uint32 internal constant UINT32_MAX = type(uint32).max;
  uint64 internal constant UINT64_MAX = type(uint64).max;
  
  error EmptyArray();
  error InvalidLengthEncoding(uint length);
  error UnexpectedMajorType(uint read, uint expected);
  error UnsupportedPrimitive(uint primitive);
  error UnsupportedMajorType(uint unexpected);  

  modifier isMajorType(
      WitnetCBOR.CBOR memory cbor,
      uint8 expected
  ) {
    if (cbor.majorType != expected) {
      revert UnexpectedMajorType(cbor.majorType, expected);
    }
    _;
  }

  modifier notEmpty(WitnetBuffer.Buffer memory buffer) {
    if (buffer.data.length == 0) {
      revert WitnetBuffer.EmptyBuffer();
    }
    _;
  }

  function eof(CBOR memory cbor)
    internal pure
    returns (bool)
  {
    return cbor.buffer.cursor >= cbor.buffer.data.length;
  }

  /// @notice Decode a CBOR structure from raw bytes.
  /// @dev This is the main factory for CBOR instances, which can be later decoded into native EVM types.
  /// @param bytecode Raw bytes representing a CBOR-encoded value.
  /// @return A `CBOR` instance containing a partially decoded value.
  function fromBytes(bytes memory bytecode)
    internal pure
    returns (CBOR memory)
  {
    WitnetBuffer.Buffer memory buffer = WitnetBuffer.Buffer(bytecode, 0);
    return fromBuffer(buffer);
  }

  /// @notice Decode a CBOR structure from raw bytes.
  /// @dev This is an alternate factory for CBOR instances, which can be later decoded into native EVM types.
  /// @param buffer A Buffer structure representing a CBOR-encoded value.
  /// @return A `CBOR` instance containing a partially decoded value.
  function fromBuffer(WitnetBuffer.Buffer memory buffer)
    internal pure
    notEmpty(buffer)
    returns (CBOR memory)
  {
    uint8 initialByte;
    uint8 majorType = 255;
    uint8 additionalInformation;
    uint64 tag = UINT64_MAX;
    uint256 len;
    bool isTagged = true;
    while (isTagged) {
      // Extract basic CBOR properties from input bytes
      initialByte = buffer.readUint8();
      len ++;
      majorType = initialByte >> 5;
      additionalInformation = initialByte & 0x1f;
      // Early CBOR tag parsing.
      if (majorType == MAJOR_TYPE_TAG) {
        uint _cursor = buffer.cursor;
        tag = readLength(buffer, additionalInformation);
        len += buffer.cursor - _cursor;
      } else {
        isTagged = false;
      }
    }
    if (majorType > MAJOR_TYPE_CONTENT_FREE) {
      revert UnsupportedMajorType(majorType);
    }
    return CBOR(
      buffer,
      initialByte,
      majorType,
      additionalInformation,
      uint64(len),
      tag
    );
  }

  function fork(WitnetCBOR.CBOR memory self)
    internal pure
    returns (WitnetCBOR.CBOR memory)
  {
    return CBOR({
      buffer: self.buffer.fork(),
      initialByte: self.initialByte,
      majorType: self.majorType,
      additionalInformation: self.additionalInformation,
      len: self.len,
      tag: self.tag
    });
  }

  function settle(CBOR memory self)
      internal pure
      returns (WitnetCBOR.CBOR memory)
  {
    if (!self.eof()) {
      return fromBuffer(self.buffer);
    } else {
      return self;
    }
  }

  function skip(CBOR memory self)
      internal pure
      returns (WitnetCBOR.CBOR memory)
  {
    if (
      self.majorType == MAJOR_TYPE_INT
        || self.majorType == MAJOR_TYPE_NEGATIVE_INT
        || (
          self.majorType == MAJOR_TYPE_CONTENT_FREE 
            && self.additionalInformation >= 25
            && self.additionalInformation <= 27
        )
    ) {
      self.buffer.cursor += self.peekLength();
    } else if (
        self.majorType == MAJOR_TYPE_STRING
          || self.majorType == MAJOR_TYPE_BYTES
    ) {
      uint64 len = readLength(self.buffer, self.additionalInformation);
      self.buffer.cursor += len;
    } else if (
      self.majorType == MAJOR_TYPE_ARRAY
        || self.majorType == MAJOR_TYPE_MAP
    ) { 
      self.len = readLength(self.buffer, self.additionalInformation);      
    } else if (
       self.majorType != MAJOR_TYPE_CONTENT_FREE
        || (
          self.additionalInformation != 20
            && self.additionalInformation != 21
        )
    ) {
      revert("WitnetCBOR.skip: unsupported major type");
    }
    return self;
  }

  function peekLength(CBOR memory self)
    internal pure
    returns (uint64)
  {
    if (self.additionalInformation < 24) {
      return 0;
    } else if (self.additionalInformation < 28) {
      return uint64(1 << (self.additionalInformation - 24));
    } else {
      revert InvalidLengthEncoding(self.additionalInformation);
    }
  }

  function readArray(CBOR memory self)
    internal pure
    isMajorType(self, MAJOR_TYPE_ARRAY)
    returns (CBOR[] memory items)
  {
    // read array's length and move self cursor forward to the first array element:
    uint64 len = readLength(self.buffer, self.additionalInformation);
    items = new CBOR[](len + 1);
    for (uint ix = 0; ix < len; ix ++) {
      // settle next element in the array:
      self = self.settle();
      // fork it and added to the list of items to be returned:
      items[ix] = self.fork();
      if (self.majorType == MAJOR_TYPE_ARRAY) {
        CBOR[] memory _subitems = self.readArray();
        // move forward to the first element after inner array:
        self = _subitems[_subitems.length - 1];
      } else if (self.majorType == MAJOR_TYPE_MAP) {
        CBOR[] memory _subitems = self.readMap();
        // move forward to the first element after inner map:
        self = _subitems[_subitems.length - 1];
      } else {
        // move forward to the next element:
        self.skip();
      }
    }
    // return self cursor as extra item at the end of the list,
    // as to optimize recursion when jumping over nested arrays:
    items[len] = self;
  }

  function readMap(CBOR memory self)
    internal pure
    isMajorType(self, MAJOR_TYPE_MAP)
    returns (CBOR[] memory items)
  {
    // read number of items within the map and move self cursor forward to the first inner element:
    uint64 len = readLength(self.buffer, self.additionalInformation) * 2;
    items = new CBOR[](len + 1);
    for (uint ix = 0; ix < len; ix ++) {
      // settle next element in the array:
      self = self.settle();
      // fork it and added to the list of items to be returned:
      items[ix] = self.fork();
      if (ix % 2 == 0 && self.majorType != MAJOR_TYPE_STRING) {
        revert UnexpectedMajorType(self.majorType, MAJOR_TYPE_STRING);
      } else if (self.majorType == MAJOR_TYPE_ARRAY || self.majorType == MAJOR_TYPE_MAP) {
        CBOR[] memory _subitems = (self.majorType == MAJOR_TYPE_ARRAY
            ? self.readArray()
            : self.readMap()
        );
        // move forward to the first element after inner array or map:
        self = _subitems[_subitems.length - 1];
      } else {
        // move forward to the next element:
        self.skip();
      }
    }
    // return self cursor as extra item at the end of the list,
    // as to optimize recursion when jumping over nested arrays:
    items[len] = self;
  }

  /// Reads the length of the settle CBOR item from a buffer, consuming a different number of bytes depending on the
  /// value of the `additionalInformation` argument.
  function readLength(
      WitnetBuffer.Buffer memory buffer,
      uint8 additionalInformation
    ) 
    internal pure
    returns (uint64)
  {
    if (additionalInformation < 24) {
      return additionalInformation;
    }
    if (additionalInformation == 24) {
      return buffer.readUint8();
    }
    if (additionalInformation == 25) {
      return buffer.readUint16();
    }
    if (additionalInformation == 26) {
      return buffer.readUint32();
    }
    if (additionalInformation == 27) {
      return buffer.readUint64();
    }
    if (additionalInformation == 31) {
      return UINT64_MAX;
    }
    revert InvalidLengthEncoding(additionalInformation);
  }

  /// @notice Read a `CBOR` structure into a native `bool` value.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as a `bool` value.
  function readBool(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
    returns (bool)
  {
    if (cbor.additionalInformation == 20) {
      return false;
    } else if (cbor.additionalInformation == 21) {
      return true;
    } else {
      revert UnsupportedPrimitive(cbor.additionalInformation);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `bytes` value.
  /// @param cbor An instance of `CBOR`.
  /// @return output The value represented by the input, as a `bytes` value.   
  function readBytes(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_BYTES)
    returns (bytes memory output)
  {
    cbor.len = readLength(
      cbor.buffer,
      cbor.additionalInformation
    );
    if (cbor.len == UINT32_MAX) {
      // These checks look repetitive but the equivalent loop would be more expensive.
      uint32 length = uint32(_readIndefiniteStringLength(
        cbor.buffer,
        cbor.majorType
      ));
      if (length < UINT32_MAX) {
        output = abi.encodePacked(cbor.buffer.read(length));
        length = uint32(_readIndefiniteStringLength(
          cbor.buffer,
          cbor.majorType
        ));
        if (length < UINT32_MAX) {
          output = abi.encodePacked(
            output,
            cbor.buffer.read(length)
          );
        }
      }
    } else {
      return cbor.buffer.read(uint32(cbor.len));
    }
  }

  /// @notice Decode a `CBOR` structure into a `fixed16` value.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`
  /// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as an `int128` value.
  function readFloat16(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
    returns (int32)
  {
    if (cbor.additionalInformation == 25) {
      return cbor.buffer.readFloat16();
    } else {
      revert UnsupportedPrimitive(cbor.additionalInformation);
    }
  }

  /// @notice Decode a `CBOR` structure into a `fixed32` value.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `fixed64`
  /// use cases. In other words, the output of this method is 10^9 times the actual value, encoded into an `int`.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as an `int` value.
  function readFloat32(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
    returns (int)
  {
    if (cbor.additionalInformation == 26) {
      return cbor.buffer.readFloat32();
    } else {
      revert UnsupportedPrimitive(cbor.additionalInformation);
    }
  }

  /// @notice Decode a `CBOR` structure into a `fixed64` value.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `fixed64`
  /// use cases. In other words, the output of this method is 10^15 times the actual value, encoded into an `int`.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as an `int` value.
  function readFloat64(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
    returns (int)
  {
    if (cbor.additionalInformation == 27) {
      return cbor.buffer.readFloat64();
    } else {
      revert UnsupportedPrimitive(cbor.additionalInformation);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `int128[]` value whose inner values follow the same convention 
  /// @notice as explained in `decodeFixed16`.
  /// @param cbor An instance of `CBOR`.
  function readFloat16Array(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_ARRAY)
    returns (int32[] memory values)
  {
    uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
    if (length < UINT64_MAX) {
      values = new int32[](length);
      for (uint64 i = 0; i < length; ) {
        CBOR memory item = fromBuffer(cbor.buffer);
        values[i] = readFloat16(item);
        unchecked {
          i ++;
        }
      }
    } else {
      revert InvalidLengthEncoding(length);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `int128` value.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as an `int128` value.
  function readInt(CBOR memory cbor)
    internal pure
    returns (int64)
  {
    if (cbor.majorType == 1) {
      uint64 _value = readLength(
        cbor.buffer,
        cbor.additionalInformation
      );
      return int64(-1) - int64(uint64(_value));
    } else if (cbor.majorType == 0) {
      // Any `uint64` can be safely casted to `int128`, so this method supports majorType 1 as well so as to have offer
      // a uniform API for positive and negative numbers
      return int64(readUint(cbor));
    }
    else {
      revert UnexpectedMajorType(cbor.majorType, 1);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `int[]` value.
  /// @param cbor instance of `CBOR`.
  /// @return array The value represented by the input, as an `int[]` value.
  function readIntArray(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_ARRAY)
    returns (int64[] memory array)
  {
    uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
    if (length < UINT64_MAX) {
      array = new int64[](length);
      for (uint i = 0; i < length; ) {
        CBOR memory item = fromBuffer(cbor.buffer);
        array[i] = readInt(item);
        unchecked {
          i ++;
        }
      }
    } else {
      revert InvalidLengthEncoding(length);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `string` value.
  /// @param cbor An instance of `CBOR`.
  /// @return text The value represented by the input, as a `string` value.
  function readString(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_STRING)
    returns (string memory text)
  {
    cbor.len = readLength(cbor.buffer, cbor.additionalInformation);
    if (cbor.len == UINT64_MAX) {
      bool _done;
      while (!_done) {
        uint64 length = _readIndefiniteStringLength(
          cbor.buffer,
          cbor.majorType
        );
        if (length < UINT64_MAX) {
          text = string(abi.encodePacked(
            text,
            cbor.buffer.readText(length / 4)
          ));
        } else {
          _done = true;
        }
      }
    } else {
      return string(cbor.buffer.readText(cbor.len));
    }
  }

  /// @notice Decode a `CBOR` structure into a native `string[]` value.
  /// @param cbor An instance of `CBOR`.
  /// @return strings The value represented by the input, as an `string[]` value.
  function readStringArray(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_ARRAY)
    returns (string[] memory strings)
  {
    uint length = readLength(cbor.buffer, cbor.additionalInformation);
    if (length < UINT64_MAX) {
      strings = new string[](length);
      for (uint i = 0; i < length; ) {
        CBOR memory item = fromBuffer(cbor.buffer);
        strings[i] = readString(item);
        unchecked {
          i ++;
        }
      }
    } else {
      revert InvalidLengthEncoding(length);
    }
  }

  /// @notice Decode a `CBOR` structure into a native `uint64` value.
  /// @param cbor An instance of `CBOR`.
  /// @return The value represented by the input, as an `uint64` value.
  function readUint(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_INT)
    returns (uint64)
  {
    return readLength(
      cbor.buffer,
      cbor.additionalInformation
    );
  }

  /// @notice Decode a `CBOR` structure into a native `uint64[]` value.
  /// @param cbor An instance of `CBOR`.
  /// @return values The value represented by the input, as an `uint64[]` value.
  function readUintArray(CBOR memory cbor)
    internal pure
    isMajorType(cbor, MAJOR_TYPE_ARRAY)
    returns (uint64[] memory values)
  {
    uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
    if (length < UINT64_MAX) {
      values = new uint64[](length);
      for (uint ix = 0; ix < length; ) {
        CBOR memory item = fromBuffer(cbor.buffer);
        values[ix] = readUint(item);
        unchecked {
          ix ++;
        }
      }
    } else {
      revert InvalidLengthEncoding(length);
    }
  }  

  /// Read the length of a CBOR indifinite-length item (arrays, maps, byte strings and text) from a buffer, consuming
  /// as many bytes as specified by the first byte.
  function _readIndefiniteStringLength(
      WitnetBuffer.Buffer memory buffer,
      uint8 majorType
    )
    private pure
    returns (uint64 len)
  {
    uint8 initialByte = buffer.readUint8();
    if (initialByte == 0xff) {
      return UINT64_MAX;
    }
    len = readLength(
      buffer,
      initialByte & 0x1f
    );
    if (len >= UINT64_MAX) {
      revert InvalidLengthEncoding(len);
    } else if (majorType != (initialByte >> 5)) {
      revert UnexpectedMajorType((initialByte >> 5), majorType);
    }
  }
 
}

File 9 of 47 : WitnetBuffer.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

/// @title A convenient wrapper around the `bytes memory` type that exposes a buffer-like interface
/// @notice The buffer has an inner cursor that tracks the final offset of every read, i.e. any subsequent read will
/// start with the byte that goes right after the last one in the previous read.
/// @dev `uint32` is used here for `cursor` because `uint16` would only enable seeking up to 8KB, which could in some
/// theoretical use cases be exceeded. Conversely, `uint32` supports up to 512MB, which cannot credibly be exceeded.
/// @author The Witnet Foundation.
library WitnetBuffer {

  error EmptyBuffer();
  error IndexOutOfBounds(uint index, uint range);
  error MissingArgs(uint expected, uint given);

  /// Iterable bytes buffer.
  struct Buffer {
      bytes data;
      uint cursor;
  }

  // Ensures we access an existing index in an array
  modifier withinRange(uint index, uint _range) {
    if (index > _range) {
      revert IndexOutOfBounds(index, _range);
    }
    _;
  }

  /// @notice Concatenate undefinite number of bytes chunks.
  /// @dev Faster than looping on `abi.encodePacked(output, _buffs[ix])`.
  function concat(bytes[] memory _buffs)
    internal pure
    returns (bytes memory output)
  {
    unchecked {
      uint destinationPointer;
      uint destinationLength;
      assembly {
        // get safe scratch location
        output := mload(0x40)
        // set starting destination pointer
        destinationPointer := add(output, 32)
      }      
      for (uint ix = 1; ix <= _buffs.length; ix ++) {  
        uint source;
        uint sourceLength;
        uint sourcePointer;        
        assembly {
          // load source length pointer
          source := mload(add(_buffs, mul(ix, 32)))
          // load source length
          sourceLength := mload(source)
          // sets source memory pointer
          sourcePointer := add(source, 32)
        }
        memcpy(
          destinationPointer,
          sourcePointer,
          sourceLength
        );
        assembly {          
          // increase total destination length
          destinationLength := add(destinationLength, sourceLength)
          // sets destination memory pointer
          destinationPointer := add(destinationPointer, sourceLength)
        }
      }
      assembly {
        // protect output bytes
        mstore(output, destinationLength)
        // set final output length
        mstore(0x40, add(mload(0x40), add(destinationLength, 32)))
      }
    }
  }

  function fork(WitnetBuffer.Buffer memory buffer)
    internal pure
    returns (WitnetBuffer.Buffer memory)
  {
    return Buffer(
      buffer.data,
      buffer.cursor
    );
  }

  function mutate(
      WitnetBuffer.Buffer memory buffer,
      uint length,
      bytes memory pokes
    )
    internal pure
    withinRange(length, buffer.data.length - buffer.cursor + 1)
  {
    bytes[] memory parts = new bytes[](3);
    parts[0] = peek(
      buffer,
      0,
      buffer.cursor
    );
    parts[1] = pokes;
    parts[2] = peek(
      buffer,
      buffer.cursor + length,
      buffer.data.length - buffer.cursor - length
    );
    buffer.data = concat(parts);
  }

  /// @notice Read and consume the next byte from the buffer.
  /// @param buffer An instance of `Buffer`.
  /// @return The next byte in the buffer counting from the cursor position.
  function next(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor, buffer.data.length)
    returns (bytes1)
  {
    // Return the byte at the position marked by the cursor and advance the cursor all at once
    return buffer.data[buffer.cursor ++];
  }

  function peek(
      WitnetBuffer.Buffer memory buffer,
      uint offset,
      uint length
    )
    internal pure
    withinRange(offset + length, buffer.data.length)
    returns (bytes memory)
  {
    bytes memory data = buffer.data;
    bytes memory peeks = new bytes(length);
    uint destinationPointer;
    uint sourcePointer;
    assembly {
      destinationPointer := add(peeks, 32)
      sourcePointer := add(add(data, 32), offset)
    }
    memcpy(
      destinationPointer,
      sourcePointer,
      length
    );
    return peeks;
  }

  // @notice Extract bytes array from buffer starting from current cursor.
  /// @param buffer An instance of `Buffer`.
  /// @param length How many bytes to peek from the Buffer.
  // solium-disable-next-line security/no-assign-params
  function peek(
      WitnetBuffer.Buffer memory buffer,
      uint length
    )
    internal pure
    withinRange(length, buffer.data.length - buffer.cursor)
    returns (bytes memory)
  {
    return peek(
      buffer,
      buffer.cursor,
      length
    );
  }

  /// @notice Read and consume a certain amount of bytes from the buffer.
  /// @param buffer An instance of `Buffer`.
  /// @param length How many bytes to read and consume from the buffer.
  /// @return output A `bytes memory` containing the first `length` bytes from the buffer, counting from the cursor position.
  function read(Buffer memory buffer, uint length)
    internal pure
    withinRange(buffer.cursor + length, buffer.data.length)
    returns (bytes memory output)
  {
    // Create a new `bytes memory destination` value
    output = new bytes(length);
    // Early return in case that bytes length is 0
    if (length > 0) {
      bytes memory input = buffer.data;
      uint offset = buffer.cursor;
      // Get raw pointers for source and destination
      uint sourcePointer;
      uint destinationPointer;
      assembly {
        sourcePointer := add(add(input, 32), offset)
        destinationPointer := add(output, 32)
      }
      // Copy `length` bytes from source to destination
      memcpy(
        destinationPointer,
        sourcePointer,
        length
      );
      // Move the cursor forward by `length` bytes
      seek(
        buffer,
        length,
        true
      );
    }
  }
  
  /// @notice Read and consume the next 2 bytes from the buffer as an IEEE 754-2008 floating point number enclosed in an
  /// `int32`.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `float16`
  /// use cases. In other words, the integer output of this method is 10,000 times the actual value. The input bytes are
  /// expected to follow the 16-bit base-2 format (a.k.a. `binary16`) in the IEEE 754-2008 standard.
  /// @param buffer An instance of `Buffer`.
  /// @return result The `int32` value of the next 4 bytes in the buffer counting from the cursor position.
  function readFloat16(Buffer memory buffer)
    internal pure
    returns (int32 result)
  {
    uint32 value = readUint16(buffer);
    // Get bit at position 0
    uint32 sign = value & 0x8000;
    // Get bits 1 to 5, then normalize to the [-15, 16] range so as to counterweight the IEEE 754 exponent bias
    int32 exponent = (int32(value & 0x7c00) >> 10) - 15;
    // Get bits 6 to 15
    int32 fraction = int32(value & 0x03ff);
    // Add 2^10 to the fraction if exponent is not -15
    if (exponent != -15) {
      fraction |= 0x400;
    } else if (exponent == 16) {
      revert(
        string(abi.encodePacked(
          "WitnetBuffer.readFloat16: ",
          sign != 0 ? "negative" : hex"",
          " infinity"
        ))
      );
    }
    // Compute `2 ^ exponent · (1 + fraction / 1024)`
    if (exponent >= 0) {
      result = int32(int(
        int(1 << uint256(int256(exponent)))
          * 10000
          * fraction
      ) >> 10);
    } else {
      result = int32(int(
        int(fraction)
          * 10000
          / int(1 << uint(int(- exponent)))
      ) >> 10);
    }
    // Make the result negative if the sign bit is not 0
    if (sign != 0) {
      result *= -1;
    }
  }

  /// @notice Consume the next 4 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `float32`
  /// use cases. In other words, the integer output of this method is 10^9 times the actual value. The input bytes are
  /// expected to follow the 64-bit base-2 format (a.k.a. `binary32`) in the IEEE 754-2008 standard.
  /// @param buffer An instance of `Buffer`.
  /// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
  function readFloat32(Buffer memory buffer)
    internal pure
    returns (int result)
  {
    uint value = readUint32(buffer);
    // Get bit at position 0
    uint sign = value & 0x80000000;
    // Get bits 1 to 8, then normalize to the [-127, 128] range so as to counterweight the IEEE 754 exponent bias
    int exponent = (int(value & 0x7f800000) >> 23) - 127;
    // Get bits 9 to 31
    int fraction = int(value & 0x007fffff);
    // Add 2^23 to the fraction if exponent is not -127
    if (exponent != -127) {
      fraction |= 0x800000;
    } else if (exponent == 128) {
      revert(
        string(abi.encodePacked(
          "WitnetBuffer.readFloat32: ",
          sign != 0 ? "negative" : hex"",
          " infinity"
        ))
      );
    }
    // Compute `2 ^ exponent · (1 + fraction / 2^23)`
    if (exponent >= 0) {
      result = (
        int(1 << uint(exponent))
          * (10 ** 9)
          * fraction
      ) >> 23;
    } else {
      result = (
        fraction 
          * (10 ** 9)
          / int(1 << uint(-exponent)) 
      ) >> 23;
    }
    // Make the result negative if the sign bit is not 0
    if (sign != 0) {
      result *= -1;
    }
  }

  /// @notice Consume the next 8 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
  /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
  /// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `float64`
  /// use cases. In other words, the integer output of this method is 10^15 times the actual value. The input bytes are
  /// expected to follow the 64-bit base-2 format (a.k.a. `binary64`) in the IEEE 754-2008 standard.
  /// @param buffer An instance of `Buffer`.
  /// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
  function readFloat64(Buffer memory buffer)
    internal pure
    returns (int result)
  {
    uint value = readUint64(buffer);
    // Get bit at position 0
    uint sign = value & 0x8000000000000000;
    // Get bits 1 to 12, then normalize to the [-1023, 1024] range so as to counterweight the IEEE 754 exponent bias
    int exponent = (int(value & 0x7ff0000000000000) >> 52) - 1023;
    // Get bits 6 to 15
    int fraction = int(value & 0x000fffffffffffff);
    // Add 2^52 to the fraction if exponent is not -1023
    if (exponent != -1023) {
      fraction |= 0x10000000000000;
    } else if (exponent == 1024) {
      revert(
        string(abi.encodePacked(
          "WitnetBuffer.readFloat64: ",
          sign != 0 ? "negative" : hex"",
          " infinity"
        ))
      );
    }
    // Compute `2 ^ exponent · (1 + fraction / 1024)`
    if (exponent >= 0) {
      result = (
        int(1 << uint(exponent))
          * (10 ** 15)
          * fraction
      ) >> 52;
    } else {
      result = (
        fraction 
          * (10 ** 15)
          / int(1 << uint(-exponent)) 
      ) >> 52;
    }
    // Make the result negative if the sign bit is not 0
    if (sign != 0) {
      result *= -1;
    }
  }

  // Read a text string of a given length from a buffer. Returns a `bytes memory` value for the sake of genericness,
  /// but it can be easily casted into a string with `string(result)`.
  // solium-disable-next-line security/no-assign-params
  function readText(
      WitnetBuffer.Buffer memory buffer,
      uint64 length
    )
    internal pure
    returns (bytes memory text)
  {
    text = new bytes(length);
    unchecked {
      for (uint64 index = 0; index < length; index ++) {
        uint8 char = readUint8(buffer);
        if (char & 0x80 != 0) {
          if (char < 0xe0) {
            char = (char & 0x1f) << 6
              | (readUint8(buffer) & 0x3f);
            length -= 1;
          } else if (char < 0xf0) {
            char  = (char & 0x0f) << 12
              | (readUint8(buffer) & 0x3f) << 6
              | (readUint8(buffer) & 0x3f);
            length -= 2;
          } else {
            char = (char & 0x0f) << 18
              | (readUint8(buffer) & 0x3f) << 12
              | (readUint8(buffer) & 0x3f) << 6  
              | (readUint8(buffer) & 0x3f);
            length -= 3;
          }
        }
        text[index] = bytes1(char);
      }
      // Adjust text to actual length:
      assembly {
        mstore(text, length)
      }
    }
  }

  /// @notice Read and consume the next byte from the buffer as an `uint8`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint8` value of the next byte in the buffer counting from the cursor position.
  function readUint8(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor, buffer.data.length)
    returns (uint8 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 1), offset))
    }
    buffer.cursor ++;
  }

  /// @notice Read and consume the next 2 bytes from the buffer as an `uint16`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint16` value of the next 2 bytes in the buffer counting from the cursor position.
  function readUint16(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor + 2, buffer.data.length)
    returns (uint16 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 2), offset))
    }
    buffer.cursor += 2;
  }

  /// @notice Read and consume the next 4 bytes from the buffer as an `uint32`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint32` value of the next 4 bytes in the buffer counting from the cursor position.
  function readUint32(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor + 4, buffer.data.length)
    returns (uint32 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 4), offset))
    }
    buffer.cursor += 4;
  }

  /// @notice Read and consume the next 8 bytes from the buffer as an `uint64`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint64` value of the next 8 bytes in the buffer counting from the cursor position.
  function readUint64(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor + 8, buffer.data.length)
    returns (uint64 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 8), offset))
    }
    buffer.cursor += 8;
  }

  /// @notice Read and consume the next 16 bytes from the buffer as an `uint128`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint128` value of the next 16 bytes in the buffer counting from the cursor position.
  function readUint128(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor + 16, buffer.data.length)
    returns (uint128 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 16), offset))
    }
    buffer.cursor += 16;
  }

  /// @notice Read and consume the next 32 bytes from the buffer as an `uint256`.
  /// @param buffer An instance of `Buffer`.
  /// @return value The `uint256` value of the next 32 bytes in the buffer counting from the cursor position.
  function readUint256(Buffer memory buffer)
    internal pure
    withinRange(buffer.cursor + 32, buffer.data.length)
    returns (uint256 value)
  {
    bytes memory data = buffer.data;
    uint offset = buffer.cursor;
    assembly {
      value := mload(add(add(data, 32), offset))
    }
    buffer.cursor += 32;
  }

  /// @notice Count number of required parameters for given bytes arrays
  /// @dev Wildcard format: "\#\", with # in ["0".."9"].
  /// @param input Bytes array containing strings.
  /// @param count Highest wildcard index found, plus 1.
  function argsCountOf(bytes memory input)
    internal pure
    returns (uint8 count)
  {
    if (input.length < 3) {
      return 0;
    }
    unchecked {
      uint ix = 0; 
      uint length = input.length - 2;
      for (; ix < length; ) {
        if (
          input[ix] == bytes1("\\")
            && input[ix + 2] == bytes1("\\")
            && input[ix + 1] >= bytes1("0")
            && input[ix + 1] <= bytes1("9")
        ) {
          uint8 ax = uint8(uint8(input[ix + 1]) - uint8(bytes1("0")) + 1);
          if (ax > count) {
            count = ax;
          }
          ix += 3;
        } else {
          ix ++;
        }
      }
    }
  }

  /// @notice Replace indexed bytes-wildcards by correspondent substrings.
  /// @dev Wildcard format: "\#\", with # in ["0".."9"].
  /// @param input Bytes array containing strings.
  /// @param args Array of substring values for replacing indexed wildcards.
  /// @return output Resulting bytes array after replacing all wildcards.
  /// @return hits Total number of replaced wildcards.
  function replace(bytes memory input, string[] memory args)
    internal pure
    returns (bytes memory output, uint hits)
  {
    uint ix = 0; uint lix = 0;
    uint inputLength;
    uint inputPointer;
    uint outputLength;
    uint outputPointer;    
    uint source;
    uint sourceLength;
    uint sourcePointer;

    if (input.length < 3) {
      return (input, 0);
    }
    
    assembly {
      // set starting input pointer
      inputPointer := add(input, 32)
      // get safe output location
      output := mload(0x40)
      // set starting output pointer
      outputPointer := add(output, 32)
    }         

    unchecked {
      uint length = input.length - 2;
      for (; ix < length; ) {
        if (
          input[ix] == bytes1("\\")
            && input[ix + 2] == bytes1("\\")
            && input[ix + 1] >= bytes1("0")
            && input[ix + 1] <= bytes1("9")
        ) {
          inputLength = (ix - lix);
          if (ix > lix) {
            memcpy(
              outputPointer,
              inputPointer,
              inputLength
            );
            inputPointer += inputLength + 3;
            outputPointer += inputLength;
          } else {
            inputPointer += 3;
          }
          uint ax = uint(uint8(input[ix + 1]) - uint8(bytes1("0")));
          if (ax >= args.length) {
            revert MissingArgs(ax + 1, args.length);
          }
          assembly {
            source := mload(add(args, mul(32, add(ax, 1))))
            sourceLength := mload(source)
            sourcePointer := add(source, 32)      
          }        
          memcpy(
            outputPointer,
            sourcePointer,
            sourceLength
          );
          outputLength += inputLength + sourceLength;
          outputPointer += sourceLength;
          ix += 3;
          lix = ix;
          hits ++;
        } else {
          ix ++;
        }
      }
      ix = input.length;    
    }
    if (outputLength > 0) {
      if (ix > lix ) {
        memcpy(
          outputPointer,
          inputPointer,
          ix - lix
        );
        outputLength += (ix - lix);
      }
      assembly {
        // set final output length
        mstore(output, outputLength)
        // protect output bytes
        mstore(0x40, add(mload(0x40), add(outputLength, 32)))
      }
    }
    else {
      return (input, 0);
    }
  }

  /// @notice Replace indexed bytes-wildcard by given substring.
  /// @dev Wildcard format: "\#\", with # in ["0".."9"].
  /// @param input Bytes array containing strings.
  /// @param argIndex Index of the wildcard to be replaced.
  /// @param argValue Replacing substring to be used.
  /// @return output Resulting bytes array after replacing all wildcards.
  /// @return hits Total number of replaced wildcards.
  function replace(bytes memory input, uint8 argIndex, string memory argValue)
    internal pure
    returns (bytes memory output, uint hits)
  {
    uint ix = 0; uint lix = 0;
    uint inputLength;
    uint inputPointer;
    uint outputLength;
    uint outputPointer; 
    uint argValueLength;
    uint argValuePointer;

    if (input.length < 3) {
      return (input, 0);
    }
    
    assembly {
      // set starting input pointer
      inputPointer := add(input, 32)
      // get safe output location
      output := mload(0x40)
      // set starting output pointer
      outputPointer := add(output, 32)
      // set pointer to arg value substring
      argValuePointer := add(argValue, 32)
      // set arg value substring length
      argValueLength := mload(argValue)
    }         

    unchecked {
      uint length = input.length - 2;
      for (; ix < length; ) {
        if (
          input[ix] == bytes1("\\")
            && input[ix + 2] == bytes1("\\")
            && input[ix + 1] >= bytes1("0")
            && input[ix + 1] <= bytes1("9")
            && uint8(input[ix + 1]) - uint8(bytes1("0")) == argIndex
        ) {
          inputLength = (ix - lix);
          if (ix > lix) {
            memcpy(
              outputPointer,
              inputPointer,
              inputLength
            );
            inputPointer += inputLength + 3;
            outputPointer += inputLength;
          } else {
            inputPointer += 3;
          }
          memcpy(
            outputPointer,
            argValuePointer,
            argValueLength
          );
          outputLength += inputLength + argValueLength;
          outputPointer += argValueLength;
          ix += 3;
          lix = ix;
          hits ++;
        } else {
          ix ++;
        }
      }
      ix = input.length;    
    }
    if (outputLength > 0) {
      if (ix > lix ) {
        memcpy(
          outputPointer,
          inputPointer,
          ix - lix
        );
        outputLength += (ix - lix);
      }
      assembly {
        // set final output length
        mstore(output, outputLength)
        // protect output bytes
        mstore(0x40, add(mload(0x40), add(outputLength, 32)))
      }
    }
    else {
      return (input, 0);
    }
  }

  /// @notice Replace indexed string wildcards by correspondent substrings.
  /// @dev Wildcard format: "\#\", with # in ["0".."9"].
  /// @param input String potentially containing wildcards.
  /// @param args Array of substring values for replacing indexed wildcards.
  /// @return output Resulting string after replacing all wildcards.
  function replace(string memory input, string[] memory args)
    internal pure
    returns (string memory)
  {
    (bytes memory _outputBytes, ) = replace(bytes(input), args);
    return string(_outputBytes);
  }

  /// @notice Replace last indexed wildcard by given substring.
  /// @dev Wildcard format: "\#\", with # in ["0".."9"].
  /// @param input String potentially containing wildcards.
  /// @param argIndex Index of the wildcard to be replaced.
  /// @param argValue Replacing string to be used.
  /// @return output Resulting string after replacing all wildcards.
  function replace(string memory input, uint8 argIndex, string memory argValue)
    internal pure
    returns (string memory)
  {
    (bytes memory _outputBytes, ) = replace(bytes(input), argIndex, argValue);
    return string(_outputBytes);
  }

  /// @notice Move the inner cursor of the buffer to a relative or absolute position.
  /// @param buffer An instance of `Buffer`.
  /// @param offset How many bytes to move the cursor forward.
  /// @param relative Whether to count `offset` from the last position of the cursor (`true`) or the beginning of the
  /// buffer (`true`).
  /// @return The final position of the cursor (will equal `offset` if `relative` is `false`).
  // solium-disable-next-line security/no-assign-params
  function seek(
      Buffer memory buffer,
      uint offset,
      bool relative
    )
    internal pure
    withinRange(offset, buffer.data.length)
    returns (uint)
  {
    // Deal with relative offsets
    if (relative) {
      offset += buffer.cursor;
    }
    buffer.cursor = offset;
    return offset;
  }

  /// @notice Move the inner cursor a number of bytes forward.
  /// @dev This is a simple wrapper around the relative offset case of `seek()`.
  /// @param buffer An instance of `Buffer`.
  /// @param relativeOffset How many bytes to move the cursor forward.
  /// @return The final position of the cursor.
  function seek(
      Buffer memory buffer,
      uint relativeOffset
    )
    internal pure
    returns (uint)
  {
    return seek(
      buffer,
      relativeOffset,
      true
    );
  }

  /// @notice Copy bytes from one memory address into another.
  /// @dev This function was borrowed from Nick Johnson's `solidity-stringutils` lib, and reproduced here under the terms
  /// of [Apache License 2.0](https://github.com/Arachnid/solidity-stringutils/blob/master/LICENSE).
  /// @param dest Address of the destination memory.
  /// @param src Address to the source memory.
  /// @param len How many bytes to copy.
  // solium-disable-next-line security/no-assign-params
  function memcpy(
      uint dest,
      uint src,
      uint len
    )
    private pure
  {
    unchecked {
      // Copy word-length chunks while possible
      for (; len >= 32; len -= 32) {
        assembly {
          mstore(dest, mload(src))
        }
        dest += 32;
        src += 32;
      }
      if (len > 0) {
        // Copy remaining bytes
        uint _mask = 256 ** (32 - len) - 1;
        assembly {
          let srcpart := and(mload(src), not(_mask))
          let destpart := and(mload(dest), _mask)
          mstore(dest, or(destpart, srcpart))
        }
      }
    }
  }

}

File 10 of 47 : Witnet.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./WitnetCBOR.sol";

library Witnet {

    using WitnetBuffer for WitnetBuffer.Buffer;
    using WitnetCBOR for WitnetCBOR.CBOR;
    using WitnetCBOR for WitnetCBOR.CBOR[];

    type BlockNumber is uint64;
    type ResultTimestamp is uint32;
    type TransactionHash is bytes32;
    
    type QueryCapability is bytes20;
    type QueryCapabilityMember is bytes4;
    type QueryHash is bytes15;
    type QueryId is uint256;
    type QueryReward is uint72;

    uint32 constant internal  WIT_1_GENESIS_TIMESTAMP = 0; // TBD    
    uint32 constant internal  WIT_1_SECS_PER_EPOCH = 45;

    uint32  constant internal WIT_2_GENESIS_BEACON_INDEX = 0;       // TBD
    uint32  constant internal WIT_2_GENESIS_BEACON_PREV_INDEX = 0;  // TBD
    bytes24 constant internal WIT_2_GENESIS_BEACON_PREV_ROOT = 0;   // TBD
    bytes16 constant internal WIT_2_GENESIS_BEACON_DDR_TALLIES_MERKLE_ROOT = 0;  // TBD
    bytes16 constant internal WIT_2_GENESIS_BEACON_DRO_TALLIES_MERKLE_ROOT = 0;  // TBD
    uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_0 = 0; // TBD
    uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_1 = 0; // TBD
    uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_2 = 0; // TBD
    uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_3 = 0; // TBD
    uint32  constant internal WIT_2_GENESIS_EPOCH = 0;      // TBD
    uint32  constant internal WIT_2_GENESIS_TIMESTAMP = 0;  // TBD
    uint32  constant internal WIT_2_SECS_PER_EPOCH = 20;    // TBD
    uint32  constant internal WIT_2_FAST_FORWARD_COMMITTEE_SIZE = 64; // TBD

    function channel(address wrb) internal view returns (bytes4) {
        return bytes4(keccak256(abi.encode(address(wrb), block.chainid)));
    }

    struct Beacon {
        uint32  index;
        uint32  prevIndex;
        bytes24 prevRoot;
        bytes16 ddrTalliesMerkleRoot;
        bytes16 droTalliesMerkleRoot;
        uint256[4] nextCommitteeAggPubkey;
    }

    struct DataPullReport {
        QueryId queryId;
        QueryHash queryHash;             // KECCAK256(channel | blockhash(block.number - 1) | ...)
        bytes   witDrRelayerSignature;   // ECDSA.signature(queryHash)
        uint32  witDrResultEpoch;
        bytes   witDrResultCborBytes;
        bytes32 witDrTxHash;
    }

    struct DataPushReport {
        QuerySLA witDrSLA;
        bytes32  witDrRadHash;
        uint32   witDrResultEpoch;
        bytes    witDrResultCborBytes;
        bytes32  witDrTxHash;
    }

    /// Data struct containing the Witnet-provided result to a Data Request.
    struct DataResult {
        ResultStatus    status;
        RadonDataTypes  dataType;
        TransactionHash drTxHash;
        ResultTimestamp timestamp;
        WitnetCBOR.CBOR value;
    }
    
    struct FastForward {
        Beacon beacon;
        uint256[2] committeeAggSignature;
        uint256[4][] committeeMissingPubkeys;
    }

    /// Struct containing both request and response data related to every query posted to the Witnet Request Board
    struct Query {
        QueryRequest  request;
        QueryResponse response;
        QuerySLA    slaParams;        // Minimum Service-Level parameters to be committed by the Witnet blockchain.
        QueryHash   hash;             // Unique query hash determined by payload, WRB instance, chain id and EVM's previous block hash.
        QueryReward reward;           // EVM amount in wei eventually to be paid to the legit result reporter.
        BlockNumber checkpoint;
    }

    /// Possible status of a Witnet query.
    enum QueryStatus {
        Unknown,
        Posted,
        Reported,
        Finalized,
        Delayed,
        Expired,
        Disputed
    }

    struct QueryCallback {
        address consumer;               // consumer contract address to which the query result will be reported
        uint24  gasLimit;               // expected max amount of gas required by the callback method in the consumer contract
    }

    /// Data kept in EVM-storage for every Request posted to the Witnet Request Board.
    struct QueryRequest {
        address  requester;              // EVM address from which the request was posted.
        uint24   callbackGas; uint72 _0; // Max callback gas limit upon response, if a callback is required.
        bytes    radonBytecode;          // Optional: Witnet Data Request bytecode to be solved by the Witnet blockchain.
        bytes32  radonRadHash;           // Optional: Previously verified hash of the Witnet Data Request to be solved.
    }

    /// QueryResponse metadata and result as resolved by the Witnet blockchain.
    struct QueryResponse {
        address reporter; uint64 _0;    // EVM address from which the Data Request result was reported.
        uint32  resultTimestamp;        // Unix timestamp (seconds) at which the data request was resolved in the Witnet blockchain.
        bytes32 resultDrTxHash;         // Unique hash of the commit/reveal act in the Witnet blockchain that resolved the data request.
        bytes   resultCborBytes;        // CBOR-encode result to the request, as resolved in the Witnet blockchain.
        address disputer;
    }

    /// Structure containing all possible SLA security parameters of Wit/2.1 Data Requests
    struct QuerySLA {
        uint16  witResultMaxSize;          // max size permitted to whatever query result may come from the wit/oracle blockchain.
        uint16  witCommitteeCapacity;      // max number of eligibile witnesses in the wit/oracle blockchain for solving some query.
        uint64  witCommitteeUnitaryReward; // unitary reward in nanowits for true witnesses and validators in the wit/oracle blockchain.
        QueryCapability witCapability;     // optional: identifies some pre-established capability-compliant commitee required for solving the query.
    }

    enum ResultStatus {
        /// 0x00: No errors.
        NoErrors,
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Source-specific format error sub-codes ============================================================================
        
        /// 0x01: At least one of the source scripts is not a valid CBOR-encoded value.
        SourceScriptNotCBOR, 
        
        /// 0x02: The CBOR value decoded from a source script is not an Array.
        SourceScriptNotArray,
        
        /// 0x03: The Array value decoded form a source script is not a valid Data Request.
        SourceScriptNotRADON,
        
        /// 0x04: The request body of at least one data source was not properly formated.
        SourceRequestBody,
        
        /// 0x05: The request headers of at least one data source was not properly formated.
        SourceRequestHeaders,
        
        /// 0x06: The request URL of at least one data source was not properly formated.
        SourceRequestURL,
        
        /// Unallocated
        SourceFormat0x07, SourceFormat0x08, SourceFormat0x09, SourceFormat0x0A, SourceFormat0x0B, SourceFormat0x0C,
        SourceFormat0x0D, SourceFormat0x0E, SourceFormat0x0F, 
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Complexity error sub-codes ========================================================================================
        
        /// 0x10: The request contains too many sources.
        RequestTooManySources,
        
        /// 0x11: The script contains too many calls.
        ScriptTooManyCalls,
        
        /// Unallocated
        Complexity0x12, Complexity0x13, Complexity0x14, Complexity0x15, Complexity0x16, Complexity0x17, Complexity0x18,
        Complexity0x19, Complexity0x1A, Complexity0x1B, Complexity0x1C, Complexity0x1D, Complexity0x1E, Complexity0x1F,

        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Lack of support error sub-codes ===================================================================================
        
        /// 0x20: Some Radon operator code was found that is not supported (1+ args).
        UnsupportedOperator,
        
        /// 0x21: Some Radon filter opcode is not currently supported (1+ args).
        UnsupportedFilter,
        
        /// 0x22: Some Radon request type is not currently supported (1+ args).
        UnsupportedHashFunction,
        
        /// 0x23: Some Radon reducer opcode is not currently supported (1+ args)
        UnsupportedReducer,
        
        /// 0x24: Some Radon hash function is not currently supported (1+ args).
        UnsupportedRequestType, 
        
        /// 0x25: Some Radon encoding function is not currently supported (1+ args).
        UnsupportedEncodingFunction,
        
        /// Unallocated
        Operator0x26, Operator0x27, 
        
        /// 0x28: Wrong number (or type) of arguments were passed to some Radon operator.
        WrongArguments,
        
        /// Unallocated
        Operator0x29, Operator0x2A, Operator0x2B, Operator0x2C, Operator0x2D, Operator0x2E, Operator0x2F,
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Retrieve-specific circumstantial error sub-codes ================================================================================
        /// 0x30: A majority of data sources returned an HTTP status code other than 200 (1+ args):
        HttpErrors,
        
        /// 0x31: A majority of data sources timed out:
        RetrievalsTimeout,
        
        /// Unallocated
        RetrieveCircumstance0x32, RetrieveCircumstance0x33, RetrieveCircumstance0x34, RetrieveCircumstance0x35,
        RetrieveCircumstance0x36, RetrieveCircumstance0x37, RetrieveCircumstance0x38, RetrieveCircumstance0x39,
        RetrieveCircumstance0x3A, RetrieveCircumstance0x3B, RetrieveCircumstance0x3C, RetrieveCircumstance0x3D,
        RetrieveCircumstance0x3E, RetrieveCircumstance0x3F,
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Scripting-specific runtime error sub-code =========================================================================
        /// 0x40: Math operator caused an underflow.
        MathUnderflow,
        
        /// 0x41: Math operator caused an overflow.
        MathOverflow,
        
        /// 0x42: Math operator tried to divide by zero.
        MathDivisionByZero,            
        
        /// 0x43: Wrong input to subscript call.
        WrongSubscriptInput,
        
        /// 0x44: Value cannot be extracted from input binary buffer.
        BufferIsNotValue,
        
        /// 0x45: Value cannot be decoded from expected type.
        Decode,
        
        /// 0x46: Unexpected empty array.
        EmptyArray,
        
        /// 0x47: Value cannot be encoded to expected type.
        Encode,
        
        /// 0x48: Failed to filter input values (1+ args).
        Filter,
        
        /// 0x49: Failed to hash input value.
        Hash,
        
        /// 0x4A: Mismatching array ranks.
        MismatchingArrays,
        
        /// 0x4B: Failed to process non-homogenous array.
        NonHomegeneousArray,
        
        /// 0x4C: Failed to parse syntax of some input value, or argument.
        Parse,
        
        /// 0x4D: Parsing logic limits were exceeded.
        ParseOverflow,
        
        /// Unallocated
        ScriptError0x4E, ScriptError0x4F,
    
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Actual first-order result error codes =============================================================================
        
        /// 0x50: Not enough reveals were received in due time:
        InsufficientReveals,
        
        /// 0x51: No actual reveal majority was reached on tally stage:
        InsufficientMajority,
        
        /// 0x52: Not enough commits were received before tally stage:
        InsufficientCommits,
        
        /// 0x53: Generic error during tally execution (to be deprecated after WIP #0028)
        TallyExecution,
        
        /// 0x54: A majority of data sources could either be temporarily unresponsive or failing to report the requested data:
        CircumstantialFailure,
        
        /// 0x55: At least one data source is inconsistent when queried through multiple transports at once:
        InconsistentSources,
        
        /// 0x56: Any one of the (multiple) Retrieve, Aggregate or Tally scripts were badly formated:
        MalformedDataRequest,
        
        /// 0x57: Values returned from a majority of data sources don't match the expected schema:
        MalformedQueryResponses,
        
        /// Unallocated:    
        OtherError0x58, OtherError0x59, OtherError0x5A, OtherError0x5B, OtherError0x5C, OtherError0x5D, OtherError0x5E, 
        
        /// 0x5F: Size of serialized tally result exceeds allowance:
        OversizedTallyResult,

        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Inter-stage runtime error sub-codes ===============================================================================
        
        /// 0x60: Data aggregation reveals could not get decoded on the tally stage:
        MalformedReveals,
        
        /// 0x61: The result to data aggregation could not get encoded:
        EncodeReveals,  
        
        /// 0x62: A mode tie ocurred when calculating some mode value on the aggregation or the tally stage:
        ModeTie, 
        
        /// Unallocated:
        OtherError0x63, OtherError0x64, OtherError0x65, OtherError0x66, OtherError0x67, OtherError0x68, OtherError0x69, 
        OtherError0x6A, OtherError0x6B, OtherError0x6C, OtherError0x6D, OtherError0x6E, OtherError0x6F,
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Runtime access error sub-codes ====================================================================================
        
        /// 0x70: Tried to access a value from an array using an index that is out of bounds (1+ args):
        ArrayIndexOutOfBounds,
        
        /// 0x71: Tried to access a value from a map using a key that does not exist (1+ args):
        MapKeyNotFound,
        
        /// 0X72: Tried to extract value from a map using a JSON Path that returns no values (+1 args):
        JsonPathNotFound,
        
        /// Unallocated:
        OtherError0x73, OtherError0x74, OtherError0x75, OtherError0x76, OtherError0x77, OtherError0x78, 
        OtherError0x79, OtherError0x7A, OtherError0x7B, OtherError0x7C, OtherError0x7D, OtherError0x7E, OtherError0x7F, 
        OtherError0x80, OtherError0x81, OtherError0x82, OtherError0x83, OtherError0x84, OtherError0x85, OtherError0x86, 
        OtherError0x87, OtherError0x88, OtherError0x89, OtherError0x8A, OtherError0x8B, OtherError0x8C, OtherError0x8D, 
        OtherError0x8E, OtherError0x8F, OtherError0x90, OtherError0x91, OtherError0x92, OtherError0x93, OtherError0x94, 
        OtherError0x95, OtherError0x96, OtherError0x97, OtherError0x98, OtherError0x99, OtherError0x9A, OtherError0x9B,
        OtherError0x9C, OtherError0x9D, OtherError0x9E, OtherError0x9F, OtherError0xA0, OtherError0xA1, OtherError0xA2, 
        OtherError0xA3, OtherError0xA4, OtherError0xA5, OtherError0xA6, OtherError0xA7, OtherError0xA8, OtherError0xA9, 
        OtherError0xAA, OtherError0xAB, OtherError0xAC, OtherError0xAD, OtherError0xAE, OtherError0xAF, OtherError0xB0,
        OtherError0xB1, OtherError0xB2, OtherError0xB3, OtherError0xB4, OtherError0xB5, OtherError0xB6, OtherError0xB7,
        OtherError0xB8, OtherError0xB9, OtherError0xBA, OtherError0xBB, OtherError0xBC, OtherError0xBD, OtherError0xBE,
        OtherError0xBF, OtherError0xC0, OtherError0xC1, OtherError0xC2, OtherError0xC3, OtherError0xC4, OtherError0xC5,
        OtherError0xC6, OtherError0xC7, OtherError0xC8, OtherError0xC9, OtherError0xCA, OtherError0xCB, OtherError0xCC,
        OtherError0xCD, OtherError0xCE, OtherError0xCF, OtherError0xD0, OtherError0xD1, OtherError0xD2, OtherError0xD3,
        OtherError0xD4, OtherError0xD5, OtherError0xD6, OtherError0xD7, OtherError0xD8, OtherError0xD9, OtherError0xDA,
        OtherError0xDB, OtherError0xDC, OtherError0xDD, OtherError0xDE, OtherError0xDF,
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Inter-client generic error codes ==================================================================================
        /// Data requests that cannot be relayed into the Witnet blockchain should be reported
        /// with one of these errors. 
        
        /// 0xE0: Requests that cannot be parsed must always get this error as their result.
        BridgeMalformedDataRequest,
        
        /// 0xE1: Witnesses exceeds 100
        BridgePoorIncentives,
        
        /// 0xE2: The request is rejected on the grounds that it may cause the submitter to spend or stake an
        /// amount of value that is unjustifiably high when compared with the reward they will be getting
        BridgeOversizedTallyResult,
        
        /// Unallocated:
        OtherError0xE3, OtherError0xE4, OtherError0xE5, OtherError0xE6, OtherError0xE7, OtherError0xE8, OtherError0xE9,
        OtherError0xEA, OtherError0xEB, OtherError0xEC, OtherError0xED, OtherError0xEE, OtherError0xEF, 
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Transient errors as determined by the Request Board contract ======================================================
        
        /// 0xF0: 
        BoardAwaitingResult,

        /// 0xF1:
        BoardFinalizingResult,

        /// 0xF2:
        BoardBeingDisputed,

        /// Unallocated
        OtherError0xF3, OtherError0xF4, OtherError0xF5, OtherError0xF6, OtherError0xF7,

        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// Final errors as determined by the Request Board contract ==========================================================

        /// 0xF8:
        BoardAlreadyDelivered,

        /// 0xF9:
        BoardResolutionTimeout,

        /// Unallocated:
        OtherError0xFA, OtherError0xFB, OtherError0xFC, OtherError0xFD, OtherError0xFE,
        
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// 0xFF: Some tally error is not intercepted but it should (0+ args)
        UnhandledIntercept
    }

    /// Possible types either processed by Witnet Radon Scripts or included within results to Witnet Data Requests.
    enum RadonDataTypes {
        /* 0x00 */ Any, 
        /* 0x01 */ Array,
        /* 0x02 */ Bool,
        /* 0x03 */ Bytes,
        /* 0x04 */ Integer,
        /* 0x05 */ Float,
        /* 0x06 */ Map,
        /* 0x07 */ String,
        Unused0x08, Unused0x09, Unused0x0A, Unused0x0B,
        Unused0x0C, Unused0x0D, Unused0x0E, Unused0x0F,
        /* 0x10 */ Same,
        /* 0x11 */ Inner,
        /* 0x12 */ Match,
        /* 0x13 */ Subscript
    }

    /// Structure defining some data filtering that can be applied at the Aggregation or the Tally stages
    /// within a Witnet Data Request resolution workflow.
    struct RadonFilter {
        RadonFilterOpcodes opcode;
        bytes cborArgs;
    }

    /// Filtering methods currently supported on the Witnet blockchain. 
    enum RadonFilterOpcodes {
        /* 0x00 */ Reserved0x00, //GreaterThan,
        /* 0x01 */ Reserved0x01, //LessThan,
        /* 0x02 */ Reserved0x02, //Equals,
        /* 0x03 */ Reserved0x03, //AbsoluteDeviation,
        /* 0x04 */ Reserved0x04, //RelativeDeviation
        /* 0x05 */ StandardDeviation,
        /* 0x06 */ Reserved0x06, //Top,
        /* 0x07 */ Reserved0x07, //Bottom,
        /* 0x08 */ Mode,
        /* 0x09 */ Reserved0x09  //LessOrEqualThan
    }

    /// Structure defining the array of filters and reducting function to be applied at either the Aggregation
    /// or the Tally stages within a Witnet Data Request resolution workflow.
    struct RadonReducer {
        RadonReduceOpcodes opcode;
        RadonFilter[] filters;
    }

    /// Reducting functions currently supported on the Witnet blockchain.
    enum RadonReduceOpcodes {
        /* 0x00 */ Reserved0x00, //Minimum,
        /* 0x01 */ Reserved0x01, //Maximum,
        /* 0x02 */ Mode,
        /* 0x03 */ AverageMean,
        /* 0x04 */ Reserved0x04, //AverageMeanWeighted,
        /* 0x05 */ AverageMedian,
        /* 0x06 */ Reserved0x06, //AverageMedianWeighted,
        /* 0x07 */ StandardDeviation,
        /* 0x08 */ Reserved0x08, //AverageDeviation,
        /* 0x09 */ Reserved0x09, //MedianDeviation,
        /* 0x0A */ Reserved0x10, //MaximumDeviation,
        /* 0x0B */ ConcatenateAndHash
    }
    
    /// Structure containing the Retrieve-Attestation-Delivery parts of a Witnet-compliant Data Request.
    struct RadonRequest {
        RadonRetrieval[] retrieve;
        RadonReducer aggregate;
        RadonReducer tally;
    }

    /// Structure containing all the parameters that fully describe a Witnet Radon Retrieval within a Witnet Data Request.
    struct RadonRetrieval {
        uint8 argsCount;
        RadonRetrievalMethods method;
        RadonDataTypes dataType;
        string url;
        string body;
        string[2][] headers;
        bytes radonScript;
    }

    /// Possible Radon retrieval methods that can be used within a Radon Retrieval. 
    enum RadonRetrievalMethods {
        /* 0 */ Unknown,
        /* 1 */ HttpGet,
        /* 2 */ RNG,
        /* 3 */ HttpPost,
        /* 4 */ HttpHead
    }

    /// Structure containing all possible SLA security parameters of a Witnet-compliant Data Request.

    struct RadonSLAv1 {
        uint8 numWitnesses;
        uint8 minConsensusPercentage;
        uint64 witnessReward;
        uint64 witnessCollateral;
        uint64 minerCommitRevealFee;
    }


    /// =======================================================================
    /// --- Beacon helper functions ------------------------------------

    function equals(Beacon storage self, Beacon calldata other)
        internal view returns (bool)
    {
        return (
            root(self) == root(other)
        );
    }

    function root(Beacon calldata self) internal pure returns (bytes24) {
        return bytes24(keccak256(abi.encode(
            self.index,
            self.prevIndex,
            self.prevRoot,
            self.ddrTalliesMerkleRoot,
            self.droTalliesMerkleRoot,
            self.nextCommitteeAggPubkey
        )));
    }
    
    function root(Beacon storage self) internal view returns (bytes24) {
        return bytes24(keccak256(abi.encode(
            self.index,
            self.prevIndex,
            self.prevRoot,
            self.ddrTalliesMerkleRoot,
            self.droTalliesMerkleRoot,
            self.nextCommitteeAggPubkey
        )));
    }

    
    /// =======================================================================
    /// --- BlockNumber helper functions --------------------------------------

    function egt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
        return BlockNumber.unwrap(a) >= BlockNumber.unwrap(b);
    }

    function elt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
        return BlockNumber.unwrap(a) <= BlockNumber.unwrap(b);
    }

    function gt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
        return BlockNumber.unwrap(a) > BlockNumber.unwrap(b);
    }

    function lt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
        return BlockNumber.unwrap(a) < BlockNumber.unwrap(b);
    }

    function isZero(BlockNumber b) internal pure returns (bool) {
        return (BlockNumber.unwrap(b) == 0);
    }


    /// =======================================================================
    /// --- FastForward helper functions -------------------------------

    function head(FastForward[] calldata rollup)
        internal pure returns (Beacon calldata)
    {
        return rollup[rollup.length - 1].beacon;
    }


    /// ===============================================================================================================
    /// --- Query* helper methods -------------------------------------------------------------------------------------

    function hashify(QueryHash hash) internal pure returns (bytes32) {
        return keccak256(abi.encode(QueryHash.unwrap(hash)));
    }

    function hashify(QueryId _queryId, bytes32 _radHash, bytes32 _slaHash) internal view returns (Witnet.QueryHash) {
        return Witnet.QueryHash.wrap(bytes15(
            keccak256(abi.encode(
                channel(address(this)), 
                blockhash(block.number - 1),
                _queryId, _radHash, _slaHash
            ))
        ));
    }

    function hashify(QuerySLA memory querySLA) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(
            querySLA.witResultMaxSize,
            querySLA.witCommitteeCapacity,
            querySLA.witCommitteeUnitaryReward,
            querySLA.witCapability
        ));
    }


    /// ===============================================================================================================
    /// --- *Report helper methods ------------------------------------------------------------------------------------

    function queryRelayer(DataPullReport calldata self) internal pure returns (address) {
        return recoverAddr(
            self.witDrRelayerSignature, 
            hashify(self.queryHash)
        );
    }

    function tallyHash(DataPullReport calldata self) internal pure returns (bytes32) {
        return keccak256(abi.encode(
            self.queryHash,
            self.witDrRelayerSignature,
            self.witDrTxHash,
            self.witDrResultEpoch,
            self.witDrResultCborBytes
        ));
    }

    function tallyHash(DataPushReport calldata self) internal pure returns (bytes32) {
        return keccak256(abi.encode(
            self.witDrRadHash,
            self.witDrSLA,
            self.witDrTxHash,
            self.witDrResultEpoch,
            self.witDrResultCborBytes
        ));
    }

    
    /// ========================================================================================================
    /// --- 'DataResult' helper methods ------------------------------------------------------------------------

    function noErrors(DataResult memory self) internal pure returns (bool) {
        return self.status == ResultStatus.NoErrors;
    }

    function keepWaiting(DataResult memory self) internal pure returns (bool) {
        return keepWaiting(self.status);
    }

    function hasErrors(DataResult memory self) internal pure returns (bool) {
        return hasErrors(self.status);
    }

    modifier _checkDataType(DataResult memory self, RadonDataTypes expectedDataType) {
        require(
            !keepWaiting(self)
                && self.dataType == expectedDataType
            , "cbor: cannot fetch data"
        ); _; 
        self.dataType = peekRadonDataType(self.value);
    }

    function fetchAddress(DataResult memory self) 
        internal pure 
        _checkDataType(self, RadonDataTypes.Bytes) 
        returns (address _res)
    {
        return toAddress(self.value.readBytes());
    }

    function fetchBool(DataResult memory self) 
        internal pure 
        _checkDataType(self, RadonDataTypes.Bool) 
        returns (bool)
    {
        return self.value.readBool();
    }

    function fetchBytes(DataResult memory self)
        internal pure 
        _checkDataType(self, RadonDataTypes.Bytes) 
        returns (bytes memory)
    {
        return self.value.readBytes();
    }

    function fetchBytes4(DataResult memory self)
        internal pure 
        _checkDataType(self, RadonDataTypes.Bytes) 
        returns (bytes4)
    {
        return toBytes4(self.value.readBytes());
    }

    function fetchBytes32(DataResult memory self)
        internal pure 
        _checkDataType(self, RadonDataTypes.Bytes) 
        returns (bytes32)
    {
        return toBytes32(self.value.readBytes());
    }

    function fetchCborArray(DataResult memory self)
        internal pure 
        _checkDataType(self, RadonDataTypes.Array) 
        returns (WitnetCBOR.CBOR[] memory)
    {
        return self.value.readArray();
    }

    /// @dev Decode a fixed16 (half-precision) numeric value from the Result's CBOR value.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values.
    /// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`.
    /// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
    function fetchFloatFixed16(DataResult memory self)
        internal pure 
        _checkDataType(self, RadonDataTypes.Float) 
        returns (int32)
    {
        return self.value.readFloat16();
    }

    /// @dev Decode an array of fixed16 values from the Result's CBOR value.
    function fetchFloatFixed16Array(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Array)
        returns (int32[] memory)
    {
        return self.value.readFloat16Array();
    }

    /// @dev Decode a `int64` value from the DataResult's CBOR value.
    function fetchInt(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Integer)
        returns (int64)
    {
        return self.value.readInt();
    }

    function fetchInt64Array(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Array)
        returns (int64[] memory)
    {
        return self.value.readIntArray();
    }

    function fetchString(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.String)
        returns (string memory)
    {
        return self.value.readString();
    }

    function fetchStringArray(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Array)
        returns (string[] memory)
    {
        return self.value.readStringArray();
    }

    /// @dev Decode a `uint64` value from the DataResult's CBOR value.
    function fetchUint(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Integer)
        returns (uint64)
    {
        return self.value.readUint();
    }

    function fetchUint64Array(DataResult memory self)
        internal pure
        _checkDataType(self, RadonDataTypes.Array)
        returns (uint64[] memory)
    {
        return self.value.readUintArray();
    }

    bytes7 private constant _CBOR_MAJOR_TYPE_TO_RADON_DATA_TYPES_MAP = 0x04040307010600;
    function peekRadonDataType(WitnetCBOR.CBOR memory cbor) internal pure returns (RadonDataTypes _type) {
        _type = RadonDataTypes.Any;
        if (!cbor.eof()) {
            if (cbor.majorType <= 6) {
                return RadonDataTypes(uint8(bytes1(_CBOR_MAJOR_TYPE_TO_RADON_DATA_TYPES_MAP[cbor.majorType])));
            
            } else if (cbor.majorType == 7) {
                if (cbor.additionalInformation == 20 || cbor.additionalInformation == 21) {
                    return RadonDataTypes.Bool;
                
                } else if (cbor.additionalInformation >= 25 && cbor.additionalInformation <= 27) {
                    return RadonDataTypes.Float;
                }
            }
        }
    }


    /// ===============================================================================================================
    /// --- ResultStatus helper methods --------------------------------------------------------------------

    function hasErrors(ResultStatus self) internal pure returns (bool) {
        return (
            self != ResultStatus.NoErrors
                && !keepWaiting(self)
        );
    }

    function isCircumstantial(ResultStatus self) internal pure returns (bool) {
        return (self == ResultStatus.CircumstantialFailure);
    }

    function isRetriable(ResultStatus self) internal pure returns (bool) {
        return (
            lackOfConsensus(self)
                || isCircumstantial(self)
                || poorIncentives(self)
        );
    }

    function keepWaiting(ResultStatus self) internal pure returns (bool) {
        return (
            self == ResultStatus.BoardAwaitingResult
                || self == ResultStatus.BoardFinalizingResult
        );
    }

    function lackOfConsensus(ResultStatus self) internal pure returns (bool) {
        return (
            self == ResultStatus.InsufficientCommits
                || self == ResultStatus.InsufficientMajority
                || self == ResultStatus.InsufficientReveals
        );
    }

    function poorIncentives(ResultStatus self) internal pure returns (bool) {
        return (
            self == ResultStatus.OversizedTallyResult
                || self == ResultStatus.InsufficientCommits
                || self == ResultStatus.BridgePoorIncentives
                || self == ResultStatus.BridgeOversizedTallyResult
        );
    }


    /// ========================================================================================================
    /// --- 'QueryId' helper methods ---------------------------------------------------------------------------

    function isZero(QueryId a) internal pure returns (bool) {
        return (QueryId.unwrap(a) == 0);
    }


    /// ========================================================================================================
    /// --- 'QuerySLA' helper methods --------------------------------------------------------------------------

    function equalOrGreaterThan(QuerySLA calldata self, QuerySLA storage stored) internal view returns (bool) {
        return (
            QueryCapability.unwrap(self.witCapability) == QueryCapability.unwrap(stored.witCapability)
                && self.witCommitteeCapacity >= stored.witCommitteeCapacity
                && self.witCommitteeUnitaryReward >= stored.witCommitteeUnitaryReward 
                && self.witResultMaxSize <= stored.witResultMaxSize
        );
    }

    function isValid(QuerySLA memory self) internal pure returns (bool) {
        return (
            self.witResultMaxSize > 0
                && self.witCommitteeUnitaryReward > 0
                && self.witCommitteeCapacity > 0
                && (QueryCapability.unwrap(self.witCapability) != 0 || self.witCommitteeCapacity <= 127)
        );
    }

    function toV1(QuerySLA calldata self) internal pure returns (RadonSLAv1 memory) {
        return RadonSLAv1({
            numWitnesses: uint8(self.witCommitteeCapacity),
            minConsensusPercentage: 66,
            witnessReward: self.witCommitteeUnitaryReward,
            witnessCollateral: self.witCommitteeUnitaryReward * 100,
            minerCommitRevealFee: self.witCommitteeUnitaryReward / self.witCommitteeCapacity
        });
    }

    function witTotalReward(QuerySLA storage self) internal view returns (uint64) {
        return self.witCommitteeUnitaryReward / (self.witCommitteeCapacity + 3);
    }


    /// ===============================================================================================================
    /// --- 'bytes*' helper methods -----------------------------------------------------------------------------------

    function merkleHash(bytes32 a, bytes32 b) internal pure returns (bytes32) {
        return (a < b
            ? _merkleHash(a, b)
            : _merkleHash(b, a)
        );
    }

    function merkleRoot(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32 _root) {
        _root = leaf;
        for (uint _ix = 0; _ix < proof.length; _ix ++) {
            _root = merkleHash(_root, proof[_ix]);
        }
    }

    function radHash(bytes calldata bytecode) internal pure returns (bytes32) {
        return keccak256(bytecode);
    }

    function recoverAddr(bytes memory signature, bytes32 hash_)
        internal pure 
        returns (address)
    {
        if (signature.length != 65) {
            return (address(0));
        }
        bytes32 r;
        bytes32 s;
        uint8 v;
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return address(0);
        }
        if (v != 27 && v != 28) {
            return address(0);
        }
        return ecrecover(hash_, v, r, s);
    }

    function toAddress(bytes memory _value) internal pure returns (address) {
        return address(toBytes20(_value));
    }

    function toBytes4(bytes memory _value) internal pure returns (bytes4) {
        return bytes4(toFixedBytes(_value, 4));
    }
    
    function toBytes20(bytes memory _value) internal pure returns (bytes20) {
        return bytes20(toFixedBytes(_value, 20));
    }
    
    function toBytes32(bytes memory _value) internal pure returns (bytes32) {
        return toFixedBytes(_value, 32);
    }

    function intoMemArray(bytes32[1] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 1, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[2] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 2, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[3] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 3, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[4] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 4, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[5] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 5, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[6] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 6, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[7] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 7, _values), (bytes32[]));
    }

    function intoMemArray(bytes32[8] memory _values) internal pure returns (bytes32[] memory) {
        return abi.decode(abi.encode(uint256(32), 8, _values), (bytes32[]));
    }

    function toFixedBytes(bytes memory _value, uint8 _numBytes)
        internal pure
        returns (bytes32 _bytes32)
    {
        assert(_numBytes <= 32);
        unchecked {
            uint _len = _value.length > _numBytes ? _numBytes : _value.length;
            for (uint _i = 0; _i < _len; _i ++) {
                _bytes32 |= bytes32(_value[_i] & 0xff) >> (_i * 8);
            }
        }
    }


    /// ===============================================================================================================
    /// --- 'string' helper methods -----------------------------------------------------------------------------------

    function toLowerCase(string memory str)
        internal pure
        returns (string memory)
    {
        bytes memory lowered = new bytes(bytes(str).length);
        unchecked {
            for (uint i = 0; i < lowered.length; i ++) {
                uint8 char = uint8(bytes(str)[i]);
                if (char >= 65 && char <= 90) {
                    lowered[i] = bytes1(char + 32);
                } else {
                    lowered[i] = bytes1(char);
                }
            }
        }
        return string(lowered);
    }

    /// @notice Converts bytes32 into string.
    function toString(bytes32 _bytes32)
        internal pure
        returns (string memory)
    {
        bytes memory _bytes = new bytes(_toStringLength(_bytes32));
        for (uint _i = 0; _i < _bytes.length;) {
            _bytes[_i] = _bytes32[_i];
            unchecked {
                _i ++;
            }
        }
        return string(_bytes);
    }

    function tryUint(string memory str)
        internal pure
        returns (uint res, bool)
    {
        unchecked {
            for (uint256 i = 0; i < bytes(str).length; i++) {
                if (
                    (uint8(bytes(str)[i]) - 48) < 0
                        || (uint8(bytes(str)[i]) - 48) > 9
                ) {
                    return (0, false);
                }
                res += (uint8(bytes(str)[i]) - 48) * 10 ** (bytes(str).length - i - 1);
            }
            return (res, true);
        }
    }


    /// ===============================================================================================================
    /// --- 'uint*' helper methods ------------------------------------------------------------------------------------

    function determineBeaconIndexFromEpoch(uint32 epoch) internal pure returns (uint32) {
        return epoch / 10;
    }
    
    function determineBeaconIndexFromTimestamp(uint32 timestamp) internal pure returns (uint32) {
        return determineBeaconIndexFromEpoch(
            determineEpochFromTimestamp(
                timestamp
            )
        );
    }

    function determineEpochFromTimestamp(uint32 timestamp) internal pure returns (uint32) {
        if (timestamp > WIT_2_GENESIS_TIMESTAMP) {
            return (
                WIT_2_GENESIS_EPOCH
                    + (timestamp - WIT_2_GENESIS_TIMESTAMP)
                        / WIT_2_SECS_PER_EPOCH
            );
        } else if (timestamp > WIT_1_GENESIS_TIMESTAMP) {
            return (
                (timestamp - WIT_1_GENESIS_TIMESTAMP)
                    / WIT_1_SECS_PER_EPOCH
            );
        } else {
            return 0;
        }
    }

    function determineTimestampFromEpoch(uint32 epoch) internal pure returns (uint32) {
        if (epoch >= WIT_2_GENESIS_EPOCH) {
            return (
                WIT_2_GENESIS_TIMESTAMP
                    + (WIT_2_SECS_PER_EPOCH * (
                        epoch
                            - WIT_2_GENESIS_EPOCH)
                    )
            );
        } else return (
            WIT_1_SECS_PER_EPOCH
                * epoch
        );
    }

    /// Generates a pseudo-random uint32 number uniformly distributed within the range `[0 .. range)`, based on
    /// the given `nonce` and `seed` values. 
    function randomUniformUint32(uint32 range, uint256 nonce, bytes32 seed)
        internal pure 
        returns (uint32) 
    {
        uint256 _number = uint256(
            keccak256(
                abi.encode(seed, nonce)
            )
        ) & uint256(2 ** 224 - 1);
        return uint32((_number * range) >> 224);
    }

    /// @notice Convert a `uint8` into a 2 characters long `string` representing its two less significant hexadecimal values.
    function toHexString(uint8 _u)
        internal pure
        returns (string memory)
    {
        bytes memory b2 = new bytes(2);
        uint8 d0 = uint8(_u / 16) + 48;
        uint8 d1 = uint8(_u % 16) + 48;
        if (d0 > 57)
            d0 += 7;
        if (d1 > 57)
            d1 += 7;
        b2[0] = bytes1(d0);
        b2[1] = bytes1(d1);
        return string(b2);
    }

    /// @notice Convert a `uint8` into a 1, 2 or 3 characters long `string` representing its.
    /// three less significant decimal values.
    function toString(uint8 _u)
        internal pure
        returns (string memory)
    {
        if (_u < 10) {
            bytes memory b1 = new bytes(1);
            b1[0] = bytes1(uint8(_u) + 48);
            return string(b1);
        } else if (_u < 100) {
            bytes memory b2 = new bytes(2);
            b2[0] = bytes1(uint8(_u / 10) + 48);
            b2[1] = bytes1(uint8(_u % 10) + 48);
            return string(b2);
        } else {
            bytes memory b3 = new bytes(3);
            b3[0] = bytes1(uint8(_u / 100) + 48);
            b3[1] = bytes1(uint8(_u % 100 / 10) + 48);
            b3[2] = bytes1(uint8(_u % 10) + 48);
            return string(b3);
        }
    }

    /// @notice Convert a `uint` into a string` representing its value.
    function toString(uint v)
        internal pure 
        returns (string memory)
    {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        do {
            uint8 remainder = uint8(v % 10);
            v = v / 10;
            reversed[i ++] = bytes1(48 + remainder);
        } while (v != 0);
        bytes memory buf = new bytes(i);
        for (uint j = 1; j <= i; j ++) {
            buf[j - 1] = reversed[i - j];
        }
        return string(buf);
    }


    /// ===============================================================================================================
    /// --- Witnet library private methods ----------------------------------------------------------------------------

    function _merkleHash(bytes32 _a, bytes32 _b) private pure returns (bytes32 _hash) {
        assembly {
            mstore(0x0, _a)
            mstore(0x20, _b)
            _hash := keccak256(0x0, 0x40)
        }
    }

    /// @dev Calculate length of string-equivalent to given bytes32.
    function _toStringLength(bytes32 _bytes32)
        private pure
        returns (uint _length)
    {
        for (; _length < 32; ) {
            if (_bytes32[_length] == 0) {
                break;
            }
            unchecked {
                _length ++;
            }
        }
    }
}

File 11 of 47 : Slices.sol
// SPDX-License-Identifier: APACHE-2.0

pragma solidity >=0.8.0 <0.9.0;

/*
 * @title String & Slice utility library for Solidity contracts.
 * @author Nick Johnson <[email protected]>
 *
 * @dev Functionality in this library is largely implemented using an
 *      abstraction called a 'Slice'. A Slice represents a part of a string -
 *      anything from the entire string to a single character, or even no
 *      characters at all (a 0-length Slice). Since a Slice only has to specify
 *      an offset and a length, copying and manipulating slices is a lot less
 *      expensive than copying and manipulating the strings they reference.
 *
 *      To further reduce gas costs, most functions on Slice that need to return
 *      a Slice modify the original one instead of allocating a new one; for
 *      instance, `s.split(".")` will return the text up to the first '.',
 *      modifying s to only contain the remainder of the string after the '.'.
 *      In situations where you do not want to modify the original Slice, you
 *      can make a copy first with `.copy()`, for example:
 *      `s.copy().split(".")`. Try and avoid using this idiom in loops; since
 *      Solidity has no memory management, it will result in allocating many
 *      short-lived slices that are later discarded.
 *
 *      Functions that return two slices come in two versions: a non-allocating
 *      version that takes the second Slice as an argument, modifying it in
 *      place, and an allocating version that allocates and returns the second
 *      Slice; see `nextRune` for example.
 *
 *      Functions that have to copy string data will return strings rather than
 *      slices; these can be cast back to slices for further processing if
 *      required.
 *
 *      For convenience, some functions are provided with non-modifying
 *      variants that create a new Slice and return both; for instance,
 *      `s.splitNew('.')` leaves s unmodified, and returns two values
 *      corresponding to the left and right parts of the string.
 */

library Slices {
    
    struct Slice {
        uint _len;
        uint _ptr;
    }

    function _memcpy(uint _dest, uint _src, uint _len) private pure {
        // Copy word-length chunks while possible
        for(; _len >= 32; _len -= 32) {
            assembly {
                mstore(_dest, mload(_src))
            }
            _dest += 32;
            _src += 32;
        }

        // Copy remaining bytes
        uint _mask = type(uint).max;
        if (_len > 0) {
            _mask = 256 ** (32 - _len) - 1;
        }
        assembly {
            let srcpart := and(mload(_src), not(_mask))
            let destpart := and(mload(_dest), _mask)
            mstore(_dest, or(destpart, srcpart))
        }
    }

    /*
     * @dev Returns a Slice containing the entire string.
     * @param self The string to make a Slice from.
     * @return A newly allocated Slice containing the entire string.
     */
    function toSlice(string memory self) internal pure returns (Slice memory) {
        uint ptr;
        assembly {
            ptr := add(self, 0x20)
        }
        return Slice(bytes(self).length, ptr);
    }

    /*
     * @dev Returns the length of a null-terminated bytes32 string.
     * @param self The value to find the length of.
     * @return The length of the string, from 0 to 32.
     */
    function len(bytes32 self) internal pure returns (uint) {
        uint ret;
        if (self == 0)
            return 0;
        if (uint(self) & type(uint128).max == 0) {
            ret += 16;
            self = bytes32(uint(self) / 0x100000000000000000000000000000000);
        }
        if (uint(self) & type(uint64).max == 0) {
            ret += 8;
            self = bytes32(uint(self) / 0x10000000000000000);
        }
        if (uint(self) & type(uint32).max == 0) {
            ret += 4;
            self = bytes32(uint(self) / 0x100000000);
        }
        if (uint(self) & type(uint16).max == 0) {
            ret += 2;
            self = bytes32(uint(self) / 0x10000);
        }
        if (uint(self) & type(uint8).max == 0) {
            ret += 1;
        }
        return 32 - ret;
    }

    /*
     * @dev Returns a Slice containing the entire bytes32, interpreted as a
     *      null-terminated utf-8 string.
     * @param self The bytes32 value to convert to a Slice.
     * @return A new Slice containing the value of the input argument up to the
     *         first null.
     */
    function toSliceB32(bytes32 self) internal pure returns (Slice memory ret) {
        // Allocate space for `self` in memory, copy it there, and point ret at it
        assembly {
            let ptr := mload(0x40)
            mstore(0x40, add(ptr, 0x20))
            mstore(ptr, self)
            mstore(add(ret, 0x20), ptr)
        }
        ret._len = len(self);
    }

    /*
     * @dev Returns a new Slice containing the same data as the current Slice.
     * @param self The Slice to copy.
     * @return A new Slice containing the same data as `self`.
     */
    function copy(Slice memory self) internal pure returns (Slice memory) {
        return Slice(self._len, self._ptr);
    }

    /*
     * @dev Copies a Slice to a new string.
     * @param self The Slice to copy.
     * @return A newly allocated string containing the Slice's text.
     */
    function toString(Slice memory self) internal pure returns (string memory) {
        string memory ret = new string(self._len);
        uint retptr;
        assembly { retptr := add(ret, 32) }

        _memcpy(retptr, self._ptr, self._len);
        return ret;
    }

    /*
     * @dev Returns the length in runes of the Slice. Note that this operation
     *      takes time proportional to the length of the Slice; avoid using it
     *      in loops, and call `Slice.empty()` if you only need to know whether
     *      the Slice is empty or not.
     * @param self The Slice to operate on.
     * @return The length of the Slice in runes.
     */
    function len(Slice memory self) internal pure returns (uint _l) {
        // Starting at ptr-31 means the LSB will be the byte we care about
        uint ptr = self._ptr - 31;
        uint end = ptr + self._len;
        for (_l = 0; ptr < end; _l++) {
            uint8 b;
            assembly { b := and(mload(ptr), 0xFF) }
            if (b < 0x80) {
                ptr += 1;
            } else if(b < 0xE0) {
                ptr += 2;
            } else if(b < 0xF0) {
                ptr += 3;
            } else if(b < 0xF8) {
                ptr += 4;
            } else if(b < 0xFC) {
                ptr += 5;
            } else {
                ptr += 6;
            }
        }
    }

    /*
     * @dev Returns true if the Slice is empty (has a length of 0).
     * @param self The Slice to operate on.
     * @return True if the Slice is empty, False otherwise.
     */
    function empty(Slice memory self) internal pure returns (bool) {
        return self._len == 0;
    }

    /*
     * @dev Returns a positive number if `other` comes lexicographically after
     *      `self`, a negative number if it comes before, or zero if the
     *      contents of the two slices are equal. Comparison is done per-rune,
     *      on unicode codepoints.
     * @param self The first Slice to compare.
     * @param other The second Slice to compare.
     * @return The result of the comparison.
     */
    function compare(Slice memory self, Slice memory other) internal pure returns (int) {
        uint shortest = self._len;
        if (other._len < self._len)
            shortest = other._len;

        uint selfptr = self._ptr;
        uint otherptr = other._ptr;
        for (uint idx = 0; idx < shortest; idx += 32) {
            uint a;
            uint b;
            assembly {
                a := mload(selfptr)
                b := mload(otherptr)
            }
            if (a != b) {
                // Mask out irrelevant bytes and check again
                uint mask = type(uint).max; // 0xffff...
                if(shortest < 32) {
                  mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);
                }
                unchecked {
                    uint diff = (a & mask) - (b & mask);
                    if (diff != 0)
                        return int(diff);
                }
            }
            selfptr += 32;
            otherptr += 32;
        }
        return int(self._len) - int(other._len);
    }

    /*
     * @dev Returns true if the two slices contain the same text.
     * @param self The first Slice to compare.
     * @param self The second Slice to compare.
     * @return True if the slices are equal, false otherwise.
     */
    function equals(Slice memory self, Slice memory other) internal pure returns (bool) {
        return compare(self, other) == 0;
    }

    /*
     * @dev Extracts the first rune in the Slice into `rune`, advancing the
     *      Slice to point to the next rune and returning `self`.
     * @param self The Slice to operate on.
     * @param rune The Slice that will contain the first rune.
     * @return `rune`.
     */
    function nextRune(Slice memory self, Slice memory rune) internal pure returns (Slice memory) {
        rune._ptr = self._ptr;

        if (self._len == 0) {
            rune._len = 0;
            return rune;
        }

        uint _l;
        uint _b;
        // Load the first byte of the rune into the LSBs of _b
        assembly { _b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) }
        if (_b < 0x80) {
            _l = 1;
        } else if(_b < 0xE0) {
            _l = 2;
        } else if(_b < 0xF0) {
            _l = 3;
        } else {
            _l = 4;
        }

        // Check for truncated codepoints
        if (_l > self._len) {
            rune._len = self._len;
            self._ptr += self._len;
            self._len = 0;
            return rune;
        }

        self._ptr += _l;
        self._len -= _l;
        rune._len = _l;
        return rune;
    }

    /*
     * @dev Returns the first rune in the Slice, advancing the Slice to point
     *      to the next rune.
     * @param self The Slice to operate on.
     * @return A Slice containing only the first rune from `self`.
     */
    function nextRune(Slice memory self) internal pure returns (Slice memory ret) {
        nextRune(self, ret);
    }

    /*
     * @dev Returns the number of the first codepoint in the Slice.
     * @param self The Slice to operate on.
     * @return The number of the first codepoint in the Slice.
     */
    function ord(Slice memory self) internal pure returns (uint ret) {
        if (self._len == 0) {
            return 0;
        }

        uint word;
        uint length;
        uint divisor = 2 ** 248;

        // Load the rune into the MSBs of b
        assembly { word:= mload(mload(add(self, 32))) }
        uint b = word / divisor;
        if (b < 0x80) {
            ret = b;
            length = 1;
        } else if(b < 0xE0) {
            ret = b & 0x1F;
            length = 2;
        } else if(b < 0xF0) {
            ret = b & 0x0F;
            length = 3;
        } else {
            ret = b & 0x07;
            length = 4;
        }

        // Check for truncated codepoints
        if (length > self._len) {
            return 0;
        }

        for (uint i = 1; i < length; i++) {
            divisor = divisor / 256;
            b = (word / divisor) & 0xFF;
            if (b & 0xC0 != 0x80) {
                // Invalid UTF-8 sequence
                return 0;
            }
            ret = (ret * 64) | (b & 0x3F);
        }

        return ret;
    }

    /*
     * @dev Returns the keccak-256 hash of the Slice.
     * @param self The Slice to hash.
     * @return The hash of the Slice.
     */
    function keccak(Slice memory self) internal pure returns (bytes32 ret) {
        assembly {
            ret := keccak256(mload(add(self, 32)), mload(self))
        }
    }

    /*
     * @dev Returns true if `self` starts with `needle`.
     * @param self The Slice to operate on.
     * @param needle The Slice to search for.
     * @return True if the Slice starts with the provided text, false otherwise.
     */
    function startsWith(Slice memory self, Slice memory needle) internal pure returns (bool) {
        if (self._len < needle._len) {
            return false;
        }

        if (self._ptr == needle._ptr) {
            return true;
        }

        bool equal;
        assembly {
            let length := mload(needle)
            let selfptr := mload(add(self, 0x20))
            let needleptr := mload(add(needle, 0x20))
            equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
        }
        return equal;
    }

    /*
     * @dev If `self` starts with `needle`, `needle` is removed from the
     *      beginning of `self`. Otherwise, `self` is unmodified.
     * @param self The Slice to operate on.
     * @param needle The Slice to search for.
     * @return `self`
     */
    function beyond(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {
        if (self._len < needle._len) {
            return self;
        }

        bool equal = true;
        if (self._ptr != needle._ptr) {
            assembly {
                let length := mload(needle)
                let selfptr := mload(add(self, 0x20))
                let needleptr := mload(add(needle, 0x20))
                equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
            }
        }

        if (equal) {
            self._len -= needle._len;
            self._ptr += needle._len;
        }

        return self;
    }

    /*
     * @dev Returns true if the Slice ends with `needle`.
     * @param self The Slice to operate on.
     * @param needle The Slice to search for.
     * @return True if the Slice starts with the provided text, false otherwise.
     */
    function endsWith(Slice memory self, Slice memory needle) internal pure returns (bool) {
        if (self._len < needle._len) {
            return false;
        }

        uint selfptr = self._ptr + self._len - needle._len;

        if (selfptr == needle._ptr) {
            return true;
        }

        bool equal;
        assembly {
            let length := mload(needle)
            let needleptr := mload(add(needle, 0x20))
            equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
        }

        return equal;
    }

    /*
     * @dev If `self` ends with `needle`, `needle` is removed from the
     *      end of `self`. Otherwise, `self` is unmodified.
     * @param self The Slice to operate on.
     * @param needle The Slice to search for.
     * @return `self`
     */
    function until(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {
        if (self._len < needle._len) {
            return self;
        }

        uint selfptr = self._ptr + self._len - needle._len;
        bool equal = true;
        if (selfptr != needle._ptr) {
            assembly {
                let length := mload(needle)
                let needleptr := mload(add(needle, 0x20))
                equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
            }
        }

        if (equal) {
            self._len -= needle._len;
        }

        return self;
    }

    // Returns the memory address of the first byte of the first occurrence of
    // `needle` in `self`, or the first byte after `self` if not found.
    function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
        uint ptr = selfptr;
        uint idx;

        if (needlelen <= selflen) {
            if (needlelen <= 32) {
                bytes32 mask;
                if (needlelen > 0) {
                    mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
                }

                bytes32 needledata;
                assembly { needledata := and(mload(needleptr), mask) }

                uint end = selfptr + selflen - needlelen;
                bytes32 ptrdata;
                assembly { ptrdata := and(mload(ptr), mask) }

                while (ptrdata != needledata) {
                    if (ptr >= end)
                        return selfptr + selflen;
                    ptr++;
                    assembly { ptrdata := and(mload(ptr), mask) }
                }
                return ptr;
            } else {
                // For long needles, use hashing
                bytes32 hash;
                assembly { hash := keccak256(needleptr, needlelen) }

                for (idx = 0; idx <= selflen - needlelen; idx++) {
                    bytes32 testHash;
                    assembly { testHash := keccak256(ptr, needlelen) }
                    if (hash == testHash)
                        return ptr;
                    ptr += 1;
                }
            }
        }
        return selfptr + selflen;
    }

    // Returns the memory address of the first byte after the last occurrence of
    // `needle` in `self`, or the address of `self` if not found.
    function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
        uint ptr;

        if (needlelen <= selflen) {
            if (needlelen <= 32) {
                bytes32 mask;
                if (needlelen > 0) {
                    mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
                }

                bytes32 needledata;
                assembly { needledata := and(mload(needleptr), mask) }

                ptr = selfptr + selflen - needlelen;
                bytes32 ptrdata;
                assembly { ptrdata := and(mload(ptr), mask) }

                while (ptrdata != needledata) {
                    if (ptr <= selfptr)
                        return selfptr;
                    ptr--;
                    assembly { ptrdata := and(mload(ptr), mask) }
                }
                return ptr + needlelen;
            } else {
                // For long needles, use hashing
                bytes32 hash;
                assembly { hash := keccak256(needleptr, needlelen) }
                ptr = selfptr + (selflen - needlelen);
                while (ptr >= selfptr) {
                    bytes32 testHash;
                    assembly { testHash := keccak256(ptr, needlelen) }
                    if (hash == testHash)
                        return ptr + needlelen;
                    ptr -= 1;
                }
            }
        }
        return selfptr;
    }

    /*
     * @dev Modifies `self` to contain everything from the first occurrence of
     *      `needle` to the end of the Slice. `self` is set to the empty Slice
     *      if `needle` is not found.
     * @param self The Slice to search and modify.
     * @param needle The text to search for.
     * @return `self`.
     */
    function find(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {
        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);
        self._len -= ptr - self._ptr;
        self._ptr = ptr;
        return self;
    }

    /*
     * @dev Modifies `self` to contain the part of the string from the start of
     *      `self` to the end of the first occurrence of `needle`. If `needle`
     *      is not found, `self` is set to the empty Slice.
     * @param self The Slice to search and modify.
     * @param needle The text to search for.
     * @return `self`.
     */
    function rfind(Slice memory self, Slice memory needle) internal pure returns (Slice memory) {
        uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);
        self._len = ptr - self._ptr;
        return self;
    }

    /*
     * @dev Splits the Slice, setting `self` to everything after the first
     *      occurrence of `needle`, and `token` to everything before it. If
     *      `needle` does not occur in `self`, `self` is set to the empty Slice,
     *      and `token` is set to the entirety of `self`.
     * @param self The Slice to split.
     * @param needle The text to search for in `self`.
     * @param token An output parameter to which the first token is written.
     * @return `token`.
     */
    function split(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) {
        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);
        token._ptr = self._ptr;
        token._len = ptr - self._ptr;
        if (ptr == self._ptr + self._len) {
            // Not found
            self._len = 0;
        } else {
            self._len -= token._len + needle._len;
            self._ptr = ptr + needle._len;
        }
        return token;
    }

    /*
     * @dev Splits the Slice, setting `self` to everything after the first
     *      occurrence of `needle`, and returning everything before it. If
     *      `needle` does not occur in `self`, `self` is set to the empty Slice,
     *      and the entirety of `self` is returned.
     * @param self The Slice to split.
     * @param needle The text to search for in `self`.
     * @return The part of `self` up to the first occurrence of `delim`.
     */
    function split(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) {
        split(self, needle, token);
    }

    /*
     * @dev Splits the Slice, setting `self` to everything before the last
     *      occurrence of `needle`, and `token` to everything after it. If
     *      `needle` does not occur in `self`, `self` is set to the empty Slice,
     *      and `token` is set to the entirety of `self`.
     * @param self The Slice to split.
     * @param needle The text to search for in `self`.
     * @param token An output parameter to which the first token is written.
     * @return `token`.
     */
    function rsplit(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) {
        uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);
        token._ptr = ptr;
        token._len = self._len - (ptr - self._ptr);
        if (ptr == self._ptr) {
            // Not found
            self._len = 0;
        } else {
            self._len -= token._len + needle._len;
        }
        return token;
    }

    /*
     * @dev Splits the Slice, setting `self` to everything before the last
     *      occurrence of `needle`, and returning everything after it. If
     *      `needle` does not occur in `self`, `self` is set to the empty Slice,
     *      and the entirety of `self` is returned.
     * @param self The Slice to split.
     * @param needle The text to search for in `self`.
     * @return The part of `self` after the last occurrence of `delim`.
     */
    function rsplit(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) {
        rsplit(self, needle, token);
    }

    /*
     * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`.
     * @param self The Slice to search.
     * @param needle The text to search for in `self`.
     * @return The number of occurrences of `needle` found in `self`.
     */
    function count(Slice memory self, Slice memory needle) internal pure returns (uint cnt) {
        uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len;
        while (ptr <= self._ptr + self._len) {
            cnt++;
            ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len;
        }
    }

    /*
     * @dev Returns True if `self` contains `needle`.
     * @param self The Slice to search.
     * @param needle The text to search for in `self`.
     * @return True if `needle` is found in `self`, false otherwise.
     */
    function contains(Slice memory self, Slice memory needle) internal pure returns (bool) {
        return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr;
    }

    /*
     * @dev Returns a newly allocated string containing the concatenation of
     *      `self` and `other`.
     * @param self The first Slice to concatenate.
     * @param other The second Slice to concatenate.
     * @return The concatenation of the two strings.
     */
    function concat(Slice memory self, Slice memory other) internal pure returns (string memory) {
        string memory ret = new string(self._len + other._len);
        uint retptr;
        assembly { retptr := add(ret, 32) }
        _memcpy(retptr, self._ptr, self._len);
        _memcpy(retptr + self._len, other._ptr, other._len);
        return ret;
    }

    /*
     * @dev Joins an array of slices, using `self` as a delimiter, returning a
     *      newly allocated string.
     * @param self The delimiter to use.
     * @param parts A list of slices to join.
     * @return A newly allocated string containing all the slices in `parts`,
     *         joined with `self`.
     */
    function join(Slice memory self, Slice[] memory parts) internal pure returns (string memory) {
        if (parts.length == 0)
            return "";

        uint length = self._len * (parts.length - 1);
        for(uint i = 0; i < parts.length; i++)
            length += parts[i]._len;

        string memory ret = new string(length);
        uint retptr;
        assembly { retptr := add(ret, 32) }

        for(uint i = 0; i < parts.length; i++) {
            _memcpy(retptr, parts[i]._ptr, parts[i]._len);
            retptr += parts[i]._len;
            if (i < parts.length - 1) {
                _memcpy(retptr, self._ptr, self._len);
                retptr += self._len;
            }
        }

        return ret;
    }
}

File 12 of 47 : IWitPriceFeedsSolverFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

interface IWitPriceFeedsSolverFactory {
    event NewPriceFeedsSolver(address solver, bytes32 codehash, bytes constructorParams);
    function deployPriceSolver(bytes calldata initcode, bytes calldata additionalParams) external returns (address);
    function determinePriceSolverAddress(bytes calldata initcode, bytes calldata additionalParams) external view returns (address);
}

File 13 of 47 : IWitPriceFeedsSolver.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitPriceFeedsSolver {
    enum LatestUpdateStatus {
        Void,
        Awaiting,
        Ready,
        Error
    }
    struct Price {
        uint64 value;
        Witnet.ResultTimestamp timestamp;
        Witnet.TransactionHash drTxHash;
        LatestUpdateStatus latestStatus;
    }
    function class() external pure returns (string memory);
    function delegator() external view returns (address);
    function solve(bytes4 feedId) external view returns (Price memory);
    function specs() external pure returns (bytes4);
    function validate(bytes4 feedId, string[] calldata initdata) external;
}

File 14 of 47 : IWitPriceFeeds.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IWitPriceFeedsSolver.sol";

interface IWitPriceFeeds {   
    /// ======================================================================================================
    /// --- IFeeds extension ---------------------------------------------------------------------------------
    
    function lookupDecimals(bytes4 feedId) external view returns (uint8);    
    function lookupPriceSolver(bytes4 feedId) external view returns (
            IWitPriceFeedsSolver solverAddress, 
            string[] memory solverDeps
        );

    /// ======================================================================================================
    /// --- IWitFeeds extension ---------------------------------------------------------------------------

    function latestPrice(bytes4 feedId) external view returns (IWitPriceFeedsSolver.Price memory);
    function latestPrices(bytes4[] calldata feedIds)  external view returns (IWitPriceFeedsSolver.Price[] memory);
}

File 15 of 47 : IWitOracleRequestTemplate.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IWitOracleRequest.sol";

interface IWitOracleRequestTemplate {

    /// Builds a WitOracleRequest instance that will provide the bytecode and RAD 
    /// hash of some Witnet-compliant Radon Request, provably made out of the 
    /// data sources, aggregate and tally Radon Reducers that compose this instance.
    /// Reverts if the ranks of passed array don't match either the number of this template's 
    /// data sources, or the number of required parameters by each one of those.
    /// @dev Produced addresses are counter-factual to the template address and the given values.
    function buildWitOracleRequest (string[][] calldata args) external returns (IWitOracleRequest);

    /// Builds a WitOracleRequest instance by specifying one single parameter value
    /// that will be equally applied to all the template's data sources.
    /// Reverts if any of the underlying data sources requires more than just one parameter.
    /// @dev Produced addresses are counter-factual to the template address and the given value.
    function buildWitOracleRequest (string calldata singleArgValue) external returns (IWitOracleRequest);

    /// Returns an array of integers telling the number of parameters required 
    /// by every single data source (i.e. Radon Retrievals) that compose this 
    /// WitOracleRequestTemplate. The length of the returned array tells the number 
    /// of data sources that compose this instance.
    function getArgsCount() external view returns (uint256[] memory);

    /// Returns the filters and reducing functions to be applied by witnessing nodes 
    /// on the Witnet blockchain both at the:
    /// - Aggregate stage: when aggregating data extracted from the public 
    ///                    data sources (i.e. Radon Retrievals).
    /// - Tally stage: when aggregating values revealed by witnesses.
    function getRadonReducers() external view returns (
            Witnet.RadonReducer memory aggregateStage,
            Witnet.RadonReducer memory tallyStage
        );

    /// Returns metadata concerning the data source specified by the given index. 
    function getRadonRetrievalByIndex(uint256) external view returns (Witnet.RadonRetrieval memory);

    /// Returns the array of one or more parameterized data sources that compose 
    /// this WitOracleRequestTemplate.
    function getRadonRetrievals() external view returns (Witnet.RadonRetrieval[] memory);

    /// Returns the expected data type produced by successful resolutions of 
    /// any WitOracleRequest that gets built out of this WitOracleRequestTemplate.
    function getResultDataType() external view returns (Witnet.RadonDataTypes); 

    /// Verifies into the bounded WitOracle's registry the actual bytecode 
    /// and RAD hash of the Witnet-compliant Radon Request that gets provably 
    /// made out of the data sources, aggregate and tally Radon Reducers that 
    /// compose this WitOracleRequestTemplate. While no WitOracleRequest instance is 
    /// actually constructed, the returned value will be accepted as a valid
    /// RAD hash on the witOracle() contract from now on. 
    /// Reverts if:
    /// - the ranks of passed array don't match either the number of this 
    ///   template's data sources, or the number of required parameters by 
    ///   each one of those.
    /// @dev This method requires less gas than buildWitOracleRequest(string[][]), and 
    /// @dev it's usually preferred when data requests built out of this template
    /// @dev are intended to be used just once in lifetime.    
    function verifyRadonRequest(string[][] calldata args) external returns (bytes32);

    /// Verifies into the bounded WitOracle's registry the actual bytecode
    /// and RAD hash of the Witnet-compliant Radon Request that gets provably
    /// made out as a result of applying the given parameter value to the underlying
    /// data sources, aggregate and tally reducers that compose this template. 
    /// While no actual WitOracleRequest instance gets constructed, the returned value
    /// will be accepted as a valid RAD hash on the bounded WitOracle contract from now on.
    /// Reverts if any of the underlying data sources requires more than just one parameter.
    /// @dev This method requires less gas than buildWitOracleRequest(string), and 
    /// @dev it's usually preferred when data requests built out of this template
    /// @dev are intended to be used just once in lifetime.
    function verifyRadonRequest(string calldata singleArgValue) external returns (bytes32);

    /// If built out of an upgradable factory, returns the SemVer tag of the 
    /// factory implementation at the time when this WitOracleRequestTemplate got built.
    function version() external view returns (string memory);
}

File 16 of 47 : IWitOracleRequestFactoryEvents.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

interface IWitOracleRequestFactoryEvents {

    /// Emitted every time a new counter-factual WitOracleRequest gets verified and built. 
    event WitOracleRequestBuilt(address request);

    /// Emitted every time a new counter-factual WitOracleRequestTemplate gets verified and built. 
    event WitOracleRequestTemplateBuilt(address template);
}

File 17 of 47 : IWitOracleRequestFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IWitOracleRequestTemplate.sol";

interface IWitOracleRequestFactory {
    
    /// @notice Builds a WitOracleRequest instance that will provide the bytecode
    /// @notice and RAD hash of some Witnet-compliant data request, provably 
    /// @notice made out of some previously verified Witnet Radon Retrievals
    /// @notice (i.e. data sources), aggregate and tally Witnet Radon Reducers.
    /// @dev Reverts if:
    /// @dev   - unverified retrievals are passed;
    /// @dev   - any of the given retrievals is parameterized;
    /// @dev   - retrievals return different data types;
    /// @dev   - unsupported reducers are passed.
    /// @param retrieveHashes Hashes of previously verified data sources.
    /// @param aggregate The Radon Reducer to apply on values returned from data sources.
    /// @param tally The Radon Reducer to apply on values revealed by witnessing nodes.
    function buildWitOracleRequest(
            bytes32[] calldata retrieveHashes,
            Witnet.RadonReducer calldata aggregate,
            Witnet.RadonReducer calldata tally
        ) external returns (IWitOracleRequest);

    /// @notice Builds a modal WitOracleRequest instance out of one single parameterized 
    /// @notice Witnet Radon Retrieval. Modal data requests apply the same data retrieval script
    /// @notice to multiple data providers that are expected to produce exactly the same result. 
    /// @notice Moreover, modal data requests apply a Mode reducing function at both the 
    /// @notice Aggregate and Tally stages everytime they get eventually solved on the Wit/Oracle
    /// @notice blockhain. You can optionally specify a list of filters to be applied at the Tally 
    /// @notice resolution stage (i.e. witnessing nodes on the Wit/Oracle blockchain reporting results
    /// @notice that get ultimately filtered out on the Tally stage would get slashed by losing collateral).
    /// @dev Reverts if:
    /// @dev  - unverified base Radon Retrieval is passed;
    /// @dev  - the specified base Radon Retrieval is not parameterized;
    /// @dev  - 2nd dimension's rank of the `requestArgs` array doesn't match the number of required parameters 
    /// @dev    required by the given Radon Retrieval;
    /// @dev  - unsupported Radon Filters are passed.
    /// @param baseRetrieveHash Hash of the parameterized Radon Retrieval upon which the new data request will be built.
    /// @param requestArgs Parameters to be applied to each repetition of the given retrieval.
    /// @param tallySlashingFilters Optional array of slashing filters to will be applied at the Tally stage.
    function buildWitOracleRequestModal(
            bytes32 baseRetrieveHash,
            string[][] calldata requestArgs,
            Witnet.RadonFilter[] calldata tallySlashingFilters
        ) external returns (IWitOracleRequest);

    /// @notice Builds a WitOracleRequestTemplate instance made out of one or more
    /// @notice parameterized Witnet Radon Retrievals (i.e. data sources), aggregate
    /// @notice and tally Witnet Radon Reducers. 
    /// @dev Reverts if:
    /// @dev   - unverified retrievals are passed;
    /// @dev   - none of given retrievals is parameterized;
    /// @dev   - retrievals return different data types;
    /// @dev   - unsupported reducers are passed.
    /// @param retrieveHashes Hashes of previously verified data sources.
    /// @param aggregate The Radon Reducer to apply on values returned from data sources.
    /// @param tally The Radon Reducer to apply on values revealed by witnessing nodes.
    function buildWitOracleRequestTemplate(
            bytes32[]  calldata retrieveHashes,
            Witnet.RadonReducer calldata aggregate,
            Witnet.RadonReducer calldata tally
        ) external returns (IWitOracleRequestTemplate);

    /// @notice Builds a modal WitOracleRequestTemplate instance out of one single parameterized 
    /// @notice Witnet Radon Retrieval. Modal request templates produce Witnet-compliant data requests
    /// @notice that apply the same data retrieval script to multiple data providers that are expected to
    /// @notice produce exactly the same result. Moreover, data requests built out of a modal request templates
    /// @notice apply a Mode reducing function at both the Aggregate and Tally stages every time they get
    /// @notice eventually solved on the Wit/Oracle blockchain. You can optionally specify a list of filters 
    /// @notice to be applied at the Tally resolution stage (i.e. witnessing nodes on the Wit/Oracle blockchain
    /// @notice reporting results that get ultimately filtered out on the Tally stage would get slashed by losing collateral).
    /// @dev Reverts if:
    /// @dev  - unverified base Radon Retrieval is passed;
    /// @dev  - the specified base Radon Retrieval is either not parameterized or requires just one single parameter;
    /// @dev  - unsupported Radon Filters are passed.
    /// @param baseRetrieveHash Hash of the parameterized Radon Retrieval upon which the new data request will be built.
    /// @param lastArgValues Parameters to be applied to each repetition of the given retrieval.
    /// @param tallySlashingFilters Optional array of slashing filters to will be applied at the Tally stage.
    function buildWitOracleRequestTemplateModal(
            bytes32 baseRetrieveHash,
            string[] calldata lastArgValues,
            Witnet.RadonFilter[] calldata tallySlashingFilters
        ) external returns (IWitOracleRequestTemplate);

    /// @notice Verifies and registers the specified Witnet Radon Retrieval 
    /// @notice (i.e. public data sources) into the WitOracleRadonRegistry of the
    /// @notice WitOracle attached to this factory. Returns a hash that uniquely 
    /// @notice identifies validated data source within the WitOracleRadonRegistry.
    /// @dev Note: all input parameters but the `requestMethod` are parameterizable
    /// @dev       by using embedded wildcard `\x\` substrings (being `x='0'..'9').
    /// @dev Reverts if:
    /// @dev   - unsupported data request method is given;
    /// @dev   - no URL is provided on Http/* data requests;
    /// @dev   - non-empty strings given on RNG data requests..
    function verifyRadonRetrieval(
            Witnet.RadonRetrievalMethods requestMethod,
            string calldata requestURL,
            string calldata requestBody,
            string[2][] calldata requestHeaders,
            bytes calldata requestRadonScript
        ) external returns (bytes32 retrievalHash);
}

File 18 of 47 : IWitOracleRequest.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitOracleRequest {

    /// Returns the Witnet-compliant RAD bytecode for the data request (i.e. Radon Request) 
    /// contained within this WitOracleRequest.
    function bytecode() external view returns (bytes memory);

    /// Returns the Witnet-compliant RAD hash of the data request (i.e. Radon Request) 
    /// contained within this WitOracleRequest. 
    function radHash() external view returns (bytes32);

    /// Returns the filters and reducing functions to be applied by witnessing nodes 
    /// on the Witnet blockchain both at the:
    /// - Aggregate stage: when aggregating data extracted from the public 
    ///                    data sources (i.e. Radon Retrievals).
    /// - Tally stage: when aggregating values revealed by witnesses.
    function getRadonReducers() external view returns (
            Witnet.RadonReducer memory aggregateStage,
            Witnet.RadonReducer memory tallyStage
        );

    
    /// Returns metadata concerning the data source specified by the given index.
    function getRadonRetrievalByIndex(uint256) external view returns (Witnet.RadonRetrieval memory);

    /// Returns the array of one or more data sources (i.e. Radon Retrievals) 
    /// that compose this WitOracleRequest.
    function getRadonRetrievals() external view returns (Witnet.RadonRetrieval[] memory);

    /// Returns the expected data type produced by successful resolutions of the 
    /// Witnet-compliant data request contained within this WitOracleRequest.
    function getResultDataType() external view returns (Witnet.RadonDataTypes);

    /// If built out of an upgradable factory, or template, returns the SemVer tag of 
    /// the actual implementation version at the time when this WitOracleRequest got built.
    function version() external view returns (string memory);
}

File 19 of 47 : IWitOracleRadonRegistryEvents.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitOracleRadonRegistryEvents {

    /// Emitted every time a new Radon Reducer gets successfully verified and
    /// stored into the WitOracleRadonRegistry.
    event NewRadonReducer(bytes32 hash);

    /// Emitted every time a new Radon Retrieval gets successfully verified and
    /// stored into the WitOracleRadonRegistry.
    event NewRadonRetrieval(bytes32 hash);

    /// Emitted every time a new Radon Request gets successfully verified and
    /// stored into the WitOracleRadonRegistry.
    event NewRadonRequest(bytes32 radHash);
}

File 20 of 47 : IWitOracleRadonRegistry.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitOracleRadonRegistry {

    /// Returns the Witnet-compliant RAD bytecode for some Radon Request 
    /// identified by its unique RAD hash. 
    function bytecodeOf(bytes32 radHash) external view returns (bytes memory);

    /// Returns the Witnet-compliant DRO bytecode for some data request object 
    /// made out of the given Radon Request and Radon SLA security parameters. 
    function bytecodeOf(
            bytes32 radHash, 
            Witnet.QuerySLA calldata sla
        ) external view returns (bytes memory);
    
    /// Returns the Witnet-compliant DRO bytecode for some data request object 
    /// made out of the given RAD bytecode and Radon SLA security parameters. 
    function bytecodeOf(
            bytes calldata radBytecode, 
            Witnet.QuerySLA calldata sla
        ) external view returns (bytes memory);
    
    /// Returns the hash of the given Witnet-compliant bytecode. Returned value
    /// can be used to trace back in the Witnet blockchain all past resolutions 
    /// of the given data request payload.
    function hashOf(bytes calldata) external view returns (bytes32);

    /// Returns the whole Witnet.RadonReducer metadata struct for the given hash.
    /// Reverts if unknown.
    function lookupRadonReducer(bytes32 hash) external view returns (Witnet.RadonReducer memory);

    /// Returns the whole Witnet.RadonRequest metadata struct for the given RAD hash value. 
    /// Reverts if unknown.
    function lookupRadonRequest(bytes32 radHash) external view returns (Witnet.RadonRequest memory);
    
    /// Returns the Aggregate reducer that is applied to the data extracted from the data sources 
    /// (i.e. Radon Retrievals) whenever the given Radon Request gets solved on the Witnet blockchain. 
    /// Reverts if unknown.
    function lookupRadonRequestAggregator(bytes32 radHash) external view returns (Witnet.RadonReducer memory);
    
    /// Returns the deterministic data type returned by successful resolutions of the given Radon Request. 
    /// Reverts if unknown.
    function lookupRadonRequestResultDataType(bytes32 radHash) external view returns (Witnet.RadonDataTypes);

    /// Returns introspective metadata for the index-th data source of some pre-verified Radon Request. 
    /// Reverts if out of range.
    function lookupRadonRequestRetrievalByIndex(bytes32 radHash, uint256 index) external view returns (Witnet.RadonRetrieval memory);

    /// Returns an array (one or more items) containing the introspective metadata of the given Radon Request's 
    /// data sources (i.e. Radon Retrievals). Reverts if unknown.
    function lookupRadonRequestRetrievals(bytes32 radHash) external view returns (Witnet.RadonRetrieval[] memory);

    /// Returns the Tally reducer that is applied to aggregated values revealed by the witnessing nodes on the 
    /// Witnet blockchain. Reverts if unknown.
    function lookupRadonRequestTally(bytes32 radHash) external view returns (Witnet.RadonReducer memory);

    /// Returns introspective metadata of some previously verified Radon Retrieval 
    /// (i.e. public data source). Reverts if unknown.
    function lookupRadonRetrieval(bytes32 hash) external view returns (Witnet.RadonRetrieval memory);
    
    /// Returns the number of indexed parameters required to be fulfilled when 
    /// eventually using the given Radon Retrieval. Reverts if unknown.
    function lookupRadonRetrievalArgsCount(bytes32 hash) external view returns (uint8);

    /// Returns the type of the data that would be retrieved by the given Radon Retrieval 
    /// (i.e. public data source). Reverts if unknown.
    function lookupRadonRetrievalResultDataType(bytes32 hash) external view returns (Witnet.RadonDataTypes);

    /// Verifies and registers the given sequence of dataset filters and reducing function to be 
    /// potentially used as either Aggregate or Tally reducers within the resolution workflow
    /// of Radon Requests in the Wit/oracle blockchain. Returns a unique hash that identifies the 
    /// given Radon Reducer in the registry. Reverts if unsupported reducing or filtering methods
    /// are specified.
    function verifyRadonReducer(Witnet.RadonReducer calldata reducer) external returns (bytes32 hash);
    
    /// Verifies and registers the specified Radon Request out of the given data sources (i.e. retrievals)
    /// and the aggregate and tally Radon Reducers. Returns a unique RAD hash that identifies the 
    /// verified Radon Request. Reverts if:
    /// - unverified retrievals are passed;
    /// - retrievals return different data types;
    /// - any of passed retrievals is parameterized;
    /// - unsupported reducers are passed.
    function verifyRadonRequest(
            bytes32[] calldata retrieveHashes,
            Witnet.RadonReducer calldata aggregate,
            Witnet.RadonReducer calldata tally
        ) external returns (bytes32 radHash);

    function verifyRadonRequest(
            bytes32[] calldata retrieveHashes,
            bytes32 aggregateReducerHash,
            bytes32 tallyReducerHash
        ) external returns (bytes32 radHash);

    /// Verifies and registers the specified Radon Request out of the given data sources (i.e. retrievals), 
    /// data sources parameters (if required), and the aggregate and tally Radon Reducers. Returns a unique 
    /// RAD hash that identifies the verified Radon Request.
    /// Reverts if:
    /// - unverified retrievals are passed;
    /// - retrievals return different data types;
    /// - ranks of passed args don't match with those required by each given retrieval;
    /// - unsupported reducers are passed.
    function verifyRadonRequest(
            bytes32[] calldata retrieveHashes,
            string[][] calldata retrieveArgs,
            Witnet.RadonReducer calldata aggregate,
            Witnet.RadonReducer calldata tally
        ) external returns (bytes32 radHash);

    function verifyRadonRequest(
            bytes32[] calldata retrieveHashes,
            string[][] calldata retrieveArgsValues,
            bytes32 aggregateReducerHash,
            bytes32 tallyReducerHash
        ) external returns (bytes32 radHash);

    /// Verifies and registers the specified Radon Retrieval (i.e. public data source) into this registry contract. 
    /// Returns a unique retrieval hash that identifies the verified Radon Retrieval.
    /// All parameters but the retrieval method are parameterizable by using embedded wildcard \x\ substrings (with x='0'..'9').
    /// Reverts if:
    /// - unsupported retrieval method is given;
    /// - no URL is provided Http/* requests;
    /// - non-empty strings given on RNG reqs.
    function verifyRadonRetrieval(
            Witnet.RadonRetrievalMethods requestMethod,
            string calldata requestURL,
            string calldata requestBody,
            string[2][] calldata requestHeaders,
            bytes calldata requestRadonScript
        ) external returns (bytes32 hash);

    /// Verifies a new Radon Retrieval by specifying the value to the highest indexed parameter of an already existing one.
    /// Returns the unique hash that identifies the resulting Radon Retrieval.
    /// Reverts if an unverified retrieval hash is passed.
    function verifyRadonRetrieval(
            bytes32 retrieveHash,
            string calldata lastArgValue
        ) external returns (bytes32 hash);
}

File 21 of 47 : IWitOracleLegacy.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

interface IWitOracleLegacy {

    struct RadonSLA {
        uint8  witCommitteeCapacity;
        uint64 witCommitteeUnitaryReward;
    }

    event WitnetQuery(uint256 id, uint256 evmReward, RadonSLA witnetSLA);

    /// @notice Estimate the minimum reward required for posting a data request.
    /// @dev Underestimates if the size of returned data is greater than `resultMaxSize`. 
    /// @param gasPrice Expected gas price to pay upon posting the data request.
    /// @param resultMaxSize Maximum expected size of returned data (in bytes).  
    function estimateBaseFee(uint256 gasPrice, uint16 resultMaxSize) external view returns (uint256);
    
    /// @notice Estimate the minimum reward required for posting a data request.
    /// @dev Fails if the RAD hash was not previously verified on the WitOracleRadonRegistry registry.
    /// @param gasPrice Expected gas price to pay upon posting the data request.
    /// @param radHash The RAD hash of the data request to be solved by Witnet.
    function estimateBaseFee(uint256 gasPrice, bytes32 radHash) external view returns (uint256);

    /// @notice Returns query's result current status from a requester's point of view:
    /// @notice   - 0 => Void: the query is either non-existent or deleted;
    /// @notice   - 1 => Awaiting: the query has not yet been reported;
    /// @notice   - 2 => Ready: the query response was finalized, and contains a result with no erros.
    /// @notice   - 3 => Error: the query response was finalized, and contains a result with errors.
    /// @notice   - 4 => Finalizing: some result to the query has been reported, but cannot yet be considered finalized.
    /// @notice   - 5 => Delivered: at least one response, either successful or with errors, was delivered to the requesting contract.
    function getQueryResponseStatus(uint256) external view returns (QueryResponseStatus);

        /// QueryResponse status from a requester's point of view.
        enum QueryResponseStatus {
            Void,
            Awaiting,
            Ready,
            Error,
            Finalizing,
            Delivered,
            Expired
        }

    /// @notice Retrieves the CBOR-encoded buffer containing the Witnet-provided result to the given query.
    function getQueryResultCborBytes(uint256) external view returns (bytes memory);

    /// @notice Gets error code identifying some possible failure on the resolution of the given query.
    function getQueryResultError(uint256) external view returns (ResultError memory);

        /// Data struct describing an error when trying to fetch a Witnet-provided result to a Data Request.
        struct ResultError {
            uint8 code;
            string reason;
        }

    function fetchQueryResponse(uint256 queryId) external returns (bytes memory);
    function postRequest(bytes32, RadonSLA calldata) external payable returns (uint256);
    function postRequestWithCallback(bytes32, RadonSLA calldata, uint24) external payable returns (uint256);
    function postRequestWithCallback(bytes calldata, RadonSLA calldata, uint24) external payable returns (uint256);
}

File 22 of 47 : IWitOracleEvents.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitOracleEvents {

    event WitOracleCommittee(
        address indexed evmSubscriber,
        Witnet.QueryCapability indexed witCapability,
        Witnet.QueryCapabilityMember[] witCapabilityMembers
    );
    
    /// Emitted every time a new query containing some verified data request is posted to the WitOracle.
    event WitOracleQuery(
        address requester,
        uint256 evmGasPrice,
        uint256 evmReward,
        uint256 queryId, 
        bytes32 queryRadHash,
        Witnet.QuerySLA querySLA
    );

    /// Emitted every time a new query containing some unverified data request bytecode is posted to the WRB.
    event WitOracleQuery(
        address requester,
        uint256 evmGasPrice,
        uint256 evmReward,
        uint256 queryId,
        bytes   queryBytecode,
        Witnet.QuerySLA querySLA
    );

    event WitOracleQueryResponseDispute(
        uint256 queryId,
        address evmResponseDisputer
    );

    /// Emitted when the reward of some not-yet reported query gets upgraded.
    event WitOracleQueryUpgrade(
        uint256 queryId,
        address evmSender,
        uint256 evmGasPrice,
        uint256 evmReward
    );

    /// Emitted when a query with no callback gets reported into the WRB.
    event WitOracleQueryResponse(
        uint256 queryId, 
        uint256 evmGasPrice
    );

    /// Emitted when a query with a callback gets successfully reported into the WRB.
    event WitOracleQueryReponseDelivered(
        uint256 queryId, 
        uint256 evmGasPrice, 
        uint256 evmCallbackGas
    );

    /// Emitted when a query with a callback cannot get reported into the WRB.
    event WitOracleQueryResponseDeliveryFailed(
        uint256 queryId, 
        uint256 evmGasPrice, 
        uint256 evmCallbackActualGas, 
        string  evmCallbackRevertReason,
        bytes   resultCborBytes
    );
}

File 23 of 47 : IWitOracleConsumer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../libs/Witnet.sol";

interface IWitOracleConsumer {

    /// @notice Method to be called from the WitOracle contract as soon as the given Witnet `queryId`
    /// @notice gets reported, if reported with no errors.
    /// @dev It should revert if called from any other address different to the WitOracle being used
    /// @dev by the WitOracleConsumer contract. 
    /// @param queryId The unique identifier of the Witnet query being reported.
    /// @param queryResult Struct contaning a Witnet.DataResult metadata and value.
    function reportWitOracleQueryResult(
            Witnet.QueryId queryId, 
            Witnet.DataResult memory queryResult
        ) external;

    /// @notice Determines if Witnet queries can be reported from given address.
    /// @dev In practice, must only be true on the WitOracle address that's being used by
    /// @dev the WitOracleConsumer to post queries. 
    function reportableFrom(address) external view returns (bool);
}

File 24 of 47 : IWitOracleAppliance.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../WitOracle.sol";
import "./IWitAppliance.sol";

abstract contract IWitOracleAppliance
    is
        IWitAppliance
{
    /// @notice Returns the WitOracle address that this appliance is bound to.
    function witOracle() virtual external view returns (WitOracle);
}

File 25 of 47 : IWitOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IWitOracleConsumer.sol";

import "../WitOracleRadonRegistry.sol";

interface IWitOracle {

    /// @notice Uniquely identifies the WitOracle addrees and the chain on which it's deployed.
    function channel() external view returns (bytes4);

    /// @notice Removes all query data from storage. Pays back reward on expired queries.
    /// @dev Fails if the query is not in a final status, or not called from the actual requester.
    /// @param queryId The unique query identifier.
    function deleteQuery(Witnet.QueryId queryId) external returns (Witnet.QueryReward);

    /// @notice Estimate the minimum reward required for posting a data request.
    /// @param evmGasPrice Expected gas price to pay upon posting the data request.
    function estimateBaseFee(uint256 evmGasPrice) external view returns (uint256);
    
    /// @notice Estimate the minimum reward required for posting a data request with a callback.
    /// @param evmGasPrice Expected gas price to pay upon posting the data request.
    /// @param callbackGas Maximum gas to be spent when reporting the data request result.
    function estimateBaseFeeWithCallback(uint256 evmGasPrice, uint24 callbackGas) external view returns (uint256);

    /// @notice Estimate the extra reward (i.e. over the base fee) to be paid when posting a new
    /// @notice data query in order to avoid getting provable "too low incentives" results from
    /// @notice the Wit/oracle blockchain. 
    /// @dev The extra fee gets calculated in proportion to:
    /// @param evmGasPrice Tentative EVM gas price at the moment the query result is ready.
    /// @param evmWitPrice  Tentative nanoWit price in Wei at the moment the query is solved on the Wit/oracle blockchain.
    /// @param querySLA The query SLA data security parameters as required for the Wit/oracle blockchain. 
    function estimateExtraFee(uint256 evmGasPrice, uint256 evmWitPrice, Witnet.QuerySLA calldata querySLA) external view returns (uint256);

    /// @notice Returns next query id to be generated by the Witnet Request Board.
    function getNextQueryId() external view returns (Witnet.QueryId);

    /// @notice Gets the whole Query data contents, if any, no matter its current status.
    function getQuery(Witnet.QueryId queryId) external view returns (Witnet.Query memory);

    /// @notice Gets the current EVM reward the report can claim, if not done yet.
    function getQueryEvmReward(Witnet.QueryId) external view returns (Witnet.QueryReward);

    /// @notice Retrieves the RAD hash and SLA parameters of the given query.
    function getQueryRequest(Witnet.QueryId) external view returns (Witnet.QueryRequest memory);

    /// @notice Retrieves the whole `Witnet.QueryResponse` record referred to a previously posted Witnet Data Request.
    function getQueryResponse(Witnet.QueryId) external view returns (Witnet.QueryResponse memory);

    function getQueryResult(Witnet.QueryId) external view returns (Witnet.DataResult memory);
    function getQueryResultStatus(Witnet.QueryId) external view returns (Witnet.ResultStatus);
    function getQueryResultStatusDescription(Witnet.QueryId) external view returns (string memory);

    /// @notice Gets current status of given query.
    function getQueryStatus(Witnet.QueryId) external view returns (Witnet.QueryStatus);
    function getQueryStatusString(Witnet.QueryId) external view returns (string memory);
    
    /// @notice Get current status of all given query ids.
    function getQueryStatusBatch(Witnet.QueryId[] calldata) external view returns (Witnet.QueryStatus[] memory);

    /// @notice Request real world data from the Wit/oracle sidechain. 
    /// @notice The paid fee is escrowed as a reward for the reporter that eventually relays back 
    /// @notice a valid query result from the Wit/oracle sidechain.
    /// @notice Query results are CBOR-encoded, and can contain either some data, or an error.
    /// @dev Reasons to revert:
    /// @dev - the data request's RAD hash was not previously verified into the WitOracleRadonRegistry contract;
    /// @dev - invalid query SLA parameters were provided;
    /// @dev - insufficient value is paid as reward.
    /// @param drRadHash The RAD hash of the data request to be solved by Wit/oracle sidechain. 
    function postQuery(bytes32 drRadHash, Witnet.QuerySLA calldata)
        external payable returns (Witnet.QueryId);

    /// @notice Request real world data from the Wit/oracle sidechain. 
    /// @notice The paid fee is escrowed as a reward for the reporter that eventually relays back 
    /// @notice a valid query result from the Wit/oracle sidechain.
    /// @notice The Witnet-provable result will be reported directly to the requesting contract. 
    /// @notice Query results are CBOR-encoded, and can contain either some data, or an error.
    /// @dev Reasons to revert:
    /// @dev - the data request's RAD hash was not previously verified into the Radon Registry;
    /// @dev - invalid query SLA parameters were provided;
    /// @dev - insufficient value is paid as reward.
    /// @dev - passed `consumer` is not a contract implementing the IWitOracleConsumer interface;
    /// @param drRadHash The RAD hash of the data request to be solved by Wit/oracle sidechain.
    function postQuery(bytes32 drRadHash, Witnet.QuerySLA calldata, Witnet.QueryCallback calldata)
        external payable returns (Witnet.QueryId);

    /// @notice Request real world data from the Wit/oracle sidechain. 
    /// @notice The paid fee is escrowed as a reward for the reporter that eventually relays back 
    /// @notice a valid query result from the Wit/oracle sidechain.
    /// @notice The Witnet-provable result will be reported directly to the requesting contract. 
    /// @notice Query results are CBOR-encoded, and can contain either some data, or an error.
    /// @dev Reasons to revert:
    /// @dev - the data request's RAD hash was not previously verified into the Radon Registry;
    /// @dev - invalid query SLA parameters were provided;
    /// @dev - insufficient value is paid as reward.
    /// @dev - passed `consumer` is not a contract implementing the IWitOracleConsumer interface;
    /// @param drBytecode Encoded witnet-compliant script describing how and where to retrieve data from.
    function postQuery(bytes calldata drBytecode, Witnet.QuerySLA calldata, Witnet.QueryCallback calldata)
        external payable returns (Witnet.QueryId);

    /// @notice Returns the singleton WitOracleRadonRegistry in which all Witnet-compliant data requests 
    /// @notice and templates must be previously verified so they can be passed as reference when 
    /// @notice calling postRequest(bytes32,..) methods.
    function registry() external view returns (WitOracleRadonRegistry);

    /// @notice Enables data requesters to settle the actual validators in the Wit/oracle
    /// @notice sidechain that will be entitled to solve data requests requiring to
    /// @notice support the specified `Wit2.Capability`.
    function settleMyOwnCapableCommittee(Witnet.QueryCapability, Witnet.QueryCapabilityMember[] calldata) external;

    /// @notice Increments the reward of a previously posted request by adding the transaction value to it.
    function upgradeQueryEvmReward(Witnet.QueryId) external payable;
}

File 26 of 47 : IWitFeedsLegacy.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./IWitOracleLegacy.sol";
import "../libs/Witnet.sol";

interface IWitFeedsLegacy {   
    struct RadonSLA {
        uint8 witCommitteeCapacity;
        uint64 witCommitteeUnitaryReward;
    }
    function estimateUpdateBaseFee(uint256 evmGasPrice) external view returns (uint);
    function latestUpdateResponse(bytes4 feedId) external view returns (Witnet.QueryResponse memory);
    function latestUpdateResponseStatus(bytes4 feedId) external view returns (IWitOracleLegacy.QueryResponseStatus);
    function latestUpdateResultError(bytes4 feedId) external view returns (IWitOracleLegacy.ResultError memory);
    function lookupWitnetBytecode(bytes4) external view returns (bytes memory);
    function requestUpdate(bytes4, RadonSLA calldata) external payable returns (uint256 usedFunds);
    function witnet() external view returns (address);
}

File 27 of 47 : IWitFeedsEvents.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

interface IWitFeedsEvents {
    
    /// A fresh update on the data feed identified as `erc2364Id4` has just been 
    /// requested and paid for by some `evmSender`, under command of the 
    /// `evmOrigin` externally owned account. 
    event PullingUpdate(
        address evmOrigin,
        address evmSender,
        bytes4  erc2362Id4,
        Witnet.QueryId witOracleQueryId
    );
}

File 28 of 47 : IWitFeedsAdmin.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../libs/Witnet.sol";

import "../WitOracleRequest.sol";
import "../WitOracleRequestTemplate.sol";

interface IWitFeedsAdmin {

    event WitFeedDeleted(string caption, bytes4 feedId);
    event WitFeedSettled(string caption, bytes4 feedId, bytes32 radHash);
    event WitFeedSolverSettled(string caption, bytes4 feedId, address solver);

    function acceptOwnership() external;
    function baseFeeOverheadPercentage() external view returns (uint16);
    function deleteFeed(string calldata caption) external;
    function deleteFeeds() external;
    function owner() external view returns (address);
    function pendingOwner() external returns (address);
    function settleBaseFeeOverheadPercentage(uint16) external;
    function settleDefaultRadonSLA(Witnet.QuerySLA calldata) external;
    function settleFeedRequest(string calldata caption, bytes32 radHash) external;
    function settleFeedRequest(string calldata caption, WitOracleRequest request) external;
    function settleFeedRequest(string calldata caption, WitOracleRequestTemplate template, string[][] calldata) external;
    function settleFeedSolver (string calldata caption, address solver, string[] calldata deps) external;
    function transferOwnership(address) external;
}

File 29 of 47 : IWitFeeds.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../WitOracle.sol";
import "../WitOracleRadonRegistry.sol";

interface IWitFeeds {   

    /// Primitive data type produced by successful data updates of all supported
    /// feeds (e.g. Witnet.RadonDataTypes.Integer in WitPriceFeeds).
    function dataType() external view returns (Witnet.RadonDataTypes);

    /// ERC-2362 caption prefix shared by all supported feeds (e.g. "Price-" in WitPriceFeeds).
    function prefix() external view returns (string memory);
    
    /// Default SLA data security parameters that will be fulfilled on Witnet upon 
    /// every feed update, if no others are specified by the requester.
    function defaultRadonSLA() external view returns (Witnet.QuerySLA memory);

    /// Estimates the minimum EVM fee required to be paid upon requesting a data 
    /// update with the given the _evmGasPrice value.
    function estimateUpdateRequestFee(uint256 evmGasPrice) external view returns (uint);

    /// Returns a unique hash determined by the combination of data sources being used by 
    /// supported non-routed price feeds, and dependencies of all supported routed 
    /// price feeds. The footprint changes if any price feed is modified, added, removed 
    /// or if the dependency tree of any routed price feed is altered.
    function footprint() external view returns (bytes4);

    /// This pure function determines the ERC-2362 identifier of the given data feed 
    /// caption string, truncated to bytes4.
    function hash(string calldata caption) external pure returns (bytes4);

    /// Returns the query id (in the context of the WitOracle addressed by witOracle()) 
    /// that solved the most recently updated value for the given feed.
    function lastValidQueryId(bytes4 feedId) external view returns (Witnet.QueryId);

    /// Returns the actual response from the Witnet oracle blockchain to the last 
    /// successful update for the given data feed.
    function lastValidQueryResponse(bytes4 feedId) external view returns (Witnet.QueryResponse memory);

    /// Returns the Witnet query id of the latest update attempt for the given data feed.
    function latestUpdateQueryId(bytes4 feedId) external view returns (Witnet.QueryId);

    /// Returns the actual request queried to the the Witnet oracle blockchain on the latest 
    /// update attempt for the given data feed.
    function latestUpdateQueryRequest(bytes4 feedId) external view returns (Witnet.QueryRequest memory);

    /// Returns the response from the Witnet oracle blockchain to the latest update attempt 
    /// for the given data feed.
    function latestUpdateQueryResult(bytes4 feedId) external view returns (Witnet.DataResult memory);

    /// Tells the current response status of the latest update attempt for the given data feed.
    function latestUpdateQueryResultStatus(bytes4 feedId) external view returns (Witnet.ResultStatus);

    /// Describes the error returned from the Witnet oracle blockchain in response to the latest 
    /// update attempt for the given data feed, if any.
    function latestUpdateQueryResultStatusDescription(bytes4 feedId) external view returns (string memory);
    
    /// Returns the ERC-2362 caption of the given feed identifier, if known. 
    function lookupCaption(bytes4) external view returns (string memory);

    /// Returns the Witnet-compliant bytecode of the data retrieving script to be solved by 
    /// the Witnet oracle blockchain upon every update of the given data feed.
    function lookupWitOracleRequestBytecode(bytes4 feedId) external view returns (bytes memory);

    /// Returns the RAD hash that uniquely identifies the data retrieving script that gets solved 
    /// by the Witnet oracle blockchain upon every update of the given data feed.
    function lookupWitOracleRequestRadHash(bytes4 feedId) external view returns (bytes32);

    /// Returns the list of actual data sources and offchain computations for the given data feed.
    function lookupWitOracleRadonRetrievals(bytes4 feedId) external view returns (Witnet.RadonRetrieval[] memory);

    /// Triggers a fresh update on the Witnet oracle blockchain for the given data feed, 
    /// using the defaultRadonSLA() security parameters.
    function requestUpdate(bytes4 feedId) external payable returns (uint256 usedFunds);

    /// Triggers a fresh update for the given data feed, requiring also the SLA data security parameters
    /// that will have to be fulfilled on Witnet. 
    function requestUpdate(bytes4 feedId, Witnet.QuerySLA calldata updateSLA) external payable returns (uint256 usedFunds);

    /// Returns the list of feed ERC-2362 ids, captions and RAD hashes of all currently supported 
    /// data feeds. The RAD hash of a data feed determines in a verifiable way the actual data sources 
    /// and off-chain computations solved by the Witnet oracle blockchain upon every data update. 
    /// The RAD hash value for a routed feed actually contains the address of the IWitnetPriceSolver 
    /// logic contract that solves it.
    function supportedFeeds() external view returns (bytes4[] memory, string[] memory, bytes32[] memory);

    /// Tells whether the given ERC-2362 feed caption is currently supported.
    function supportsCaption(string calldata) external view returns (bool);

    /// Total number of data feeds, routed or not, that are currently supported.
    function totalFeeds() external view returns (uint256);
}

File 30 of 47 : IWitAppliance.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

abstract contract IWitAppliance {

    /// @notice Returns the name of the actual contract implementing the logic of this Witnet appliance.
    function class() virtual public view returns (string memory);

    /// @notice Returns the ERC-165 id of the minimal functionality expected for this appliance.
    function specs() virtual external view returns (bytes4);

    function _require(bool _condition, string memory _message) virtual internal view {
        if (!_condition) {
            _revert(_message);
        }
    }

    function _revert(string memory _message) virtual internal view {
        revert(
            string(abi.encodePacked(
                class(),
                ": ",
                _message
            ))
        );
    }

}

File 31 of 47 : WitPriceFeedsDataLib.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "../interfaces/IWitFeedsAdmin.sol";
import "../interfaces/IWitPriceFeedsSolver.sol";

import "../libs/Slices.sol";
import "../libs/Witnet.sol";

/// @title WitFeeds data model.
/// @author The Witnet Foundation.
library WitPriceFeedsDataLib {

    using Slices for string;
    using Slices for Slices.Slice;

    using Witnet for Witnet.DataResult;
    using Witnet for Witnet.QueryId;
    using Witnet for Witnet.ResultStatus;
    
    bytes32 private constant _WIT_FEEDS_DATA_SLOTHASH =
        /* keccak256("io.witnet.feeds.data") */
        0xe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff;

    struct Storage {
        bytes32 reserved;
        bytes4[] ids;
        mapping (bytes4 => Record) records;
    }

    struct Record {
        string  caption;
        uint8   decimals;
        uint256 index;
        Witnet.QueryId lastValidQueryId;
        Witnet.QueryId latestUpdateQueryId;
        bytes32 radHash;
        address solver;         // logic contract address for reducing values on routed feeds.
        int256  solverReductor; // as to reduce resulting number of decimals on routed feeds.
        bytes32 solverDepsFlag; // as to store ids of up to 8 depending feeds.
    }

    
    // ================================================================================================
    // --- Internal functions -------------------------------------------------------------------------
    
    /// @notice Returns array of feed ids from which given feed's value depends.
    /// @dev Returns empty array on either unsupported or not-routed feeds.
    /// @dev The maximum number of dependencies is hard-limited to 8, as to limit number
    /// @dev of SSTORE operations (`__storage().records[feedId].solverDepsFlag`), 
    /// @dev no matter the actual number of depending feeds involved.
    function depsOf(bytes4 feedId) public view returns (bytes4[] memory _deps) {
        bytes32 _solverDepsFlag = data().records[feedId].solverDepsFlag;
        _deps = new bytes4[](8);
        uint _len;
        for (_len = 0; _len < 8; _len ++) {
            _deps[_len] = bytes4(_solverDepsFlag);
            if (_deps[_len] == 0) {
                break;
            } else {
                _solverDepsFlag <<= 32;
            }
        }
        assembly {
            // reset length to actual number of dependencies:
            mstore(_deps, _len)
        }
    }

    /// @notice Returns storage pointer to where Storage data is located. 
    function data()
      internal pure
      returns (Storage storage _ptr)
    {
        assembly {
            _ptr.slot := _WIT_FEEDS_DATA_SLOTHASH
        }
    }

    function hash(string memory caption) internal pure returns (bytes4) {
        return bytes4(keccak256(bytes(caption)));
    }

    function lastValidQueryId(WitOracle witOracle, bytes4 feedId)
        internal view 
        returns (Witnet.QueryId _queryId)
    {
        _queryId = seekRecord(feedId).latestUpdateQueryId;
        if (
            _queryId.isZero()
                || witOracle.getQueryResultStatus(_queryId) != Witnet.ResultStatus.NoErrors
        ) {
            _queryId = seekRecord(feedId).lastValidQueryId;
        }
    }

    function latestUpdateQueryResultStatus(WitOracle witOracle, bytes4 feedId)
        internal view
        returns (Witnet.ResultStatus)
    {
        Witnet.QueryId _queryId = seekRecord(feedId).latestUpdateQueryId;
        if (!_queryId.isZero()) {
            return witOracle.getQueryResultStatus(_queryId);
        } else {
            return Witnet.ResultStatus.NoErrors;
        }
    }

    /// @notice Returns storage pointer to where Record for given feedId is located.
    function seekRecord(bytes4 feedId) internal view returns (Record storage) {
        return data().records[feedId];
    }

    function seekPriceSolver(bytes4 feedId) internal view returns (
            IWitPriceFeedsSolver _solverAddress,
            string[] memory _solverDeps
        )
    {
        _solverAddress = IWitPriceFeedsSolver(seekRecord(feedId).solver);
        bytes4[] memory _deps = depsOf(feedId);
        _solverDeps = new string[](_deps.length);
        for (uint _ix = 0; _ix < _deps.length; _ix ++) {
            _solverDeps[_ix] = seekRecord(_deps[_ix]).caption;
        }
    }


    // ================================================================================================
    // --- Public functions ---------------------------------------------------------------------------

    function deleteFeed(string calldata caption) public {
        bytes4 feedId = hash(caption);
        bytes4[] storage __ids = data().ids;
        Record storage __record = seekRecord(feedId);
        uint _index = __record.index;
        require(_index != 0, "unknown feed");
        bytes4 _lastFeedId = __ids[__ids.length - 1];
        __ids[_index - 1] = _lastFeedId;
        __ids.pop();
        seekRecord(_lastFeedId).index = _index;
        delete data().records[feedId];
        emit IWitFeedsAdmin.WitFeedDeleted(caption, feedId);
    }

    function deleteFeeds() public {
        bytes4[] storage __ids = data().ids;
        for (uint _ix = __ids.length; _ix > 0; _ix --) {
            bytes4 _feedId = __ids[_ix - 1];
            string memory _caption = data().records[_feedId].caption;
            delete data().records[_feedId]; __ids.pop();
            emit IWitFeedsAdmin.WitFeedDeleted(_caption, _feedId);
        }
    }

    function latestPrice(
            WitOracle witOracle,
            bytes4 feedId
        ) 
        public view 
        returns (IWitPriceFeedsSolver.Price memory)
    {
        Witnet.QueryId _queryId = lastValidQueryId(witOracle, feedId);
        if (!_queryId.isZero()) {
            Witnet.DataResult memory _lastValidResult = witOracle.getQueryResult(_queryId);
            return IWitPriceFeedsSolver.Price({
                value: _lastValidResult.fetchUint(),
                timestamp: _lastValidResult.timestamp,
                drTxHash: _lastValidResult.drTxHash,
                latestStatus: _intoLatestUpdateStatus(latestUpdateQueryResultStatus(witOracle, feedId))
            });
        
        } else {
            address _solver = seekRecord(feedId).solver;
            if (_solver != address(0)) {
                // solhint-disable-next-line avoid-low-level-calls
                (bool _success, bytes memory _result) = address(this).staticcall(abi.encodeWithSelector(
                    IWitPriceFeedsSolver.solve.selector,
                    feedId
                ));
                if (!_success) {
                    assembly {
                        _result := add(_result, 4)
                    }
                    revert(string(abi.decode(_result, (string))));
                } else {
                    return abi.decode(_result, (IWitPriceFeedsSolver.Price));
                }
            } else {
                return IWitPriceFeedsSolver.Price({
                    value: 0,
                    timestamp: Witnet.ResultTimestamp.wrap(0),
                    drTxHash: Witnet.TransactionHash.wrap(0),
                    latestStatus: _intoLatestUpdateStatus(latestUpdateQueryResultStatus(witOracle, feedId))
                });
            }
        }
    }

    function requestUpdate(
            WitOracle witOracle, 
            bytes4 feedId, 
            Witnet.QuerySLA memory querySLA,
            uint256 evmUpdateRequestFee
        )
        public
        returns (
            Witnet.QueryId _latestQueryId,
            uint256 _evmUsedFunds
        )
    {
        Record storage __feed = seekRecord(feedId);
        _latestQueryId = __feed.latestUpdateQueryId;
        
        Witnet.ResultStatus _latestStatus = latestUpdateQueryResultStatus(witOracle, feedId);   
        if (_latestStatus.keepWaiting()) {
            uint72 _evmUpdateRequestCurrentFee = Witnet.QueryReward.unwrap(
                witOracle.getQueryEvmReward(_latestQueryId)
            );
            if (evmUpdateRequestFee > _evmUpdateRequestCurrentFee) {
                // latest update is still pending, so just increase the reward
                // accordingly to current tx gasprice:
                _evmUsedFunds = (evmUpdateRequestFee - _evmUpdateRequestCurrentFee);
                witOracle.upgradeQueryEvmReward{
                    value: _evmUsedFunds
                }(
                    _latestQueryId
                );
            
            } else {
                _evmUsedFunds = 0;
            }
        
        } else {
            // Check if latest update ended successfully:
            if (_latestStatus == Witnet.ResultStatus.NoErrors) {
                // If so, remove previous last valid query from the WRB:
                if (!__feed.lastValidQueryId.isZero()) {
                    evmUpdateRequestFee += Witnet.QueryReward.unwrap(
                        witOracle.deleteQuery(__feed.lastValidQueryId)
                    );
                }
                __feed.lastValidQueryId = _latestQueryId;
            } else {
                // Otherwise, try to delete latest query, as it was faulty
                // and we are about to post a new update request:
                try witOracle.deleteQuery(_latestQueryId) returns (Witnet.QueryReward _unsedReward) {
                    evmUpdateRequestFee += Witnet.QueryReward.unwrap(_unsedReward);
                
                } catch {}
            }
            // Post update request to the WRB:
            _evmUsedFunds = evmUpdateRequestFee;
            _latestQueryId = witOracle.postQuery{
                value: _evmUsedFunds
            }(
                __feed.radHash,
                querySLA
            );
            // Update latest query id:
            __feed.latestUpdateQueryId = _latestQueryId;
        }
    }

    function settleFeedRequest(
            string calldata caption,
            bytes32 radHash
        )
        public
    {
        bytes4 feedId = hash(caption);
        Record storage __record = seekRecord(feedId);
        if (__record.index == 0) {
            // settle new feed:
            __record.caption = caption;
            __record.decimals = validateCaption(caption);
            __record.index = data().ids.length + 1;
            __record.radHash = radHash;
            data().ids.push(feedId);
        } else if (__record.radHash != radHash) {
            // update radHash on existing feed:
            __record.radHash = radHash;
            __record.solver = address(0);
        }
        emit IWitFeedsAdmin.WitFeedSettled(caption, feedId, radHash);
    }

    function settleFeedSolver(
            string calldata caption, 
            address solver, 
            string[] calldata deps
        )
        public
    {
        bytes4 feedId = hash(caption);        
        Record storage __record = seekRecord(feedId);
        if (__record.index == 0) {
            // settle new feed:
            __record.caption = caption;
            __record.decimals = validateCaption(caption);
            __record.index = data().ids.length + 1;
            __record.solver = solver;
            data().ids.push(feedId);
            
        } else if (__record.solver != solver) {
            // update radHash on existing feed:
            __record.radHash = 0;
            __record.solver = solver;
        }
        // validate solver first-level dependencies
        {
            // solhint-disable-next-line avoid-low-level-calls
            (bool _success, bytes memory _reason) = solver.delegatecall(abi.encodeWithSelector(
                IWitPriceFeedsSolver.validate.selector,
                feedId,
                deps
            ));
            if (!_success) {
                assembly {
                    _reason := add(_reason, 4)
                }
                revert(string(abi.encodePacked(
                    "solver validation failed: ",
                    string(abi.decode(_reason,(string)))
                )));
            }
        }
        // smoke-test the solver 
        {   
            // solhint-disable-next-line avoid-low-level-calls
            (bool _success, bytes memory _reason) = address(this).staticcall(abi.encodeWithSelector(
                IWitPriceFeedsSolver.solve.selector,
                feedId
            ));
            if (!_success) {
                assembly {
                    _reason := add(_reason, 4)
                }
                revert(string(abi.encodePacked(
                    "smoke-test failed: ",
                    string(abi.decode(_reason,(string)))
                )));
            }
        }
        emit IWitFeedsAdmin.WitFeedSolverSettled(caption, feedId, solver);
    }

    function supportedFeeds() public view returns (
            bytes4[] memory _ids,
            string[] memory _captions,
            bytes32[] memory _solvers
        )
    {
        _ids = data().ids;
        _captions = new string[](_ids.length);
        _solvers = new bytes32[](_ids.length);
        for (uint _ix = 0; _ix < _ids.length; _ix ++) {
            Record storage __record = seekRecord(_ids[_ix]);
            _captions[_ix] = __record.caption;
            _solvers[_ix] = (
                address(__record.solver) == address(0) 
                    ? __record.radHash 
                    : bytes32(bytes20(__record.solver))
            );
        }
    }

    // --- IWitPriceFeedsSolver public functions -------------------------------------------------------------

    function deployPriceSolver(
            bytes calldata initcode,
            bytes calldata constructorParams
        )
        external
        returns (address _solver)
    {
        _solver = determinePriceSolverAddress(initcode, constructorParams);
        if (_solver.code.length == 0) {
            bytes memory _bytecode = _completeInitCode(initcode, constructorParams);
            address _createdContract;
            assembly {
                _createdContract := create2(
                    0, 
                    add(_bytecode, 0x20),
                    mload(_bytecode), 
                    0
                )
            }
            // assert(_solver == _createdContract); // fails on TEN chains
            _solver = _createdContract;
            require(
                IWitPriceFeedsSolver(_solver).specs() == type(IWitPriceFeedsSolver).interfaceId,
                "uncompliant solver implementation"
            );
        }
    }

    function determinePriceSolverAddress(
            bytes calldata initcode,
            bytes calldata constructorParams
        )
        public view
        returns (address)
    {
        return address(
            uint160(uint(keccak256(
                abi.encodePacked(
                    bytes1(0xff),
                    address(this),
                    bytes32(0),
                    keccak256(_completeInitCode(initcode, constructorParams))
                )
            )))
        );
    }

    function validateCaption(string calldata caption) public pure returns (uint8) {
        Slices.Slice memory _caption = caption.toSlice();
        Slices.Slice memory _delim = string("-").toSlice();
        string[] memory _parts = new string[](_caption.count(_delim) + 1);
        for (uint _ix = 0; _ix < _parts.length; _ix ++) {
            _parts[_ix] = _caption.split(_delim).toString();
        }
        (uint _decimals, bool _success) = Witnet.tryUint(_parts[_parts.length - 1]);
        require(_success, "bad decimals");
        return uint8(_decimals);
    }

    
    // ================================================================================================
    // --- Private functions --------------------------------------------------------------------------

    function _completeInitCode(bytes calldata initcode, bytes calldata constructorParams)
        private pure
        returns (bytes memory)
    {
        return abi.encodePacked(
            initcode,
            constructorParams
        );
    }

    function _intoLatestUpdateStatus(Witnet.ResultStatus _resultStatus)
        private pure 
        returns (IWitPriceFeedsSolver.LatestUpdateStatus)
    {
        return (_resultStatus.keepWaiting() 
            ? IWitPriceFeedsSolver.LatestUpdateStatus.Awaiting
            : (_resultStatus.hasErrors()
                ? IWitPriceFeedsSolver.LatestUpdateStatus.Error
                : IWitPriceFeedsSolver.LatestUpdateStatus.Ready
            )
        );
    }

}

File 32 of 47 : WitnetUpgradableBase.sol
// SPDX-License-Identifier: MIT
// solhint-disable var-name-mixedcase
// solhint-disable payable-fallback

pragma solidity >=0.8.0 <0.9.0;

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

import "./WitnetProxy.sol";

/// @title Witnet Request Board base contract, with an Upgradeable (and Destructible) touch.
/// @author Guillermo Díaz <[email protected]>
abstract contract WitnetUpgradableBase
    is
        Ownable2Step,
        Upgradeable, 
        ReentrancyGuard
{
    bytes32 internal immutable _WITNET_UPGRADABLE_VERSION;

    address public immutable deployer = msg.sender;

    constructor(
            bool _upgradable,
            bytes32 _versionTag,
            string memory _proxiableUUID
        )
        Upgradeable(_upgradable)
    {
        _WITNET_UPGRADABLE_VERSION = _versionTag;
        proxiableUUID = keccak256(bytes(_proxiableUUID));
    }
    
    /// @dev Reverts if proxy delegatecalls to unexistent method.
    /* solhint-disable no-complex-fallback */
    fallback() virtual external { 
        revert(string(abi.encodePacked(
            "WitnetUpgradableBase: not implemented: 0x",
            _toHexString(uint8(bytes1(msg.sig))),
            _toHexString(uint8(bytes1(msg.sig << 8))),
            _toHexString(uint8(bytes1(msg.sig << 16))),
            _toHexString(uint8(bytes1(msg.sig << 24)))
        )));
    }
   
    
    // ================================================================================================================
    // --- Overrides 'Proxiable' --------------------------------------------------------------------------------------

    /// @dev Gets immutable "heritage blood line" (ie. genotype) as a Proxiable, and eventually Upgradeable, contract.
    ///      If implemented as an Upgradeable touch, upgrading this contract to another one with a different 
    ///      `proxiableUUID()` value should fail.
    bytes32 public immutable override proxiableUUID;


    // ================================================================================================================
    // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------

    /// @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 _initData) virtual override public {
        address _owner = owner();
        if (_owner == address(0)) {
            // upon first upgrade, extract decode owner address from _intidata
            (_owner, _initData) = abi.decode(_initData, (address, bytes));
            _transferOwnership(_owner);
        
        } else {
            // only owner can initialize an existing proxy:
            require(msg.sender == _owner, "not the owner");
        }
        __initializeUpgradableData(_initData);
        if (
            __proxiable().codehash != bytes32(0)
                && __proxiable().codehash == codehash()
        ) {
            revert("already initialized codehash");
        }
        __proxiable().codehash = codehash();
        emit Upgraded(owner(), base(), codehash(), version());
    }

    /// Tells whether provided address could eventually upgrade the contract.
    function isUpgradableFrom(address _from) external view virtual override returns (bool) {
        return (
            // false if the WRB is intrinsically not upgradable, or `_from` is no owner
            isUpgradable()
                && owner() == _from
        );
    }

    /// Retrieves human-readable version tag of current implementation.
    function version() public view virtual override returns (string memory) {
        return _toString(_WITNET_UPGRADABLE_VERSION);
    }


    // ================================================================================================================
    // --- Internal methods -------------------------------------------------------------------------------------------

    function _toHexString(uint8 _u)
        internal pure
        returns (string memory)
    {
        bytes memory b2 = new bytes(2);
        uint8 d0 = uint8(_u / 16) + 48;
        uint8 d1 = uint8(_u % 16) + 48;
        if (d0 > 57)
            d0 += 7;
        if (d1 > 57)
            d1 += 7;
        b2[0] = bytes1(d0);
        b2[1] = bytes1(d1);
        return string(b2);
    }

    /// Converts bytes32 into string.
    function _toString(bytes32 _bytes32)
        internal pure
        returns (string memory)
    {
        bytes memory _bytes = new bytes(_toStringLength(_bytes32));
        for (uint _i = 0; _i < _bytes.length;) {
            _bytes[_i] = _bytes32[_i];
            unchecked {
                _i ++;
            }
        }
        return string(_bytes);
    }

    // Calculate length of string-equivalent to given bytes32.
    function _toStringLength(bytes32 _bytes32)
        internal pure
        returns (uint _length)
    {
        for (; _length < 32; ) {
            if (_bytes32[_length] == 0) {
                break;
            }
            unchecked {
                _length ++;
            }
        }
    }
}

File 33 of 47 : 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 <[email protected]>
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
        }
    }

}

File 34 of 47 : WitPriceFeeds.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./WitFeeds.sol";
import "./interfaces/IWitPriceFeeds.sol";

/// @title WitPriceFeeds: Price Feeds live repository reliant on the Wit/oracle blockchain.
/// @author The Witnet Foundation.
abstract contract WitPriceFeeds
    is
        WitFeeds,
        IWitPriceFeeds
{
    constructor()
        WitFeeds(
            Witnet.RadonDataTypes.Integer,
            "Price-"
        ) 
    {}

    function specs() virtual override external pure returns (bytes4) {
        return (
            type(IWitOracleAppliance).interfaceId
                ^ type(IERC2362).interfaceId
                ^ type(IWitFeeds).interfaceId
                ^ type(IWitPriceFeeds).interfaceId
        );
    }
}

File 35 of 47 : WitOracleRequestTemplate.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./interfaces/IWitOracleAppliance.sol";
import "./interfaces/IWitOracleRadonRegistryEvents.sol";
import "./interfaces/IWitOracleRequestFactoryEvents.sol";
import "./interfaces/IWitOracleRequestTemplate.sol";

abstract contract WitOracleRequestTemplate
    is
        IWitOracleAppliance,
        IWitOracleRadonRegistryEvents,
        IWitOracleRequestFactoryEvents,
        IWitOracleRequestTemplate
{}

File 36 of 47 : WitOracleRequestFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./interfaces/IWitOracleAppliance.sol";
import "./interfaces/IWitOracleRadonRegistryEvents.sol";
import "./interfaces/IWitOracleRequestFactory.sol";
import "./interfaces/IWitOracleRequestFactoryEvents.sol";

abstract contract WitOracleRequestFactory
    is
        IWitOracleAppliance, 
        IWitOracleRadonRegistryEvents,
        IWitOracleRequestFactory,
        IWitOracleRequestFactoryEvents
{}

File 37 of 47 : WitOracleRequest.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./interfaces/IWitOracleAppliance.sol";
import "./interfaces/IWitOracleRequest.sol";

abstract contract WitOracleRequest
    is
        IWitOracleAppliance,
        IWitOracleRequest
{}

File 38 of 47 : WitOracleRadonRegistry.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./interfaces/IWitAppliance.sol";
import "./interfaces/IWitOracleRadonRegistry.sol";
import "./interfaces/IWitOracleRadonRegistryEvents.sol";

abstract contract WitOracleRadonRegistry
    is
        IWitAppliance,
        IWitOracleRadonRegistry,
        IWitOracleRadonRegistryEvents
{
    function specs() virtual override external pure returns (bytes4) {
        return (
            type(IWitAppliance).interfaceId
                ^ type(IWitOracleRadonRegistry).interfaceId
        );
    }
}

File 39 of 47 : WitOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./WitOracleRadonRegistry.sol";
import "./WitOracleRequestFactory.sol";

import "./interfaces/IWitAppliance.sol";
import "./interfaces/IWitOracle.sol";
import "./interfaces/IWitOracleEvents.sol";

/// @title Witnet Request Board functionality base contract.
/// @author The Witnet Foundation.
abstract contract WitOracle
    is
        IWitAppliance,
        IWitOracle,
        IWitOracleEvents
{
    function specs() virtual override external pure returns (bytes4) {
        return (
            type(IWitAppliance).interfaceId
                ^ type(IWitOracle).interfaceId
        );
    }
}

File 40 of 47 : WitFeeds.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "./interfaces/IWitFeeds.sol";
import "./interfaces/IWitFeedsEvents.sol";
import "./interfaces/IWitOracleAppliance.sol";

import "ado-contracts/contracts/interfaces/IERC2362.sol";

abstract contract WitFeeds
    is 
        IERC2362,
        IWitFeeds,
        IWitFeedsEvents,
        IWitOracleAppliance,
        IWitOracleEvents
{
    Witnet.RadonDataTypes immutable public override dataType;
    bytes32 immutable internal __prefix;

    constructor(
            Witnet.RadonDataTypes _dataType,
            string memory _prefix
        )
    {
        dataType = _dataType;
        __prefix = Witnet.toBytes32(bytes(_prefix));
    }

    function prefix() override public view returns (string memory) {
        return Witnet.toString(__prefix);
    }
}

File 41 of 47 : IERC2362.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.0 <0.9.0;

/**
* @dev EIP2362 Interface for pull oracles
* https://github.com/adoracles/EIPs/blob/erc-2362/EIPS/eip-2362.md
*/
interface IERC2362
{
	/**
	 * @dev Exposed function pertaining to EIP standards
	 * @param _id bytes32 ID of the query
	 * @return int,uint,uint returns the value, timestamp, and status code of query
	 */
	function valueFor(bytes32 _id) external view returns(int256,uint256,uint256);
}

File 42 of 47 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

File 43 of 47 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.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 ERC-165 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;
    }
}

File 44 of 47 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 45 of 47 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 46 of 47 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 47 of 47 : 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
        }
    }
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "libraries": {
    "/contracts/libs/WitPriceFeedsLib.sol": {
      "WitPriceFeedsLib": "0xA2d9384Cfd3529D1287Bc06e58897EBb8dfF2E94"
    },
    "/contracts/data/WitPriceFeedsDataLib.sol": {
      "WitPriceFeedsDataLib": "0xeDA862F66cd1708bb77D4ec2029Ce8aFbfFA11fc"
    }
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract ABI

API
[{"inputs":[{"internalType":"contract WitOracle","name":"_witOracle","type":"address"},{"internalType":"bytes32","name":"_versionTag","type":"bytes32"},{"internalType":"bool","name":"_upgradable","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"solver","type":"address"},{"indexed":false,"internalType":"bytes32","name":"codehash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"NewPriceFeedsSolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"evmOrigin","type":"address"},{"indexed":false,"internalType":"address","name":"evmSender","type":"address"},{"indexed":false,"internalType":"bytes4","name":"erc2362Id4","type":"bytes4"},{"indexed":false,"internalType":"Witnet.QueryId","name":"witOracleQueryId","type":"uint256"}],"name":"PullingUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"baseAddr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"baseCodehash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"versionTag","type":"string"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"WitFeedDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"bytes32","name":"radHash","type":"bytes32"}],"name":"WitFeedSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"address","name":"solver","type":"address"}],"name":"WitFeedSolverSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"evmSubscriber","type":"address"},{"indexed":true,"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"},{"indexed":false,"internalType":"Witnet.QueryCapabilityMember[]","name":"witCapabilityMembers","type":"bytes4[]"}],"name":"WitOracleCommittee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"queryRadHash","type":"bytes32"},{"components":[{"internalType":"uint16","name":"witResultMaxSize","type":"uint16"},{"internalType":"uint16","name":"witCommitteeCapacity","type":"uint16"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"},{"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"}],"indexed":false,"internalType":"struct Witnet.QuerySLA","name":"querySLA","type":"tuple"}],"name":"WitOracleQuery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"queryBytecode","type":"bytes"},{"components":[{"internalType":"uint16","name":"witResultMaxSize","type":"uint16"},{"internalType":"uint16","name":"witCommitteeCapacity","type":"uint16"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"},{"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"}],"indexed":false,"internalType":"struct Witnet.QuerySLA","name":"querySLA","type":"tuple"}],"name":"WitOracleQuery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackGas","type":"uint256"}],"name":"WitOracleQueryReponseDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"}],"name":"WitOracleQueryResponse","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackActualGas","type":"uint256"},{"indexed":false,"internalType":"string","name":"evmCallbackRevertReason","type":"string"},{"indexed":false,"internalType":"bytes","name":"resultCborBytes","type":"bytes"}],"name":"WitOracleQueryResponseDeliveryFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"address","name":"evmResponseDisputer","type":"address"}],"name":"WitOracleQueryResponseDispute","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"queryId","type":"uint256"},{"indexed":false,"internalType":"address","name":"evmSender","type":"address"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"}],"name":"WitOracleQueryUpgrade","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseFeeOverheadPercentage","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"class","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"codehash","outputs":[{"internalType":"bytes32","name":"_codehash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataType","outputs":[{"internalType":"enum Witnet.RadonDataTypes","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultRadonSLA","outputs":[{"components":[{"internalType":"uint16","name":"witResultMaxSize","type":"uint16"},{"internalType":"uint16","name":"witCommitteeCapacity","type":"uint16"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"},{"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"}],"internalType":"struct Witnet.QuerySLA","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"deleteFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deleteFeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"deployPriceSolver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"determinePriceSolverAddress","outputs":[{"internalType":"address","name":"_address","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_evmGasPrice","type":"uint256"}],"name":"estimateUpdateBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_evmGasPrice","type":"uint256"}],"name":"estimateUpdateRequestFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"footprint","outputs":[{"internalType":"bytes4","name":"_footprint","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"hash","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_initData","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isUpgradable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"}],"name":"isUpgradableFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lastValidQueryId","outputs":[{"internalType":"Witnet.QueryId","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lastValidQueryResponse","outputs":[{"components":[{"internalType":"address","name":"reporter","type":"address"},{"internalType":"uint64","name":"_0","type":"uint64"},{"internalType":"uint32","name":"resultTimestamp","type":"uint32"},{"internalType":"bytes32","name":"resultDrTxHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"internalType":"address","name":"disputer","type":"address"}],"internalType":"struct Witnet.QueryResponse","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestPrice","outputs":[{"components":[{"internalType":"uint64","name":"value","type":"uint64"},{"internalType":"Witnet.ResultTimestamp","name":"timestamp","type":"uint32"},{"internalType":"Witnet.TransactionHash","name":"drTxHash","type":"bytes32"},{"internalType":"enum IWitPriceFeedsSolver.LatestUpdateStatus","name":"latestStatus","type":"uint8"}],"internalType":"struct IWitPriceFeedsSolver.Price","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"feedIds","type":"bytes4[]"}],"name":"latestPrices","outputs":[{"components":[{"internalType":"uint64","name":"value","type":"uint64"},{"internalType":"Witnet.ResultTimestamp","name":"timestamp","type":"uint32"},{"internalType":"Witnet.TransactionHash","name":"drTxHash","type":"bytes32"},{"internalType":"enum IWitPriceFeedsSolver.LatestUpdateStatus","name":"latestStatus","type":"uint8"}],"internalType":"struct IWitPriceFeedsSolver.Price[]","name":"_prices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryId","outputs":[{"internalType":"Witnet.QueryId","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryRequest","outputs":[{"components":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"uint24","name":"callbackGas","type":"uint24"},{"internalType":"uint72","name":"_0","type":"uint72"},{"internalType":"bytes","name":"radonBytecode","type":"bytes"},{"internalType":"bytes32","name":"radonRadHash","type":"bytes32"}],"internalType":"struct Witnet.QueryRequest","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryResult","outputs":[{"components":[{"internalType":"enum Witnet.ResultStatus","name":"status","type":"uint8"},{"internalType":"enum Witnet.RadonDataTypes","name":"dataType","type":"uint8"},{"internalType":"Witnet.TransactionHash","name":"drTxHash","type":"bytes32"},{"internalType":"Witnet.ResultTimestamp","name":"timestamp","type":"uint32"},{"components":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"cursor","type":"uint256"}],"internalType":"struct WitnetBuffer.Buffer","name":"buffer","type":"tuple"},{"internalType":"uint8","name":"initialByte","type":"uint8"},{"internalType":"uint8","name":"majorType","type":"uint8"},{"internalType":"uint8","name":"additionalInformation","type":"uint8"},{"internalType":"uint64","name":"len","type":"uint64"},{"internalType":"uint64","name":"tag","type":"uint64"}],"internalType":"struct WitnetCBOR.CBOR","name":"value","type":"tuple"}],"internalType":"struct Witnet.DataResult","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryResultStatus","outputs":[{"internalType":"enum Witnet.ResultStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryResultStatusDescription","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResponse","outputs":[{"components":[{"internalType":"address","name":"reporter","type":"address"},{"internalType":"uint64","name":"_0","type":"uint64"},{"internalType":"uint32","name":"resultTimestamp","type":"uint32"},{"internalType":"bytes32","name":"resultDrTxHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"internalType":"address","name":"disputer","type":"address"}],"internalType":"struct Witnet.QueryResponse","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResponseStatus","outputs":[{"internalType":"enum IWitOracleLegacy.QueryResponseStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResultError","outputs":[{"components":[{"internalType":"uint8","name":"code","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"internalType":"struct IWitOracleLegacy.ResultError","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupCaption","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupPriceSolver","outputs":[{"internalType":"contract IWitPriceFeedsSolver","name":"_solverAddress","type":"address"},{"internalType":"string[]","name":"_solverDeps","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitOracleRadonRetrievals","outputs":[{"components":[{"internalType":"uint8","name":"argsCount","type":"uint8"},{"internalType":"enum Witnet.RadonRetrievalMethods","name":"method","type":"uint8"},{"internalType":"enum Witnet.RadonDataTypes","name":"dataType","type":"uint8"},{"internalType":"string","name":"url","type":"string"},{"internalType":"string","name":"body","type":"string"},{"internalType":"string[2][]","name":"headers","type":"string[2][]"},{"internalType":"bytes","name":"radonScript","type":"bytes"}],"internalType":"struct Witnet.RadonRetrieval[]","name":"_retrievals","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitOracleRequestBytecode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitOracleRequestRadHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitnetBytecode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"},{"components":[{"internalType":"uint8","name":"witCommitteeCapacity","type":"uint8"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"}],"internalType":"struct IWitFeedsLegacy.RadonSLA","name":"updateSLA","type":"tuple"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"},{"components":[{"internalType":"uint16","name":"witResultMaxSize","type":"uint16"},{"internalType":"uint16","name":"witCommitteeCapacity","type":"uint16"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"},{"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"}],"internalType":"struct Witnet.QuerySLA","name":"updateSLA","type":"tuple"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_baseFeeOverheadPercentage","type":"uint16"}],"name":"settleBaseFeeOverheadPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"witResultMaxSize","type":"uint16"},{"internalType":"uint16","name":"witCommitteeCapacity","type":"uint16"},{"internalType":"uint64","name":"witCommitteeUnitaryReward","type":"uint64"},{"internalType":"Witnet.QueryCapability","name":"witCapability","type":"bytes20"}],"internalType":"struct Witnet.QuerySLA","name":"defaultSLA","type":"tuple"}],"name":"settleDefaultRadonSLA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"bytes32","name":"radHash","type":"bytes32"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"contract WitOracleRequest","name":"request","type":"address"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"contract WitOracleRequestTemplate","name":"template","type":"address"},{"internalType":"string[][]","name":"args","type":"string[][]"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"string[]","name":"deps","type":"string[]"}],"name":"settleFeedSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specs","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"supportedFeeds","outputs":[{"internalType":"bytes4[]","name":"_ids","type":"bytes4[]"},{"internalType":"string[]","name":"_captions","type":"string[]"},{"internalType":"bytes32[]","name":"_solvers","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"supportsCaption","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"feedId","type":"bytes32"}],"name":"valueFor","outputs":[{"internalType":"int256","name":"_value","type":"int256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_status","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witOracle","outputs":[{"internalType":"contract WitOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witnet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101c0604052336101405234801561001657600080fd5b50604051615ba9380380615ba9833981016040819052610035916103c6565b80826040518060400160405280601f81526020017f696f2e7769746e65742e70726f786961626c652e66656564732e707269636500815250823360046040518060400160405280600681526020016550726963652d60d01b8152508160138111156100a2576100a261041a565b60808160138111156100b6576100b661041a565b9052506100c281610239565b60a05250506001600160a01b0381166100f657604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6100ff8161024c565b503060c052151561010052600160025561012091909152805160209182012061016052604080518082019091526011815270696e6578697374656e74206f7261636c6560781b9181019190915261016491506001600160a01b0385163b151590610268565b61022563143fb0e360e01b63124f910d60e01b186001600160e01b031916846001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e49190610430565b6001600160e01b0319161460405180604001604052806012815260200171756e636f6d706c69616e74206f7261636c6560701b81525061026860201b60201c565b50506001600160a01b031661018052610521565b600061024682602061027a565b92915050565b600180546001600160a01b03191690556102658161030a565b50565b81610276576102768161035a565b5050565b600060208260ff16111561029057610290610461565b60008260ff168451116102a45783516102a9565b8260ff165b905060005b8181101561030257806008028582815181106102cc576102cc610477565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c92909217916001016102ae565b505092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051808201909152601781527f5769745072696365466565647355706772616461626c650000000000000000006020820152816040516020016103a09291906104b1565b60408051601f198184030181529082905262461bcd60e51b82526100ed916004016104ee565b6000806000606084860312156103db57600080fd5b83516001600160a01b03811681146103f257600080fd5b602085015160408601519194509250801515811461040f57600080fd5b809150509250925092565b634e487b7160e01b600052602160045260246000fd5b60006020828403121561044257600080fd5b81516001600160e01b03198116811461045a57600080fd5b9392505050565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60005b838110156104a8578181015183820152602001610490565b50506000910152565b600083516104c381846020880161048d565b6101d160f51b90830190815283516104e281600284016020880161048d565b01600201949350505050565b602081526000825180602084015261050d81604085016020870161048d565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051615572610637600039600050506000818161051c015281816105c601528181610ed2015281816113f4015281816114dc015281816115cc01528181611a9401528181611ed30152818161216b0152818161219d01528181612258015281816123770152818161243b0152818161255801528181612b2a0152613081015260006106c901526000610be3015260006115620152600081816106fa01526116960152600050506000818161069301528181610a1201528181611269015281816112da015281816113210152611343015260008181610f9401526117b801526000818161079e01526117f101526155726000f3fe6080604052600436106103a25760003560e01c80638da5cb5b116101e7578063d3471e341161010d578063f14cb812116100a0578063f9f34bb61161006f578063f9f34bb614610d76578063ff24fb4f14610da3578063ff448afc14610dc3578063ff75890f14610df0576103a2565b8063f14cb81214610cc1578063f2fde38b14610cee578063f48db4e014610d0e578063f78eea8314610d3b576103a2565b8063e30c3978116100dc578063e30c397814610c3c578063e5cbebcb14610c51578063eb92b29b14610c7e578063ef1dff2b14610ca1576103a2565b8063d3471e3414610bb1578063d5f3948814610bd1578063d6a3614f14610c05578063e1c9e3c014610c27576103a2565b8063b411ee9411610185578063c3d98ea811610154578063c3d98ea814610b24578063c459d3ea14610b51578063c5010d1714610b64578063cfae692914610b84576103a2565b8063b411ee9414610a84578063b8d38c9614610aa4578063bff852fa14610ac4578063c064d37214610b04576103a2565b8063a9e954b9116101c1578063a9e954b914610a03578063abc86c6e14610a37578063ac82c60814610a4a578063adb7c3f714610a6a576103a2565b80638da5cb5b146109a557806396f2d185146109c3578063a55b471c146109e3576103a2565b806354fd4d50116102cc57806370c12f661161026a57806384292f071161023957806384292f071461091757806386ac03e01461093757806389809929146109575780638a416ea914610977576103a2565b806370c12f66146108b8578063715018a6146108d857806375dadb32146108ed57806379ba509714610902576103a2565b80636175ff00116102a65780636175ff001461078c5780636ab221f8146107cd5780636b58960a146107ff5780636d1178e51461081f576103a2565b806354fd4d501461072a5780635be939841461073f5780635c0d9d801461075f576103a2565b806346d1d21a116103445780634fae21eb116103135780634fae21eb146106645780635001f3b51461068457806352d1902d146106b75780635479d940146106eb576103a2565b806346d1d21a146105b757806348759633146105ea57806349492ef11461060a5780634efef9c014610637576103a2565b80631014d375116103805780631014d3751461050a578063384ac938146105565780633e088e1214610584578063439fab9114610597576103a2565b8063029db958146104935780630306732e146104c657806303f3813d146104ea575b3480156103ae57600080fd5b506000356001600160e01b03191663e0d20f7360e01b1480156103d057503330145b156104615760006103f760206103e63684613781565b6001600160c01b031916901b610e10565b6006015460408051808201909152601081526f3ab739b2ba3a3632b21039b7b63b32b960811b60208201526001600160a01b03909116915061043c9082151590610e4a565b60405136600082376000803683855af43d806000843e81801561045d578184f35b8184fd5b6104916040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610e5c565b005b34801561049f57600080fd5b506104b36104ae3660046137c5565b610ecb565b6040519081526020015b60405180910390f35b3480156104d257600080fd5b506104db610efd565b6040516104bd9392919061388c565b3480156104f657600080fd5b506104916105053660046139c7565b610f7e565b34801561051657600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016104bd565b34801561056257600080fd5b506105766105713660046137c5565b61111a565b6040516104bd929190613a4b565b6104b36105923660046137c5565b611130565b3480156105a357600080fd5b506104916105b2366004613bc8565b611192565b3480156105c357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061053e565b3480156105f657600080fd5b506104b36106053660046137c5565b6113c8565b34801561061657600080fd5b5061062a6106253660046137c5565b6113dd565b6040516104bd9190613c10565b34801561064357600080fd5b506106576106523660046137c5565b61148d565b6040516104bd9190613c38565b34801561067057600080fd5b506104b361067f366004613c4b565b611498565b34801561069057600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061053e565b3480156106c357600080fd5b506104b37f000000000000000000000000000000000000000000000000000000000000000081565b3480156106f757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190151581526020016104bd565b34801561073657600080fd5b5061065761155b565b34801561074b57600080fd5b506104b361075a3660046137c5565b61158b565b34801561076b57600080fd5b5061077f61077a3660046137c5565b6115a0565b6040516104bd9190613c64565b34801561079857600080fd5b506107c07f000000000000000000000000000000000000000000000000000000000000000081565b6040516104bd9190613cf6565b3480156107d957600080fd5b506107ed6107e83660046137c5565b611665565b60405160ff90911681526020016104bd565b34801561080b57600080fd5b5061071a61081a366004613d04565b61167d565b34801561082b57600080fd5b506108ab604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b0319169082015290565b6040516104bd9190613d67565b3480156108c457600080fd5b506106576108d33660046137c5565b6116d9565b3480156108e457600080fd5b5061049161179d565b3480156108f957600080fd5b506106576117b1565b34801561090e57600080fd5b506104916117dc565b34801561092357600080fd5b50610491610932366004613d75565b6117e4565b34801561094357600080fd5b50610491610952366004613dc0565b6119b8565b34801561096357600080fd5b506106576109723660046137c5565b611a90565b34801561098357600080fd5b5061098c611b2d565b6040516001600160e01b031990911681526020016104bd565b3480156109b157600080fd5b506000546001600160a01b031661053e565b3480156109cf57600080fd5b506104916109de366004613e13565b611c0b565b3480156109ef57600080fd5b5061053e6109fe366004613e2f565b611c63565b348015610a0f57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000003f6104b3565b6104b3610a45366004613e9a565b611da9565b348015610a5657600080fd5b50610491610a65366004613edb565b611e0b565b348015610a7657600080fd5b50630b80eaa960e11b61098c565b348015610a9057600080fd5b5061098c610a9f366004613bc8565b611e7a565b348015610ab057600080fd5b50610491610abf366004613f41565b611e89565b348015610ad057600080fd5b506040805180820190915260178152765769745072696365466565647355706772616461626c6560481b6020820152610657565b348015610b1057600080fd5b506104b3610b1f366004613c4b565b611ea9565b348015610b3057600080fd5b50610b44610b3f3660046137c5565b611eb4565b6040516104bd9190613fa5565b6104b3610b5f366004613fb3565b611fd9565b348015610b7057600080fd5b5061071a610b7f366004613dc0565b61203c565b348015610b9057600080fd5b50610ba4610b9f3660046137c5565b612138565b6040516104bd9190613fe9565b348015610bbd57600080fd5b50610ba4610bcc3660046137c5565b612225565b348015610bdd57600080fd5b5061053e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c1157600080fd5b5060008051602061551d833981519152546104b3565b348015610c3357600080fd5b5061049161228e565b348015610c4857600080fd5b5061053e61235c565b348015610c5d57600080fd5b50610c71610c6c3660046137c5565b612370565b6040516104bd919061406f565b348015610c8a57600080fd5b5060045460405161ffff90911681526020016104bd565b348015610cad57600080fd5b50610657610cbc3660046137c5565b61239c565b348015610ccd57600080fd5b50610ce1610cdc3660046137c5565b612437565b6040516104bd919061407d565b348015610cfa57600080fd5b50610491610d09366004613d04565b6124d0565b348015610d1a57600080fd5b50610d2e610d293660046137c5565b6124e1565b6040516104bd9190614097565b348015610d4757600080fd5b50610d5b610d56366004613c4b565b6125f1565b604080519384526020840192909252908201526060016104bd565b348015610d8257600080fd5b50610d96610d9136600461416c565b61267a565b6040516104bd91906141a1565b348015610daf57600080fd5b50610491610dbe3660046139c7565b612731565b348015610dcf57600080fd5b50610de3610dde3660046137c5565b61278b565b6040516104bd9190614285565b348015610dfc57600080fd5b5061053e610e0b366004613e2f565b61280f565b6001600160e01b03191660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b81610e5857610e5881610e5c565b5050565b6040805180820190915260178152765769745072696365466565647355706772616461626c6560481b602082015281604051602001610e9c92919061436b565b60408051601f198184030181529082905262461bcd60e51b8252610ec291600401613c38565b60405180910390fd5b6000610ef77f00000000000000000000000000000000000000000000000000000000000000008361289c565b92915050565b606080606073eda862f66cd1708bb77d4ec2029ce8afbffa11fc630306732e6040518163ffffffff1660e01b8152600401600060405180830381865af4158015610f4b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f739190810190614504565b925092509250909192565b610f8661294d565b610ff96001600160d01b03197f000000000000000000000000000000000000000000000000000000000000000016610fbe8688614606565b6001600160d01b03191614604051806040016040528060128152602001710c4c2c840c6c2e0e8d2dedc40e0e4caccd2f60731b815250610e4a565b6040805180820190915260118152706e6f20736f6c766572206164647265737360781b6020820152611037906001600160a01b038516151590610e4a565b6040516303f3813d60e01b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906303f3813d9061107690889088908890889088906004016146a2565b60006040518083038186803b15801561108e57600080fd5b505af492505050801561109f575060015b611113576110ab61472f565b806308c379a0036110d957506110bf61474a565b806110ca57506110db565b6110d381610e5c565b50611113565b505b3d808015611105576040519150601f19603f3d011682016040523d82523d6000602084013e61110a565b606091505b506110d361297a565b5050505050565b600060606111278361298a565b91509150915091565b6040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b03191690820152600090610ef7908390612ae5565b6000546001600160a01b0316806111c957818060200190518101906111b791906147d3565b925090506111c481612d7f565b611211565b336001600160a01b038216146112115760405162461bcd60e51b815260206004820152600d60248201526c3737ba103a34329037bbb732b960991b6044820152606401610ec2565b61121a82612d98565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe541580159061128b57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f00000000000000000000000000000000000000000000000000000000000000003f145b156112d85760405162461bcd60e51b815260206004820152601c60248201527f616c726561647920696e697469616c697a656420636f646568617368000000006044820152606401610ec2565b7f00000000000000000000000000000000000000000000000000000000000000003f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600201557f00000000000000000000000000000000000000000000000000000000000000003f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661137d6000546001600160a01b031690565b6001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f66113af61155b565b6040516113bc9190613c38565b60405180910390a45050565b60006113d382610e10565b6005015492915050565b6040805180820190915260008152606060208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a77fc1a461142a8461158b565b6040518263ffffffff1660e01b815260040161144891815260200190565b600060405180830381865afa158015611465573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef7919081019061483d565b6060610ef7826116d9565b6004546000906064906114af9061ffff16826148d6565b604051630f7b104360e31b8152600481018590526020602482015261ffff91909116906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637bd8821890604401602060405180830381865afa158015611523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154791906148f1565b611551919061490a565b610ef79190614921565b60606115867f0000000000000000000000000000000000000000000000000000000000000000612fd9565b905090565b600061159682610e10565b6004015492915050565b6040805160a08101825260008082526020820181905291810182905260608082015260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630aa4112a6116028461158b565b6040518263ffffffff1660e01b815260040161162091815260200190565b600060405180830381865afa15801561163d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614967565b600061167082610e10565b6001015460ff1692915050565b6000806116926000546001600160a01b031690565b90507f000000000000000000000000000000000000000000000000000000000000000080156116d25750826001600160a01b0316816001600160a01b0316145b9392505050565b606060006116e683610e10565b905061171f81600501546000801b14156040518060400160405280600b81526020016a0dcde40a4828840d0c2e6d60ab1b815250610e4a565b61172761307d565b6001600160a01b0316632ebf5d5c82600501546040518263ffffffff1660e01b815260040161175891815260200190565b600060405180830381865afa158015611775573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116d29190810190614a23565b6117a561294d565b6117af6000612d7f565b565b60606115867f0000000000000000000000000000000000000000000000000000000000000000613101565b6117af6131a5565b6117ec61294d565b6118db7f0000000000000000000000000000000000000000000000000000000000000000601381111561182157611821613ccc565b61182961307d565b6001600160a01b0316634c729104846040518263ffffffff1660e01b815260040161185691815260200190565b602060405180830381865afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190614a66565b60138111156118a8576118a8613ccc565b146040518060400160405280601481526020017362616420726573756c742064617461207479706560601b815250610e4a565b6040516384292f0760e01b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906384292f079061191690869086908690600401614a81565b60006040518083038186803b15801561192e57600080fd5b505af492505050801561193f575060015b6119b35761194b61472f565b806308c379a003611979575061195f61474a565b8061196a575061197b565b61197381610e5c565b50505050565b505b3d8080156119a5576040519150601f19603f3d011682016040523d82523d6000602084013e6119aa565b606091505b5061197361297a565b505050565b6119c061294d565b604051630435601f60e51b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906386ac03e0906119f99085908590600401614aa5565b60006040518083038186803b158015611a1157600080fd5b505af4925050508015611a22575060015b610e5857611a2e61472f565b806308c379a003611a565750611a4261474a565b80611a4d5750611a58565b6119b381610e5c565b505b3d808015611a82576040519150601f19603f3d011682016040523d82523d6000602084013e611a87565b606091505b506119b361297a565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c2581348611aca8461158b565b6040518263ffffffff1660e01b8152600401611ae891815260200190565b600060405180830381865afa158015611b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614a23565b60008051602061551d8339815191525460009015611c0857611ba67fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff600101600081548110611b7e57611b7e614ab9565b90600052602060002090600891828204019190066004029054906101000a900460e01b613220565b905060015b60008051602061551d83398151915254811015611c0657611bfa7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001018281548110611b7e57611b7e614ab9565b90911890600101611bab565b505b90565b611c1361294d565b611c56611c2d611c2836849003840184614afa565b6132aa565b6040518060400160405280600b81526020016a696e76616c696420534c4160a81b815250610e4a565b8060036119b38282614b65565b6000611c6d61294d565b604051632956d1c760e21b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc9063a55b471c90611caa908890889088908890600401614bfd565b602060405180830381865af4925050508015611ce3575060408051601f3d908101601f19168201909252611ce091810190614c2f565b60015b611d5757611cef61472f565b806308c379a003611d1d5750611d0361474a565b80611d0e5750611d1f565b611d1781610e5c565b50611da1565b505b3d808015611d49576040519150601f19603f3d011682016040523d82523d6000602084013e611d4e565b606091505b50611d1761297a565b7f18678abae9a91a452648053bebd7d23122fb9204cddc206fa8193750abb8940f81826001600160a01b03163f8686604051611d969493929190614c4c565b60405180910390a190505b949350505050565b604080516080810190915260035461ffff1681526000906116d2908490602080820190611dd890870187614c7e565b60ff168152602090810190611df39060408801908801614c9b565b6001600160401b031681526000602090910152612ae5565b611e1361294d565b6119b38383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e56573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093291906148f1565b80516020820120600090610ef7565b611e9161294d565b6004805461ffff191661ffff92909216919091179055565b6000610ef782611498565b611ebc613759565b604051630f92ac1760e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526001600160e01b03198316602482015273eda862f66cd1708bb77d4ec2029ce8afbffa11fc90633e4ab05c90604401608060405180830381865af4925050508015611f60575060408051601f3d908101601f19168201909252611f5d91810190614ce0565b60015b610ef757611f6c61472f565b806308c379a003611f9a5750611f8061474a565b80611f8b5750611f9c565b611f9481610e5c565b50919050565b505b3d808015611fc6576040519150601f19603f3d011682016040523d82523d6000602084013e611fcb565b606091505b50611f9461297a565b919050565b6000612024611fe9836003613312565b6040518060400160405280601781526020017f756e736563757265207570646174652072657175657374000000000000000000815250610e4a565b6116d28361203736859003850185614afa565b612ae5565b60008061207e84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e7a92505050565b90506001600160e01b0319811661212561209783610e10565b80546120a290614d3a565b80601f01602080910402602001604051908101604052809291908181526020018280546120ce90614d3a565b801561211b5780601f106120f05761010080835404028352916020019161211b565b820191906000526020600020905b8154815290600101906020018083116120fe57829003601f168201915b5050505050611e7a565b6001600160e01b03191614949350505050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082015260a08101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f61921b26121c27f00000000000000000000000000000000000000000000000000000000000000008561289c565b6040518263ffffffff1660e01b81526004016121e091815260200190565b600060405180830381865afa1580156121fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614d6e565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082015260a08101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f61921b26121c28461158b565b61229661294d565b73eda862f66cd1708bb77d4ec2029ce8afbffa11fc63e1c9e3c06040518163ffffffff1660e01b815260040160006040518083038186803b1580156122da57600080fd5b505af49250505080156122eb575060015b6117af576122f761472f565b806308c379a003612322575061230b61474a565b806123165750612324565b61231f81610e5c565b50565b505b3d80801561234e576040519150601f19603f3d011682016040523d82523d6000602084013e612353565b606091505b5061231f61297a565b60006115866001546001600160a01b031690565b6000610ef77f0000000000000000000000000000000000000000000000000000000000000000836133d0565b60606123a782610e10565b80546123b290614d3a565b80601f01602080910402602001604051908101604052809291908181526020018280546123de90614d3a565b801561242b5780601f106124005761010080835404028352916020019161242b565b820191906000526020600020905b81548152906001019060200180831161240e57829003601f168201915b50505050509050919050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663234fe6e36124718461158b565b6040518263ffffffff1660e01b815260040161248f91815260200190565b602060405180830381865afa1580156124ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef79190614e2e565b6124d861294d565b61231f81613463565b6125566040805160a08101909152806000815260200160008152600060208201819052604082015260600161377c604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166359209b3961258e8461158b565b6040518263ffffffff1660e01b81526004016125ac91815260200190565b600060405180830381865afa1580156125c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614e5f565b60008060008061260085611eb4565b805160208201519192506001600160401b03169060028360600151600381111561262c5761262c613ccc565b1461265e5760018360600151600381111561264957612649613ccc565b1461265657610190612661565b610194612661565b60c85b91955063ffffffff16935061ffff169150509193909250565b6060816001600160401b0381111561269457612694613a6f565b6040519080825280602002602001820160405280156126cd57816020015b6126ba613759565b8152602001906001900390816126b25790505b50905060005b8281101561272a576127058484838181106126f0576126f0614ab9565b9050602002016020810190610b3f91906137c5565b82828151811061271757612717614ab9565b60209081029190910101526001016126d3565b5092915050565b61273961294d565b6111138585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161276c929190615019565b6020604051808303816000875af1158015611e56573d6000803e3d6000fd5b606061279561307d565b6001600160a01b03166377c112596127ac846113c8565b6040518263ffffffff1660e01b81526004016127ca91815260200190565b600060405180830381865afa1580156127e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef791908101906151a5565b6040516001628a76f160e01b0319815260009073eda862f66cd1708bb77d4ec2029ce8afbffa11fc9063ff75890f90612852908890889088908890600401614bfd565b602060405180830381865af415801561286f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128939190614c2f565b95945050505050565b60006128a782610e10565b60040154905080158061293457506000604051634cddf61560e01b8152600481018390526001600160a01b03851690634cddf61590602401602060405180830381865afa1580156128fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612920919061533f565b60ff81111561293157612931613ccc565b14155b15610ef75761294282610e10565b600301549392505050565b6000546001600160a01b031633146117af5760405163118cdaa760e01b8152336004820152602401610ec2565b6117af612985613495565b610e5c565b6000606061299783610e10565b600601546001600160a01b0316915060006129b1846134e8565b905080516001600160401b038111156129cc576129cc613a6f565b6040519080825280602002602001820160405280156129ff57816020015b60608152602001906001900390816129ea5790505b50915060005b8151811015612ade57612a30828281518110612a2357612a23614ab9565b6020026020010151610e10565b8054612a3b90614d3a565b80601f0160208091040260200160405190810160405280929190818152602001828054612a6790614d3a565b8015612ab45780601f10612a8957610100808354040283529160200191612ab4565b820191906000526020600020905b815481529060010190602001808311612a9757829003601f168201915b5050505050838281518110612acb57612acb614ab9565b6020908102919091010152600101612a05565b5050915091565b6000612af083610e10565b6005015415612ca357604051630a5581f560e11b8152349073eda862f66cd1708bb77d4ec2029ce8afbffa11fc906314ab03ea90612b58907f00000000000000000000000000000000000000000000000000000000000000009088908890879060040161535a565b6040805180830381865af4925050508015612b90575060408051601f3d908101601f19168201909252612b8d91810190615396565b60015b612c0457612b9c61472f565b806308c379a003612bca5750612bb061474a565b80612bbb5750612bcc565b612bc481610e5c565b50612c9d565b505b3d808015612bf6576040519150601f19603f3d011682016040523d82523d6000602084013e612bfb565b606091505b50612bc461297a565b34811015612c4457336108fc612c1a83346153ba565b6040518115909202916000818181858888f19350505050158015612c42573d6000803e3d6000fd5b505b604080513281523360208201526001600160e01b03198816818301526060810184905290517f0bd652a116bb5006c2e07594e8a3fe9b5ba51acf6cd9572568913fda51ad26c49181900360800190a19250610ef7915050565b50610ef7565b6000612cae84610e10565b600601546001600160a01b031614612d525760405163148a3a1160e11b81526001600160e01b031984166004820152612d4b9073eda862f66cd1708bb77d4ec2029ce8afbffa11fc90632914742290602401600060405180830381865af4158015612d1d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d4591908101906153cd565b836135d2565b9050610ef7565b610ef76040518060400160405280600c81526020016b1d5b9adb9bdddb881999595960a21b815250610e5c565b600180546001600160a01b031916905561231f81613697565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54612e08576040805160808101825260108152600a60208201819052630bebc200928201929092526000606090910152670bebc200000a00106003556004805461ffff19169091179055612f44565b805115612ead5760008082806020019051810190612e269190615401565b6004805461ffff191661ffff9384161790558051600380546020840151604085015160609586015194871663ffffffff19909316929092176201000091909616029490941763ffffffff166401000000006001600160401b03909516949094026bffffffffffffffffffffffff1693909317600160601b9190921c0217905550612f449050565b6040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b03191690820152612f0a906132aa565b612f44576040805160808101825260108152600a6020820152630bebc200918101919091526000606090910152670bebc200000a00106003555b60005b60008051602061551d83398151915254811015610e585760007fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001018281548110612f9557612f95614ab9565b60009182526020822060088204015460079091166004026101000a900460e01b9150612fc082610e10565b6000600382018190556004909101555050600101612f47565b60606000612fe6836136e7565b6001600160401b03811115612ffd57612ffd613a6f565b6040519080825280601f01601f191660200182016040528015613027576020820181803683370190505b50905060005b815181101561272a5783816020811061304857613048614ab9565b1a60f81b82828151811061305e5761305e614ab9565b60200101906001600160f81b031916908160001a90535060010161302d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115869190614c2f565b6060600061310e83613720565b6001600160401b0381111561312557613125613a6f565b6040519080825280601f01601f19166020018201604052801561314f576020820181803683370190505b50905060005b815181101561272a5783816020811061317057613170614ab9565b1a60f81b82828151811061318657613186614ab9565b60200101906001600160f81b031916908160001a905350600101613155565b33806131af61235c565b6001600160a01b0316146132175760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610ec2565b61231f81612d7f565b60008061322c83610e10565b600501541461327c578161323f83610e10565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b8161328683610e10565b60080154604080516001600160e01b0319909316602084015282015260600161325f565b805160009061ffff16158015906132ce5750600082604001516001600160401b0316115b80156132e257506000826020015161ffff16115b8015610ef7575060608201516001600160601b031916151580610ef757505060200151607f61ffff909116111590565b8054600090600160601b9004606090811b6001600160601b0319169061333e9060808601908601615495565b6001600160601b0319161480156133735750815462010000900461ffff1661336c6040850160208601613f41565b61ffff1610155b80156133a95750815464010000000090046001600160401b031661339d6060850160408601614c9b565b6001600160401b031610155b80156116d25750815461ffff166133c36020850185613f41565b61ffff1611159392505050565b6000806133dc83610e10565b600401549050801561345957604051634cddf61560e01b8152600481018290526001600160a01b03851690634cddf61590602401602060405180830381865afa15801561342d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613451919061533f565b915050610ef7565b6000915050610ef7565b61346b61294d565b6001600160a01b03811661321757604051631e4fbdf760e01b815260006004820152602401610ec2565b6060604051806040016040526014815280602001732bb4ba283934b1b2a332b2b239a230ba30a634b160611b8152506040516020016134d491906154b2565b604051602081830303815290604052905090565b6001600160e01b0319811660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602090815260409182902060089081015483518281526101208101909452606093909290919082016101008036833701905050915060005b60088110156135ca578183828151811061356d5761356d614ab9565b60200260200101906001600160e01b03191690816001600160e01b031916815250508281815181106135a1576135a1614ab9565b60209081029190910101516001600160e01b031916156135ca57602082901b9150600101613551565b825250919050565b6000808351346135e29190614921565b905060005b845181101561368f57306001600160a01b031663c459d3ea8387848151811061361257613612614ab9565b6020026020010151876040518463ffffffff1660e01b81526004016136389291906154eb565b60206040518083038185885af1158015613656573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061367b91906148f1565b6136859084615509565b92506001016135e7565b505092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b6020811015611fd45781816020811061370557613705614ab9565b1a60f81b6001600160f81b03191615611fd4576001016136ea565b60005b6020811015611fd45781816020811061373e5761373e614ab9565b1a60f81b6001600160f81b03191615611fd457600101613723565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b6001600160c01b0319813581811691600885101561368f5760089490940360031b84901b1690921692915050565b6001600160e01b03198116811461231f57600080fd5b6000602082840312156137d757600080fd5b81356116d2816137af565b60005b838110156137fd5781810151838201526020016137e5565b50506000910152565b6000815180845261381e8160208601602086016137e2565b601f01601f19169290920160200192915050565b60008282518085526020808601955060208260051b8401016020860160005b8481101561387f57601f1986840301895261386d838351613806565b98840198925090830190600101613851565b5090979650505050505050565b606080825284519082018190526000906020906080840190828801845b828110156138cf5781516001600160e01b031916845292840192908401906001016138a9565b505050838103828501526138e38187613832565b8481036040860152855180825283870192509083019060005b81811015613918578351835292840192918401916001016138fc565b509098975050505050505050565b60008083601f84011261393857600080fd5b5081356001600160401b0381111561394f57600080fd5b60208301915083602082850101111561396757600080fd5b9250929050565b6001600160a01b038116811461231f57600080fd5b60008083601f84011261399557600080fd5b5081356001600160401b038111156139ac57600080fd5b6020830191508360208260051b850101111561396757600080fd5b6000806000806000606086880312156139df57600080fd5b85356001600160401b03808211156139f657600080fd5b613a0289838a01613926565b909750955060208801359150613a178261396e565b90935060408701359080821115613a2d57600080fd5b50613a3a88828901613983565b969995985093965092949392505050565b6001600160a01b0383168152604060208201819052600090611da190830184613832565b634e487b7160e01b600052604160045260246000fd5b604081018181106001600160401b0382111715613aa457613aa4613a6f565b60405250565b60a081018181106001600160401b0382111715613aa457613aa4613a6f565b608081018181106001600160401b0382111715613aa457613aa4613a6f565b60c081018181106001600160401b0382111715613aa457613aa4613a6f565b601f8201601f191681016001600160401b0381118282101715613b2c57613b2c613a6f565b6040525050565b60405160e081016001600160401b0381118282101715613b5557613b55613a6f565b60405290565b60006001600160401b03821115613b7457613b74613a6f565b50601f01601f191660200190565b6000613b8d83613b5b565b604051613b9a8282613b07565b809250848152858585011115613baf57600080fd5b8484602083013760006020868301015250509392505050565b600060208284031215613bda57600080fd5b81356001600160401b03811115613bf057600080fd5b8201601f81018413613c0157600080fd5b611da184823560208401613b82565b6020815260ff825116602082015260006020830151604080840152611da16060840182613806565b6020815260006116d26020830184613806565b600060208284031215613c5d57600080fd5b5035919050565b6020815260018060a01b03825116602082015262ffffff602083015116604082015268ffffffffffffffffff60408301511660608201526000606083015160a06080840152613cb660c0840182613806565b9050608084015160a08401528091505092915050565b634e487b7160e01b600052602160045260246000fd5b60148110613cf257613cf2613ccc565b9052565b60208101610ef78284613ce2565b600060208284031215613d1657600080fd5b81356116d28161396e565b61ffff808251168352806020830151166020840152506001600160401b0360408201511660408301526bffffffffffffffffffffffff1960608201511660608301525050565b60808101610ef78284613d21565b600080600060408486031215613d8a57600080fd5b83356001600160401b03811115613da057600080fd5b613dac86828701613926565b909790965060209590950135949350505050565b60008060208385031215613dd357600080fd5b82356001600160401b03811115613de957600080fd5b613df585828601613926565b90969095509350505050565b600060808284031215611f9457600080fd5b600060808284031215613e2557600080fd5b6116d28383613e01565b60008060008060408587031215613e4557600080fd5b84356001600160401b0380821115613e5c57600080fd5b613e6888838901613926565b90965094506020870135915080821115613e8157600080fd5b50613e8e87828801613926565b95989497509550505050565b6000808284036060811215613eae57600080fd5b8335613eb9816137af565b92506040601f1982011215613ecd57600080fd5b506020830190509250929050565b600080600060408486031215613ef057600080fd5b83356001600160401b03811115613f0657600080fd5b613f1286828701613926565b9094509250506020840135613f268161396e565b809150509250925092565b61ffff8116811461231f57600080fd5b600060208284031215613f5357600080fd5b81356116d281613f31565b6001600160401b03815116825263ffffffff602082015116602083015260408101516040830152606081015160048110613f9a57613f9a613ccc565b806060840152505050565b60808101610ef78284613f5e565b60008060a08385031215613fc657600080fd5b8235613fd1816137af565b9150613fe08460208501613e01565b90509250929050565b60208152600060018060a01b038084511660208401526001600160401b03602085015116604084015263ffffffff604085015116606084015260608401516080840152608084015160c060a085015261404560e0850182613806565b90508160a08601511660c0850152809250505092915050565b6101008110613cf257613cf2613ccc565b60208101610ef7828461405e565b602081016007831061409157614091613ccc565b91905290565b602081526140a960208201835161405e565b600060208301516140bd6040840182613ce2565b506040830151606083015263ffffffff6060840151166080830152608083015160a080840152805160c080850152805160406101808601526141036101c0860182613806565b6020928301516101a08701529183015160ff1660e08601525060408201519061413261010086018360ff169052565b606083015160ff1661012086015260808301516001600160401b0380821661014088015260a0909401519384166101608701529150612893565b6000806020838503121561417f57600080fd5b82356001600160401b0381111561419557600080fd5b613df585828601613983565b6020808252825182820181905260009190848201906040850190845b818110156141e3576141d0838551613f5e565b92840192608092909201916001016141bd565b50909695505050505050565b60058110613cf257613cf2613ccc565b600082825180855260208086019550808260051b8401018186016000805b8581101561427757868403601f19018a5282518460408101845b6002811015614262578782038352614250828551613806565b93890193928901929150600101614237565b509b87019b955050509184019160010161421d565b509198975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561391857603f19898403018552815160e060ff8251168552888201516142da8a8701826141ef565b50878201516142eb89870182613ce2565b50606080830151828288015261430383880182613806565b925050506080808301518683038288015261431e8382613806565b9250505060a0808301518683038288015261433983826141ff565b9250505060c080830151925085820381870152506143578183613806565b9689019694505050908601906001016142ae565b6000835161437d8184602088016137e2565b6101d160f51b908301908152835161439c8160028401602088016137e2565b01600201949350505050565b60006001600160401b038211156143c1576143c1613a6f565b5060051b60200190565b600082601f8301126143dc57600080fd5b815160206143e9826143a8565b6040516143f68282613b07565b80915083815260208101915060208460051b87010193508684111561441a57600080fd5b602086015b8481101561443f578051614432816137af565b835291830191830161441f565b509695505050505050565b600082601f83011261445b57600080fd5b815161446681613b5b565b6040516144738282613b07565b82815285602084870101111561448857600080fd5b6128938360208301602088016137e2565b600082601f8301126144aa57600080fd5b815160206144b7826143a8565b6040516144c48282613b07565b80915083815260208101915060208460051b8701019350868411156144e857600080fd5b602086015b8481101561443f57805183529183019183016144ed565b60008060006060848603121561451957600080fd5b83516001600160401b038082111561453057600080fd5b61453c878388016143cb565b945060209150818601518181111561455357600080fd5b8601601f8101881361456457600080fd5b805161456f816143a8565b60405161457c8282613b07565b82815260059290921b830185019185810191508a83111561459c57600080fd5b8584015b838110156145d4578051868111156145b85760008081fd5b6145c68d898389010161444a565b8452509186019186016145a0565b5060408a01519097509450505050808211156145ef57600080fd5b506145fc86828701614499565b9150509250925092565b6001600160d01b0319813581811691600685101561368f5760069490940360031b84901b1690921692915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e1984360301811261467457600080fd5b83016020810192503590506001600160401b0381111561469357600080fd5b80360382131561396757600080fd5b6060815260006146b6606083018789614634565b6001600160a01b0386166020848101919091528382036040850152848252818101600586901b830182018760005b8881101561471e57858303601f190184526146ff828b61465d565b61470a858284614634565b9587019594505050908401906001016146e4565b50909b9a5050505050505050505050565b600060033d1115611c085760046000803e5060005160e01c90565b600060443d10156147585790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561478757505050505090565b828501915081518181111561479f5750505050505090565b843d87010160208285010111156147b95750505050505090565b6147c860208286010187613b07565b509095945050505050565b600080604083850312156147e657600080fd5b82516147f18161396e565b60208401519092506001600160401b0381111561480d57600080fd5b6148198582860161444a565b9150509250929050565b60ff8116811461231f57600080fd5b8051611fd481614823565b60006020828403121561484f57600080fd5b81516001600160401b038082111561486657600080fd5b908301906040828603121561487a57600080fd5b60405161488681613a85565b825161489181614823565b81526020830151828111156148a557600080fd5b6148b18782860161444a565b60208301525095945050505050565b634e487b7160e01b600052601160045260246000fd5b61ffff81811683821601908082111561272a5761272a6148c0565b60006020828403121561490357600080fd5b5051919050565b8082028115828204841417610ef757610ef76148c0565b60008261493e57634e487b7160e01b600052601260045260246000fd5b500490565b8051611fd48161396e565b805168ffffffffffffffffff81168114611fd457600080fd5b60006020828403121561497957600080fd5b81516001600160401b038082111561499057600080fd5b9083019060a082860312156149a457600080fd5b6040516149b081613aaa565b82516149bb8161396e565b8152602083015162ffffff811681146149d357600080fd5b60208201526149e46040840161494e565b60408201526060830151828111156149fb57600080fd5b614a078782860161444a565b6060830152506080830151608082015280935050505092915050565b600060208284031215614a3557600080fd5b81516001600160401b03811115614a4b57600080fd5b611da18482850161444a565b805160148110611fd457600080fd5b600060208284031215614a7857600080fd5b6116d282614a57565b604081526000614a95604083018587614634565b9050826020830152949350505050565b602081526000611da1602083018486614634565b634e487b7160e01b600052603260045260246000fd5b6001600160401b038116811461231f57600080fd5b6001600160601b03198116811461231f57600080fd5b600060808284031215614b0c57600080fd5b604051614b1881613ac9565b8235614b2381613f31565b81526020830135614b3381613f31565b60208201526040830135614b4681614acf565b60408201526060830135614b5981614ae4565b60608201529392505050565b8135614b7081613f31565b61ffff8116905081548161ffff1982161783556020840135614b9181613f31565b63ffff00008160101b169050808363ffffffff198416171784556040850135614bb981614acf565b6bffffffffffffffff0000000060209190911b166001600160601b03199283168417821781178555606086013592614bf084614ae4565b9290921692171717905550565b604081526000614c11604083018688614634565b8281036020840152614c24818587614634565b979650505050505050565b600060208284031215614c4157600080fd5b81516116d28161396e565b60018060a01b0385168152836020820152606060408201526000614c74606083018486614634565b9695505050505050565b600060208284031215614c9057600080fd5b81356116d281614823565b600060208284031215614cad57600080fd5b81356116d281614acf565b8051611fd481614acf565b63ffffffff8116811461231f57600080fd5b8051611fd481614cc3565b600060808284031215614cf257600080fd5b604051614cfe81613ac9565b8251614d0981614acf565b81526020830151614d1981614cc3565b602082015260408381015190820152606083015160048110614b5957600080fd5b600181811c90821680614d4e57607f821691505b602082108103611f9457634e487b7160e01b600052602260045260246000fd5b600060208284031215614d8057600080fd5b81516001600160401b0380821115614d9757600080fd5b9083019060c08286031215614dab57600080fd5b604051614db781613ae8565b8251614dc28161396e565b8152614dd060208401614cb8565b6020820152614de160408401614cd5565b604082015260608301516060820152608083015182811115614e0257600080fd5b614e0e8782860161444a565b608083015250614e2060a08401614943565b60a082015295945050505050565b600060208284031215614e4057600080fd5b8151600781106116d257600080fd5b80516101008110611fd457600080fd5b60006020808385031215614e7257600080fd5b82516001600160401b0380821115614e8957600080fd5b9084019060a08287031215614e9d57600080fd5b60408051614eaa81613aaa565b614eb384614e4f565b8152614ec0858501614a57565b8582015281840151828201526060840151614eda81614cc3565b6060820152608084015183811115614ef157600080fd5b939093019260c08489031215614f0657600080fd5b8151614f1181613ae8565b845184811115614f2057600080fd5b8501808a03841315614f3157600080fd5b8351614f3c81613a85565b815186811115614f4b57600080fd5b614f578c82850161444a565b82525090870151878201528152614f6f858701614832565b86820152614f7e838601614832565b83820152614f8e60608601614832565b6060820152614f9f60808601614cb8565b6080820152614fb060a08601614cb8565b60a08201526080820152979650505050505050565b6000838385526020808601955060208560051b8301018460005b8781101561387f57848303601f19018952614ffa828861465d565b615005858284614634565b9a86019a9450505090830190600101614fdf565b6020808252818101839052600090600560408085019086831b86010187855b8881101561391857878303603f190184528135368b9003601e1901811261505e57600080fd5b8a0186810190356001600160401b0381111561507957600080fd5b80871b360382131561508a57600080fd5b615095858284614fc5565b958801959450505090850190600101615038565b805160058110611fd457600080fd5b600082601f8301126150c957600080fd5b815160206150d6826143a8565b6040516150e38282613b07565b83815260059390931b850182019282810191508684111561510357600080fd5b8286015b8481101561443f5780516001600160401b03808211156151275760008081fd5b818901915089603f83011261513c5760008081fd5b60405161514881613a85565b80606084018c81111561515b5760008081fd5b8885015b81811015615193578051858111156151775760008081fd5b6151858f8c838a010161444a565b84525091890191890161515f565b50505085525050918301918301615107565b600060208083850312156151b857600080fd5b82516001600160401b03808211156151cf57600080fd5b818501915085601f8301126151e357600080fd5b81516151ee816143a8565b6040516151fb8282613b07565b82815260059290921b840185019185810191508883111561521b57600080fd5b8585015b838110156153325780518581111561523657600080fd5b860160e0818c03601f1901121561524d5760008081fd5b615255613b33565b615260898301614832565b815261526e604083016150a9565b89820152606061527f818401614a57565b6040830152608080840151898111156152985760008081fd5b6152a68f8d8388010161444a565b838501525060a0915081840151898111156152c15760008081fd5b6152cf8f8d8388010161444a565b82850152505060c080840151898111156152e95760008081fd5b6152f78f8d838801016150b8565b838501525060e08401519150888211156153115760008081fd5b61531f8e8c8487010161444a565b908301525084525091860191860161521f565b5098975050505050505050565b60006020828403121561535157600080fd5b6116d282614e4f565b6001600160a01b03851681526001600160e01b03198416602082015260e081016153876040830185613d21565b8260c083015295945050505050565b600080604083850312156153a957600080fd5b505080516020909101519092909150565b81810381811115610ef757610ef76148c0565b6000602082840312156153df57600080fd5b81516001600160401b038111156153f557600080fd5b611da1848285016143cb565b60008082840360a081121561541557600080fd5b835161542081613f31565b92506080601f198201121561543457600080fd5b5060405161544181613ac9565b602084015161544f81613f31565b8152604084015161545f81613f31565b6020820152606084015161547281614acf565b6040820152608084015161548581614ae4565b6060820152919491935090915050565b6000602082840312156154a757600080fd5b81356116d281614ae4565b600082516154c48184602087016137e2565b741d103ab73430b7323632b21030b9b9b2b93a34b7b760591b920191825250601501919050565b6001600160e01b03198316815260a081016116d26020830184613d21565b80820180821115610ef757610ef76148c056fee36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200a2646970667358221220b07503a885f5cf3c4e918dc36833de8a95ccc0bd3eaa418aa12e07ea294b055e64736f6c6343000819003300000000000000000000000077703ae126b971c9946d562f41dd47071da00777322e312e302d346535346132652d6637353361616400000000000000000000000000000000000000000000000000000000000000000000000000000000000001

Deployed Bytecode

0x6080604052600436106103a25760003560e01c80638da5cb5b116101e7578063d3471e341161010d578063f14cb812116100a0578063f9f34bb61161006f578063f9f34bb614610d76578063ff24fb4f14610da3578063ff448afc14610dc3578063ff75890f14610df0576103a2565b8063f14cb81214610cc1578063f2fde38b14610cee578063f48db4e014610d0e578063f78eea8314610d3b576103a2565b8063e30c3978116100dc578063e30c397814610c3c578063e5cbebcb14610c51578063eb92b29b14610c7e578063ef1dff2b14610ca1576103a2565b8063d3471e3414610bb1578063d5f3948814610bd1578063d6a3614f14610c05578063e1c9e3c014610c27576103a2565b8063b411ee9411610185578063c3d98ea811610154578063c3d98ea814610b24578063c459d3ea14610b51578063c5010d1714610b64578063cfae692914610b84576103a2565b8063b411ee9414610a84578063b8d38c9614610aa4578063bff852fa14610ac4578063c064d37214610b04576103a2565b8063a9e954b9116101c1578063a9e954b914610a03578063abc86c6e14610a37578063ac82c60814610a4a578063adb7c3f714610a6a576103a2565b80638da5cb5b146109a557806396f2d185146109c3578063a55b471c146109e3576103a2565b806354fd4d50116102cc57806370c12f661161026a57806384292f071161023957806384292f071461091757806386ac03e01461093757806389809929146109575780638a416ea914610977576103a2565b806370c12f66146108b8578063715018a6146108d857806375dadb32146108ed57806379ba509714610902576103a2565b80636175ff00116102a65780636175ff001461078c5780636ab221f8146107cd5780636b58960a146107ff5780636d1178e51461081f576103a2565b806354fd4d501461072a5780635be939841461073f5780635c0d9d801461075f576103a2565b806346d1d21a116103445780634fae21eb116103135780634fae21eb146106645780635001f3b51461068457806352d1902d146106b75780635479d940146106eb576103a2565b806346d1d21a146105b757806348759633146105ea57806349492ef11461060a5780634efef9c014610637576103a2565b80631014d375116103805780631014d3751461050a578063384ac938146105565780633e088e1214610584578063439fab9114610597576103a2565b8063029db958146104935780630306732e146104c657806303f3813d146104ea575b3480156103ae57600080fd5b506000356001600160e01b03191663e0d20f7360e01b1480156103d057503330145b156104615760006103f760206103e63684613781565b6001600160c01b031916901b610e10565b6006015460408051808201909152601081526f3ab739b2ba3a3632b21039b7b63b32b960811b60208201526001600160a01b03909116915061043c9082151590610e4a565b60405136600082376000803683855af43d806000843e81801561045d578184f35b8184fd5b6104916040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610e5c565b005b34801561049f57600080fd5b506104b36104ae3660046137c5565b610ecb565b6040519081526020015b60405180910390f35b3480156104d257600080fd5b506104db610efd565b6040516104bd9392919061388c565b3480156104f657600080fd5b506104916105053660046139c7565b610f7e565b34801561051657600080fd5b5061053e7f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077781565b6040516001600160a01b0390911681526020016104bd565b34801561056257600080fd5b506105766105713660046137c5565b61111a565b6040516104bd929190613a4b565b6104b36105923660046137c5565b611130565b3480156105a357600080fd5b506104916105b2366004613bc8565b611192565b3480156105c357600080fd5b507f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077761053e565b3480156105f657600080fd5b506104b36106053660046137c5565b6113c8565b34801561061657600080fd5b5061062a6106253660046137c5565b6113dd565b6040516104bd9190613c10565b34801561064357600080fd5b506106576106523660046137c5565b61148d565b6040516104bd9190613c38565b34801561067057600080fd5b506104b361067f366004613c4b565b611498565b34801561069057600080fd5b507f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f061053e565b3480156106c357600080fd5b506104b37f688a557b3c9b52d2ba2301577897f3d892372d2d9be386db46c3ca9048c47f0b81565b3480156106f757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000015b60405190151581526020016104bd565b34801561073657600080fd5b5061065761155b565b34801561074b57600080fd5b506104b361075a3660046137c5565b61158b565b34801561076b57600080fd5b5061077f61077a3660046137c5565b6115a0565b6040516104bd9190613c64565b34801561079857600080fd5b506107c07f000000000000000000000000000000000000000000000000000000000000000481565b6040516104bd9190613cf6565b3480156107d957600080fd5b506107ed6107e83660046137c5565b611665565b60405160ff90911681526020016104bd565b34801561080b57600080fd5b5061071a61081a366004613d04565b61167d565b34801561082b57600080fd5b506108ab604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b0319169082015290565b6040516104bd9190613d67565b3480156108c457600080fd5b506106576108d33660046137c5565b6116d9565b3480156108e457600080fd5b5061049161179d565b3480156108f957600080fd5b506106576117b1565b34801561090e57600080fd5b506104916117dc565b34801561092357600080fd5b50610491610932366004613d75565b6117e4565b34801561094357600080fd5b50610491610952366004613dc0565b6119b8565b34801561096357600080fd5b506106576109723660046137c5565b611a90565b34801561098357600080fd5b5061098c611b2d565b6040516001600160e01b031990911681526020016104bd565b3480156109b157600080fd5b506000546001600160a01b031661053e565b3480156109cf57600080fd5b506104916109de366004613e13565b611c0b565b3480156109ef57600080fd5b5061053e6109fe366004613e2f565b611c63565b348015610a0f57600080fd5b507f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f03f6104b3565b6104b3610a45366004613e9a565b611da9565b348015610a5657600080fd5b50610491610a65366004613edb565b611e0b565b348015610a7657600080fd5b50630b80eaa960e11b61098c565b348015610a9057600080fd5b5061098c610a9f366004613bc8565b611e7a565b348015610ab057600080fd5b50610491610abf366004613f41565b611e89565b348015610ad057600080fd5b506040805180820190915260178152765769745072696365466565647355706772616461626c6560481b6020820152610657565b348015610b1057600080fd5b506104b3610b1f366004613c4b565b611ea9565b348015610b3057600080fd5b50610b44610b3f3660046137c5565b611eb4565b6040516104bd9190613fa5565b6104b3610b5f366004613fb3565b611fd9565b348015610b7057600080fd5b5061071a610b7f366004613dc0565b61203c565b348015610b9057600080fd5b50610ba4610b9f3660046137c5565b612138565b6040516104bd9190613fe9565b348015610bbd57600080fd5b50610ba4610bcc3660046137c5565b612225565b348015610bdd57600080fd5b5061053e7f00000000000000000000000003232abe800d1638b30432feef300581de323a4e81565b348015610c1157600080fd5b5060008051602061551d833981519152546104b3565b348015610c3357600080fd5b5061049161228e565b348015610c4857600080fd5b5061053e61235c565b348015610c5d57600080fd5b50610c71610c6c3660046137c5565b612370565b6040516104bd919061406f565b348015610c8a57600080fd5b5060045460405161ffff90911681526020016104bd565b348015610cad57600080fd5b50610657610cbc3660046137c5565b61239c565b348015610ccd57600080fd5b50610ce1610cdc3660046137c5565b612437565b6040516104bd919061407d565b348015610cfa57600080fd5b50610491610d09366004613d04565b6124d0565b348015610d1a57600080fd5b50610d2e610d293660046137c5565b6124e1565b6040516104bd9190614097565b348015610d4757600080fd5b50610d5b610d56366004613c4b565b6125f1565b604080519384526020840192909252908201526060016104bd565b348015610d8257600080fd5b50610d96610d9136600461416c565b61267a565b6040516104bd91906141a1565b348015610daf57600080fd5b50610491610dbe3660046139c7565b612731565b348015610dcf57600080fd5b50610de3610dde3660046137c5565b61278b565b6040516104bd9190614285565b348015610dfc57600080fd5b5061053e610e0b366004613e2f565b61280f565b6001600160e01b03191660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b81610e5857610e5881610e5c565b5050565b6040805180820190915260178152765769745072696365466565647355706772616461626c6560481b602082015281604051602001610e9c92919061436b565b60408051601f198184030181529082905262461bcd60e51b8252610ec291600401613c38565b60405180910390fd5b6000610ef77f00000000000000000000000077703ae126b971c9946d562f41dd47071da007778361289c565b92915050565b606080606073eda862f66cd1708bb77d4ec2029ce8afbffa11fc630306732e6040518163ffffffff1660e01b8152600401600060405180830381865af4158015610f4b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f739190810190614504565b925092509250909192565b610f8661294d565b610ff96001600160d01b03197f50726963652d000000000000000000000000000000000000000000000000000016610fbe8688614606565b6001600160d01b03191614604051806040016040528060128152602001710c4c2c840c6c2e0e8d2dedc40e0e4caccd2f60731b815250610e4a565b6040805180820190915260118152706e6f20736f6c766572206164647265737360781b6020820152611037906001600160a01b038516151590610e4a565b6040516303f3813d60e01b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906303f3813d9061107690889088908890889088906004016146a2565b60006040518083038186803b15801561108e57600080fd5b505af492505050801561109f575060015b611113576110ab61472f565b806308c379a0036110d957506110bf61474a565b806110ca57506110db565b6110d381610e5c565b50611113565b505b3d808015611105576040519150601f19603f3d011682016040523d82523d6000602084013e61110a565b606091505b506110d361297a565b5050505050565b600060606111278361298a565b91509150915091565b6040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b03191690820152600090610ef7908390612ae5565b6000546001600160a01b0316806111c957818060200190518101906111b791906147d3565b925090506111c481612d7f565b611211565b336001600160a01b038216146112115760405162461bcd60e51b815260206004820152600d60248201526c3737ba103a34329037bbb732b960991b6044820152606401610ec2565b61121a82612d98565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe541580159061128b57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f03f145b156112d85760405162461bcd60e51b815260206004820152601c60248201527f616c726561647920696e697469616c697a656420636f646568617368000000006044820152606401610ec2565b7f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f03f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600201557f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f03f7f000000000000000000000000210b6cb2062bf231e43a5d2a7b3be7aec65f51f06001600160a01b031661137d6000546001600160a01b031690565b6001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f66113af61155b565b6040516113bc9190613c38565b60405180910390a45050565b60006113d382610e10565b6005015492915050565b6040805180820190915260008152606060208201527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663a77fc1a461142a8461158b565b6040518263ffffffff1660e01b815260040161144891815260200190565b600060405180830381865afa158015611465573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef7919081019061483d565b6060610ef7826116d9565b6004546000906064906114af9061ffff16826148d6565b604051630f7b104360e31b8152600481018590526020602482015261ffff91909116906001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771690637bd8821890604401602060405180830381865afa158015611523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154791906148f1565b611551919061490a565b610ef79190614921565b60606115867f322e312e302d346535346132652d663735336161640000000000000000000000612fd9565b905090565b600061159682610e10565b6004015492915050565b6040805160a08101825260008082526020820181905291810182905260608082015260808101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316630aa4112a6116028461158b565b6040518263ffffffff1660e01b815260040161162091815260200190565b600060405180830381865afa15801561163d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614967565b600061167082610e10565b6001015460ff1692915050565b6000806116926000546001600160a01b031690565b90507f000000000000000000000000000000000000000000000000000000000000000180156116d25750826001600160a01b0316816001600160a01b0316145b9392505050565b606060006116e683610e10565b905061171f81600501546000801b14156040518060400160405280600b81526020016a0dcde40a4828840d0c2e6d60ab1b815250610e4a565b61172761307d565b6001600160a01b0316632ebf5d5c82600501546040518263ffffffff1660e01b815260040161175891815260200190565b600060405180830381865afa158015611775573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116d29190810190614a23565b6117a561294d565b6117af6000612d7f565b565b60606115867f50726963652d0000000000000000000000000000000000000000000000000000613101565b6117af6131a5565b6117ec61294d565b6118db7f0000000000000000000000000000000000000000000000000000000000000004601381111561182157611821613ccc565b61182961307d565b6001600160a01b0316634c729104846040518263ffffffff1660e01b815260040161185691815260200190565b602060405180830381865afa158015611873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118979190614a66565b60138111156118a8576118a8613ccc565b146040518060400160405280601481526020017362616420726573756c742064617461207479706560601b815250610e4a565b6040516384292f0760e01b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906384292f079061191690869086908690600401614a81565b60006040518083038186803b15801561192e57600080fd5b505af492505050801561193f575060015b6119b35761194b61472f565b806308c379a003611979575061195f61474a565b8061196a575061197b565b61197381610e5c565b50505050565b505b3d8080156119a5576040519150601f19603f3d011682016040523d82523d6000602084013e6119aa565b606091505b5061197361297a565b505050565b6119c061294d565b604051630435601f60e51b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc906386ac03e0906119f99085908590600401614aa5565b60006040518083038186803b158015611a1157600080fd5b505af4925050508015611a22575060015b610e5857611a2e61472f565b806308c379a003611a565750611a4261474a565b80611a4d5750611a58565b6119b381610e5c565b505b3d808015611a82576040519150601f19603f3d011682016040523d82523d6000602084013e611a87565b606091505b506119b361297a565b60607f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663c2581348611aca8461158b565b6040518263ffffffff1660e01b8152600401611ae891815260200190565b600060405180830381865afa158015611b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614a23565b60008051602061551d8339815191525460009015611c0857611ba67fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff600101600081548110611b7e57611b7e614ab9565b90600052602060002090600891828204019190066004029054906101000a900460e01b613220565b905060015b60008051602061551d83398151915254811015611c0657611bfa7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001018281548110611b7e57611b7e614ab9565b90911890600101611bab565b505b90565b611c1361294d565b611c56611c2d611c2836849003840184614afa565b6132aa565b6040518060400160405280600b81526020016a696e76616c696420534c4160a81b815250610e4a565b8060036119b38282614b65565b6000611c6d61294d565b604051632956d1c760e21b815273eda862f66cd1708bb77d4ec2029ce8afbffa11fc9063a55b471c90611caa908890889088908890600401614bfd565b602060405180830381865af4925050508015611ce3575060408051601f3d908101601f19168201909252611ce091810190614c2f565b60015b611d5757611cef61472f565b806308c379a003611d1d5750611d0361474a565b80611d0e5750611d1f565b611d1781610e5c565b50611da1565b505b3d808015611d49576040519150601f19603f3d011682016040523d82523d6000602084013e611d4e565b606091505b50611d1761297a565b7f18678abae9a91a452648053bebd7d23122fb9204cddc206fa8193750abb8940f81826001600160a01b03163f8686604051611d969493929190614c4c565b60405180910390a190505b949350505050565b604080516080810190915260035461ffff1681526000906116d2908490602080820190611dd890870187614c7e565b60ff168152602090810190611df39060408801908801614c9b565b6001600160401b031681526000602090910152612ae5565b611e1361294d565b6119b38383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e56573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093291906148f1565b80516020820120600090610ef7565b611e9161294d565b6004805461ffff191661ffff92909216919091179055565b6000610ef782611498565b611ebc613759565b604051630f92ac1760e21b81526001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771660048201526001600160e01b03198316602482015273eda862f66cd1708bb77d4ec2029ce8afbffa11fc90633e4ab05c90604401608060405180830381865af4925050508015611f60575060408051601f3d908101601f19168201909252611f5d91810190614ce0565b60015b610ef757611f6c61472f565b806308c379a003611f9a5750611f8061474a565b80611f8b5750611f9c565b611f9481610e5c565b50919050565b505b3d808015611fc6576040519150601f19603f3d011682016040523d82523d6000602084013e611fcb565b606091505b50611f9461297a565b919050565b6000612024611fe9836003613312565b6040518060400160405280601781526020017f756e736563757265207570646174652072657175657374000000000000000000815250610e4a565b6116d28361203736859003850185614afa565b612ae5565b60008061207e84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e7a92505050565b90506001600160e01b0319811661212561209783610e10565b80546120a290614d3a565b80601f01602080910402602001604051908101604052809291908181526020018280546120ce90614d3a565b801561211b5780601f106120f05761010080835404028352916020019161211b565b820191906000526020600020905b8154815290600101906020018083116120fe57829003601f168201915b5050505050611e7a565b6001600160e01b03191614949350505050565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082015260a08101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663f61921b26121c27f00000000000000000000000077703ae126b971c9946d562f41dd47071da007778561289c565b6040518263ffffffff1660e01b81526004016121e091815260200190565b600060405180830381865afa1580156121fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614d6e565b6040805160c0810182526000808252602082018190529181018290526060808201839052608082015260a08101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663f61921b26121c28461158b565b61229661294d565b73eda862f66cd1708bb77d4ec2029ce8afbffa11fc63e1c9e3c06040518163ffffffff1660e01b815260040160006040518083038186803b1580156122da57600080fd5b505af49250505080156122eb575060015b6117af576122f761472f565b806308c379a003612322575061230b61474a565b806123165750612324565b61231f81610e5c565b50565b505b3d80801561234e576040519150601f19603f3d011682016040523d82523d6000602084013e612353565b606091505b5061231f61297a565b60006115866001546001600160a01b031690565b6000610ef77f00000000000000000000000077703ae126b971c9946d562f41dd47071da00777836133d0565b60606123a782610e10565b80546123b290614d3a565b80601f01602080910402602001604051908101604052809291908181526020018280546123de90614d3a565b801561242b5780601f106124005761010080835404028352916020019161242b565b820191906000526020600020905b81548152906001019060200180831161240e57829003601f168201915b50505050509050919050565b60007f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663234fe6e36124718461158b565b6040518263ffffffff1660e01b815260040161248f91815260200190565b602060405180830381865afa1580156124ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef79190614e2e565b6124d861294d565b61231f81613463565b6125566040805160a08101909152806000815260200160008152600060208201819052604082015260600161377c604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b7f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03166359209b3961258e8461158b565b6040518263ffffffff1660e01b81526004016125ac91815260200190565b600060405180830381865afa1580156125c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef79190810190614e5f565b60008060008061260085611eb4565b805160208201519192506001600160401b03169060028360600151600381111561262c5761262c613ccc565b1461265e5760018360600151600381111561264957612649613ccc565b1461265657610190612661565b610194612661565b60c85b91955063ffffffff16935061ffff169150509193909250565b6060816001600160401b0381111561269457612694613a6f565b6040519080825280602002602001820160405280156126cd57816020015b6126ba613759565b8152602001906001900390816126b25790505b50905060005b8281101561272a576127058484838181106126f0576126f0614ab9565b9050602002016020810190610b3f91906137c5565b82828151811061271757612717614ab9565b60209081029190910101526001016126d3565b5092915050565b61273961294d565b6111138585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161276c929190615019565b6020604051808303816000875af1158015611e56573d6000803e3d6000fd5b606061279561307d565b6001600160a01b03166377c112596127ac846113c8565b6040518263ffffffff1660e01b81526004016127ca91815260200190565b600060405180830381865afa1580156127e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ef791908101906151a5565b6040516001628a76f160e01b0319815260009073eda862f66cd1708bb77d4ec2029ce8afbffa11fc9063ff75890f90612852908890889088908890600401614bfd565b602060405180830381865af415801561286f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128939190614c2f565b95945050505050565b60006128a782610e10565b60040154905080158061293457506000604051634cddf61560e01b8152600481018390526001600160a01b03851690634cddf61590602401602060405180830381865afa1580156128fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612920919061533f565b60ff81111561293157612931613ccc565b14155b15610ef75761294282610e10565b600301549392505050565b6000546001600160a01b031633146117af5760405163118cdaa760e01b8152336004820152602401610ec2565b6117af612985613495565b610e5c565b6000606061299783610e10565b600601546001600160a01b0316915060006129b1846134e8565b905080516001600160401b038111156129cc576129cc613a6f565b6040519080825280602002602001820160405280156129ff57816020015b60608152602001906001900390816129ea5790505b50915060005b8151811015612ade57612a30828281518110612a2357612a23614ab9565b6020026020010151610e10565b8054612a3b90614d3a565b80601f0160208091040260200160405190810160405280929190818152602001828054612a6790614d3a565b8015612ab45780601f10612a8957610100808354040283529160200191612ab4565b820191906000526020600020905b815481529060010190602001808311612a9757829003601f168201915b5050505050838281518110612acb57612acb614ab9565b6020908102919091010152600101612a05565b5050915091565b6000612af083610e10565b6005015415612ca357604051630a5581f560e11b8152349073eda862f66cd1708bb77d4ec2029ce8afbffa11fc906314ab03ea90612b58907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007779088908890879060040161535a565b6040805180830381865af4925050508015612b90575060408051601f3d908101601f19168201909252612b8d91810190615396565b60015b612c0457612b9c61472f565b806308c379a003612bca5750612bb061474a565b80612bbb5750612bcc565b612bc481610e5c565b50612c9d565b505b3d808015612bf6576040519150601f19603f3d011682016040523d82523d6000602084013e612bfb565b606091505b50612bc461297a565b34811015612c4457336108fc612c1a83346153ba565b6040518115909202916000818181858888f19350505050158015612c42573d6000803e3d6000fd5b505b604080513281523360208201526001600160e01b03198816818301526060810184905290517f0bd652a116bb5006c2e07594e8a3fe9b5ba51acf6cd9572568913fda51ad26c49181900360800190a19250610ef7915050565b50610ef7565b6000612cae84610e10565b600601546001600160a01b031614612d525760405163148a3a1160e11b81526001600160e01b031984166004820152612d4b9073eda862f66cd1708bb77d4ec2029ce8afbffa11fc90632914742290602401600060405180830381865af4158015612d1d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d4591908101906153cd565b836135d2565b9050610ef7565b610ef76040518060400160405280600c81526020016b1d5b9adb9bdddb881999595960a21b815250610e5c565b600180546001600160a01b031916905561231f81613697565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54612e08576040805160808101825260108152600a60208201819052630bebc200928201929092526000606090910152670bebc200000a00106003556004805461ffff19169091179055612f44565b805115612ead5760008082806020019051810190612e269190615401565b6004805461ffff191661ffff9384161790558051600380546020840151604085015160609586015194871663ffffffff19909316929092176201000091909616029490941763ffffffff166401000000006001600160401b03909516949094026bffffffffffffffffffffffff1693909317600160601b9190921c0217905550612f449050565b6040805160808101825260035461ffff808216835262010000820416602083015264010000000081046001600160401b031692820192909252600160601b909104606090811b6001600160601b03191690820152612f0a906132aa565b612f44576040805160808101825260108152600a6020820152630bebc200918101919091526000606090910152670bebc200000a00106003555b60005b60008051602061551d83398151915254811015610e585760007fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001018281548110612f9557612f95614ab9565b60009182526020822060088204015460079091166004026101000a900460e01b9150612fc082610e10565b6000600382018190556004909101555050600101612f47565b60606000612fe6836136e7565b6001600160401b03811115612ffd57612ffd613a6f565b6040519080825280601f01601f191660200182016040528015613027576020820181803683370190505b50905060005b815181101561272a5783816020811061304857613048614ab9565b1a60f81b82828151811061305e5761305e614ab9565b60200101906001600160f81b031916908160001a90535060010161302d565b60007f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115869190614c2f565b6060600061310e83613720565b6001600160401b0381111561312557613125613a6f565b6040519080825280601f01601f19166020018201604052801561314f576020820181803683370190505b50905060005b815181101561272a5783816020811061317057613170614ab9565b1a60f81b82828151811061318657613186614ab9565b60200101906001600160f81b031916908160001a905350600101613155565b33806131af61235c565b6001600160a01b0316146132175760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610ec2565b61231f81612d7f565b60008061322c83610e10565b600501541461327c578161323f83610e10565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b8161328683610e10565b60080154604080516001600160e01b0319909316602084015282015260600161325f565b805160009061ffff16158015906132ce5750600082604001516001600160401b0316115b80156132e257506000826020015161ffff16115b8015610ef7575060608201516001600160601b031916151580610ef757505060200151607f61ffff909116111590565b8054600090600160601b9004606090811b6001600160601b0319169061333e9060808601908601615495565b6001600160601b0319161480156133735750815462010000900461ffff1661336c6040850160208601613f41565b61ffff1610155b80156133a95750815464010000000090046001600160401b031661339d6060850160408601614c9b565b6001600160401b031610155b80156116d25750815461ffff166133c36020850185613f41565b61ffff1611159392505050565b6000806133dc83610e10565b600401549050801561345957604051634cddf61560e01b8152600481018290526001600160a01b03851690634cddf61590602401602060405180830381865afa15801561342d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613451919061533f565b915050610ef7565b6000915050610ef7565b61346b61294d565b6001600160a01b03811661321757604051631e4fbdf760e01b815260006004820152602401610ec2565b6060604051806040016040526014815280602001732bb4ba283934b1b2a332b2b239a230ba30a634b160611b8152506040516020016134d491906154b2565b604051602081830303815290604052905090565b6001600160e01b0319811660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602090815260409182902060089081015483518281526101208101909452606093909290919082016101008036833701905050915060005b60088110156135ca578183828151811061356d5761356d614ab9565b60200260200101906001600160e01b03191690816001600160e01b031916815250508281815181106135a1576135a1614ab9565b60209081029190910101516001600160e01b031916156135ca57602082901b9150600101613551565b825250919050565b6000808351346135e29190614921565b905060005b845181101561368f57306001600160a01b031663c459d3ea8387848151811061361257613612614ab9565b6020026020010151876040518463ffffffff1660e01b81526004016136389291906154eb565b60206040518083038185885af1158015613656573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061367b91906148f1565b6136859084615509565b92506001016135e7565b505092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b6020811015611fd45781816020811061370557613705614ab9565b1a60f81b6001600160f81b03191615611fd4576001016136ea565b60005b6020811015611fd45781816020811061373e5761373e614ab9565b1a60f81b6001600160f81b03191615611fd457600101613723565b604080516080810182526000808252602082018190529181018290529060608201905b905290565b6001600160c01b0319813581811691600885101561368f5760089490940360031b84901b1690921692915050565b6001600160e01b03198116811461231f57600080fd5b6000602082840312156137d757600080fd5b81356116d2816137af565b60005b838110156137fd5781810151838201526020016137e5565b50506000910152565b6000815180845261381e8160208601602086016137e2565b601f01601f19169290920160200192915050565b60008282518085526020808601955060208260051b8401016020860160005b8481101561387f57601f1986840301895261386d838351613806565b98840198925090830190600101613851565b5090979650505050505050565b606080825284519082018190526000906020906080840190828801845b828110156138cf5781516001600160e01b031916845292840192908401906001016138a9565b505050838103828501526138e38187613832565b8481036040860152855180825283870192509083019060005b81811015613918578351835292840192918401916001016138fc565b509098975050505050505050565b60008083601f84011261393857600080fd5b5081356001600160401b0381111561394f57600080fd5b60208301915083602082850101111561396757600080fd5b9250929050565b6001600160a01b038116811461231f57600080fd5b60008083601f84011261399557600080fd5b5081356001600160401b038111156139ac57600080fd5b6020830191508360208260051b850101111561396757600080fd5b6000806000806000606086880312156139df57600080fd5b85356001600160401b03808211156139f657600080fd5b613a0289838a01613926565b909750955060208801359150613a178261396e565b90935060408701359080821115613a2d57600080fd5b50613a3a88828901613983565b969995985093965092949392505050565b6001600160a01b0383168152604060208201819052600090611da190830184613832565b634e487b7160e01b600052604160045260246000fd5b604081018181106001600160401b0382111715613aa457613aa4613a6f565b60405250565b60a081018181106001600160401b0382111715613aa457613aa4613a6f565b608081018181106001600160401b0382111715613aa457613aa4613a6f565b60c081018181106001600160401b0382111715613aa457613aa4613a6f565b601f8201601f191681016001600160401b0381118282101715613b2c57613b2c613a6f565b6040525050565b60405160e081016001600160401b0381118282101715613b5557613b55613a6f565b60405290565b60006001600160401b03821115613b7457613b74613a6f565b50601f01601f191660200190565b6000613b8d83613b5b565b604051613b9a8282613b07565b809250848152858585011115613baf57600080fd5b8484602083013760006020868301015250509392505050565b600060208284031215613bda57600080fd5b81356001600160401b03811115613bf057600080fd5b8201601f81018413613c0157600080fd5b611da184823560208401613b82565b6020815260ff825116602082015260006020830151604080840152611da16060840182613806565b6020815260006116d26020830184613806565b600060208284031215613c5d57600080fd5b5035919050565b6020815260018060a01b03825116602082015262ffffff602083015116604082015268ffffffffffffffffff60408301511660608201526000606083015160a06080840152613cb660c0840182613806565b9050608084015160a08401528091505092915050565b634e487b7160e01b600052602160045260246000fd5b60148110613cf257613cf2613ccc565b9052565b60208101610ef78284613ce2565b600060208284031215613d1657600080fd5b81356116d28161396e565b61ffff808251168352806020830151166020840152506001600160401b0360408201511660408301526bffffffffffffffffffffffff1960608201511660608301525050565b60808101610ef78284613d21565b600080600060408486031215613d8a57600080fd5b83356001600160401b03811115613da057600080fd5b613dac86828701613926565b909790965060209590950135949350505050565b60008060208385031215613dd357600080fd5b82356001600160401b03811115613de957600080fd5b613df585828601613926565b90969095509350505050565b600060808284031215611f9457600080fd5b600060808284031215613e2557600080fd5b6116d28383613e01565b60008060008060408587031215613e4557600080fd5b84356001600160401b0380821115613e5c57600080fd5b613e6888838901613926565b90965094506020870135915080821115613e8157600080fd5b50613e8e87828801613926565b95989497509550505050565b6000808284036060811215613eae57600080fd5b8335613eb9816137af565b92506040601f1982011215613ecd57600080fd5b506020830190509250929050565b600080600060408486031215613ef057600080fd5b83356001600160401b03811115613f0657600080fd5b613f1286828701613926565b9094509250506020840135613f268161396e565b809150509250925092565b61ffff8116811461231f57600080fd5b600060208284031215613f5357600080fd5b81356116d281613f31565b6001600160401b03815116825263ffffffff602082015116602083015260408101516040830152606081015160048110613f9a57613f9a613ccc565b806060840152505050565b60808101610ef78284613f5e565b60008060a08385031215613fc657600080fd5b8235613fd1816137af565b9150613fe08460208501613e01565b90509250929050565b60208152600060018060a01b038084511660208401526001600160401b03602085015116604084015263ffffffff604085015116606084015260608401516080840152608084015160c060a085015261404560e0850182613806565b90508160a08601511660c0850152809250505092915050565b6101008110613cf257613cf2613ccc565b60208101610ef7828461405e565b602081016007831061409157614091613ccc565b91905290565b602081526140a960208201835161405e565b600060208301516140bd6040840182613ce2565b506040830151606083015263ffffffff6060840151166080830152608083015160a080840152805160c080850152805160406101808601526141036101c0860182613806565b6020928301516101a08701529183015160ff1660e08601525060408201519061413261010086018360ff169052565b606083015160ff1661012086015260808301516001600160401b0380821661014088015260a0909401519384166101608701529150612893565b6000806020838503121561417f57600080fd5b82356001600160401b0381111561419557600080fd5b613df585828601613983565b6020808252825182820181905260009190848201906040850190845b818110156141e3576141d0838551613f5e565b92840192608092909201916001016141bd565b50909695505050505050565b60058110613cf257613cf2613ccc565b600082825180855260208086019550808260051b8401018186016000805b8581101561427757868403601f19018a5282518460408101845b6002811015614262578782038352614250828551613806565b93890193928901929150600101614237565b509b87019b955050509184019160010161421d565b509198975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561391857603f19898403018552815160e060ff8251168552888201516142da8a8701826141ef565b50878201516142eb89870182613ce2565b50606080830151828288015261430383880182613806565b925050506080808301518683038288015261431e8382613806565b9250505060a0808301518683038288015261433983826141ff565b9250505060c080830151925085820381870152506143578183613806565b9689019694505050908601906001016142ae565b6000835161437d8184602088016137e2565b6101d160f51b908301908152835161439c8160028401602088016137e2565b01600201949350505050565b60006001600160401b038211156143c1576143c1613a6f565b5060051b60200190565b600082601f8301126143dc57600080fd5b815160206143e9826143a8565b6040516143f68282613b07565b80915083815260208101915060208460051b87010193508684111561441a57600080fd5b602086015b8481101561443f578051614432816137af565b835291830191830161441f565b509695505050505050565b600082601f83011261445b57600080fd5b815161446681613b5b565b6040516144738282613b07565b82815285602084870101111561448857600080fd5b6128938360208301602088016137e2565b600082601f8301126144aa57600080fd5b815160206144b7826143a8565b6040516144c48282613b07565b80915083815260208101915060208460051b8701019350868411156144e857600080fd5b602086015b8481101561443f57805183529183019183016144ed565b60008060006060848603121561451957600080fd5b83516001600160401b038082111561453057600080fd5b61453c878388016143cb565b945060209150818601518181111561455357600080fd5b8601601f8101881361456457600080fd5b805161456f816143a8565b60405161457c8282613b07565b82815260059290921b830185019185810191508a83111561459c57600080fd5b8584015b838110156145d4578051868111156145b85760008081fd5b6145c68d898389010161444a565b8452509186019186016145a0565b5060408a01519097509450505050808211156145ef57600080fd5b506145fc86828701614499565b9150509250925092565b6001600160d01b0319813581811691600685101561368f5760069490940360031b84901b1690921692915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e1984360301811261467457600080fd5b83016020810192503590506001600160401b0381111561469357600080fd5b80360382131561396757600080fd5b6060815260006146b6606083018789614634565b6001600160a01b0386166020848101919091528382036040850152848252818101600586901b830182018760005b8881101561471e57858303601f190184526146ff828b61465d565b61470a858284614634565b9587019594505050908401906001016146e4565b50909b9a5050505050505050505050565b600060033d1115611c085760046000803e5060005160e01c90565b600060443d10156147585790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561478757505050505090565b828501915081518181111561479f5750505050505090565b843d87010160208285010111156147b95750505050505090565b6147c860208286010187613b07565b509095945050505050565b600080604083850312156147e657600080fd5b82516147f18161396e565b60208401519092506001600160401b0381111561480d57600080fd5b6148198582860161444a565b9150509250929050565b60ff8116811461231f57600080fd5b8051611fd481614823565b60006020828403121561484f57600080fd5b81516001600160401b038082111561486657600080fd5b908301906040828603121561487a57600080fd5b60405161488681613a85565b825161489181614823565b81526020830151828111156148a557600080fd5b6148b18782860161444a565b60208301525095945050505050565b634e487b7160e01b600052601160045260246000fd5b61ffff81811683821601908082111561272a5761272a6148c0565b60006020828403121561490357600080fd5b5051919050565b8082028115828204841417610ef757610ef76148c0565b60008261493e57634e487b7160e01b600052601260045260246000fd5b500490565b8051611fd48161396e565b805168ffffffffffffffffff81168114611fd457600080fd5b60006020828403121561497957600080fd5b81516001600160401b038082111561499057600080fd5b9083019060a082860312156149a457600080fd5b6040516149b081613aaa565b82516149bb8161396e565b8152602083015162ffffff811681146149d357600080fd5b60208201526149e46040840161494e565b60408201526060830151828111156149fb57600080fd5b614a078782860161444a565b6060830152506080830151608082015280935050505092915050565b600060208284031215614a3557600080fd5b81516001600160401b03811115614a4b57600080fd5b611da18482850161444a565b805160148110611fd457600080fd5b600060208284031215614a7857600080fd5b6116d282614a57565b604081526000614a95604083018587614634565b9050826020830152949350505050565b602081526000611da1602083018486614634565b634e487b7160e01b600052603260045260246000fd5b6001600160401b038116811461231f57600080fd5b6001600160601b03198116811461231f57600080fd5b600060808284031215614b0c57600080fd5b604051614b1881613ac9565b8235614b2381613f31565b81526020830135614b3381613f31565b60208201526040830135614b4681614acf565b60408201526060830135614b5981614ae4565b60608201529392505050565b8135614b7081613f31565b61ffff8116905081548161ffff1982161783556020840135614b9181613f31565b63ffff00008160101b169050808363ffffffff198416171784556040850135614bb981614acf565b6bffffffffffffffff0000000060209190911b166001600160601b03199283168417821781178555606086013592614bf084614ae4565b9290921692171717905550565b604081526000614c11604083018688614634565b8281036020840152614c24818587614634565b979650505050505050565b600060208284031215614c4157600080fd5b81516116d28161396e565b60018060a01b0385168152836020820152606060408201526000614c74606083018486614634565b9695505050505050565b600060208284031215614c9057600080fd5b81356116d281614823565b600060208284031215614cad57600080fd5b81356116d281614acf565b8051611fd481614acf565b63ffffffff8116811461231f57600080fd5b8051611fd481614cc3565b600060808284031215614cf257600080fd5b604051614cfe81613ac9565b8251614d0981614acf565b81526020830151614d1981614cc3565b602082015260408381015190820152606083015160048110614b5957600080fd5b600181811c90821680614d4e57607f821691505b602082108103611f9457634e487b7160e01b600052602260045260246000fd5b600060208284031215614d8057600080fd5b81516001600160401b0380821115614d9757600080fd5b9083019060c08286031215614dab57600080fd5b604051614db781613ae8565b8251614dc28161396e565b8152614dd060208401614cb8565b6020820152614de160408401614cd5565b604082015260608301516060820152608083015182811115614e0257600080fd5b614e0e8782860161444a565b608083015250614e2060a08401614943565b60a082015295945050505050565b600060208284031215614e4057600080fd5b8151600781106116d257600080fd5b80516101008110611fd457600080fd5b60006020808385031215614e7257600080fd5b82516001600160401b0380821115614e8957600080fd5b9084019060a08287031215614e9d57600080fd5b60408051614eaa81613aaa565b614eb384614e4f565b8152614ec0858501614a57565b8582015281840151828201526060840151614eda81614cc3565b6060820152608084015183811115614ef157600080fd5b939093019260c08489031215614f0657600080fd5b8151614f1181613ae8565b845184811115614f2057600080fd5b8501808a03841315614f3157600080fd5b8351614f3c81613a85565b815186811115614f4b57600080fd5b614f578c82850161444a565b82525090870151878201528152614f6f858701614832565b86820152614f7e838601614832565b83820152614f8e60608601614832565b6060820152614f9f60808601614cb8565b6080820152614fb060a08601614cb8565b60a08201526080820152979650505050505050565b6000838385526020808601955060208560051b8301018460005b8781101561387f57848303601f19018952614ffa828861465d565b615005858284614634565b9a86019a9450505090830190600101614fdf565b6020808252818101839052600090600560408085019086831b86010187855b8881101561391857878303603f190184528135368b9003601e1901811261505e57600080fd5b8a0186810190356001600160401b0381111561507957600080fd5b80871b360382131561508a57600080fd5b615095858284614fc5565b958801959450505090850190600101615038565b805160058110611fd457600080fd5b600082601f8301126150c957600080fd5b815160206150d6826143a8565b6040516150e38282613b07565b83815260059390931b850182019282810191508684111561510357600080fd5b8286015b8481101561443f5780516001600160401b03808211156151275760008081fd5b818901915089603f83011261513c5760008081fd5b60405161514881613a85565b80606084018c81111561515b5760008081fd5b8885015b81811015615193578051858111156151775760008081fd5b6151858f8c838a010161444a565b84525091890191890161515f565b50505085525050918301918301615107565b600060208083850312156151b857600080fd5b82516001600160401b03808211156151cf57600080fd5b818501915085601f8301126151e357600080fd5b81516151ee816143a8565b6040516151fb8282613b07565b82815260059290921b840185019185810191508883111561521b57600080fd5b8585015b838110156153325780518581111561523657600080fd5b860160e0818c03601f1901121561524d5760008081fd5b615255613b33565b615260898301614832565b815261526e604083016150a9565b89820152606061527f818401614a57565b6040830152608080840151898111156152985760008081fd5b6152a68f8d8388010161444a565b838501525060a0915081840151898111156152c15760008081fd5b6152cf8f8d8388010161444a565b82850152505060c080840151898111156152e95760008081fd5b6152f78f8d838801016150b8565b838501525060e08401519150888211156153115760008081fd5b61531f8e8c8487010161444a565b908301525084525091860191860161521f565b5098975050505050505050565b60006020828403121561535157600080fd5b6116d282614e4f565b6001600160a01b03851681526001600160e01b03198416602082015260e081016153876040830185613d21565b8260c083015295945050505050565b600080604083850312156153a957600080fd5b505080516020909101519092909150565b81810381811115610ef757610ef76148c0565b6000602082840312156153df57600080fd5b81516001600160401b038111156153f557600080fd5b611da1848285016143cb565b60008082840360a081121561541557600080fd5b835161542081613f31565b92506080601f198201121561543457600080fd5b5060405161544181613ac9565b602084015161544f81613f31565b8152604084015161545f81613f31565b6020820152606084015161547281614acf565b6040820152608084015161548581614ae4565b6060820152919491935090915050565b6000602082840312156154a757600080fd5b81356116d281614ae4565b600082516154c48184602087016137e2565b741d103ab73430b7323632b21030b9b9b2b93a34b7b760591b920191825250601501919050565b6001600160e01b03198316815260a081016116d26020830184613d21565b80820180821115610ef757610ef76148c056fee36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200a2646970667358221220b07503a885f5cf3c4e918dc36833de8a95ccc0bd3eaa418aa12e07ea294b055e64736f6c63430008190033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000077703ae126b971c9946d562f41dd47071da00777322e312e302d346535346132652d6637353361616400000000000000000000000000000000000000000000000000000000000000000000000000000000000001

-----Decoded View---------------
Arg [0] : _witOracle (address): 0x77703aE126B971c9946d562F41Dd47071dA00777
Arg [1] : _versionTag (bytes32): 0x322e312e302d346535346132652d663735336161640000000000000000000000
Arg [2] : _upgradable (bool): True

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000077703ae126b971c9946d562f41dd47071da00777
Arg [1] : 322e312e302d346535346132652d663735336161640000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.