Source Code
Overview
POL Balance
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14127645 | 138 days ago | Contract Creation | 0 POL |
Loading...
Loading
This contract contains unverified libraries: WitPriceFeedsLib
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
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)
// 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(); } }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/ReentrancyGuard.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 } } }
// 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); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol";
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.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); } } }
// 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)) } } } } }
// 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 ++; } } } }
// 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; } }
// 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); }
// 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; }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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 ); }
// 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); }
// 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); }
// 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; }
// 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); }
// 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 ); }
// 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; }
// 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); }
// 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 )) ); } }
// 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 ) ); } }
// 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 ++; } } } }
// 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 } } }
// 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 ); } }
// 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 {}
// 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 {}
// 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 {}
// 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 ); } }
// 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 ); } }
// 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); } }
// 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); }
// 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); }
// 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; } }
// 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; } }
// 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; } }
// 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); } }
// 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 } } }
{ "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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
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.