Source Code
Overview
DEV Balance
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
11755227 | 1 min ago | 0 DEV | ||||
11754685 | 55 mins ago | 0 DEV | ||||
11754673 | 56 mins ago | 0 DEV | ||||
11754508 | 1 hr ago | 0 DEV | ||||
11754492 | 1 hr ago | 0 DEV | ||||
11754410 | 1 hr ago | 0 DEV | ||||
11753218 | 3 hrs ago | 0 DEV | ||||
11752889 | 3 hrs ago | 0 DEV | ||||
11752401 | 4 hrs ago | 0 DEV | ||||
11751737 | 5 hrs ago | 0 DEV | ||||
11751661 | 5 hrs ago | 0 DEV | ||||
11749980 | 8 hrs ago | 0 DEV | ||||
11749306 | 9 hrs ago | 0 DEV | ||||
11749290 | 9 hrs ago | 0 DEV | ||||
11749248 | 10 hrs ago | 0 DEV | ||||
11748310 | 11 hrs ago | 0 DEV | ||||
11747726 | 12 hrs ago | 0 DEV | ||||
11747507 | 12 hrs ago | 0 DEV | ||||
11747464 | 12 hrs ago | 0 DEV | ||||
11747030 | 13 hrs ago | 0 DEV | ||||
11747016 | 13 hrs ago | 0 DEV | ||||
11746066 | 15 hrs ago | 0 DEV | ||||
11745332 | 16 hrs ago | 0 DEV | ||||
11745316 | 16 hrs ago | 0 DEV | ||||
11745027 | 17 hrs ago | 0 DEV |
Loading...
Loading
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:
WitnetRequestBytecodesDefault
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4 <0.9.0; import "../WitnetUpgradableBase.sol"; import "../../WitnetRequestBytecodes.sol"; import "../../data/WitnetRequestBytecodesData.sol"; import "../../libs/WitnetEncodingLib.sol"; /// @title Witnet Request Board EVM-default implementation contract. /// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. /// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. /// The result of the requests will be posted back to this contract by the bridge nodes too. /// @author The Witnet Foundation contract WitnetRequestBytecodesDefault is WitnetRequestBytecodes, WitnetRequestBytecodesData, WitnetUpgradableBase { using Witnet for bytes; using Witnet for string; using WitnetV2 for WitnetV2.RadonSLA; using WitnetEncodingLib for Witnet.RadonDataRequestMethods; using WitnetEncodingLib for Witnet.RadonRetrieval; using WitnetEncodingLib for Witnet.RadonRetrieval[]; using WitnetEncodingLib for Witnet.RadonReducer; using WitnetEncodingLib for Witnet.RadonSLA; using WitnetEncodingLib for Witnet.RadonDataTypes; function class() public view virtual override(WitnetRequestBytecodes, WitnetUpgradableBase) returns (string memory) { return type(WitnetRequestBytecodesDefault).name; } bytes4 public immutable override specs = type(IWitnetRequestBytecodes).interfaceId; constructor(bool _upgradable, bytes32 _versionTag) Ownable(address(msg.sender)) WitnetUpgradableBase( _upgradable, _versionTag, "io.witnet.proxiable.bytecodes" ) {} receive() external payable { revert("WitnetRequestBytecodes: no transfers"); } // ================================================================================================================ // --- Overrides 'Ownable2Step' ----------------------------------------------------------------------------------- /// Returns the address of the pending owner. function pendingOwner() public view virtual override returns (address) { return __bytecodes().pendingOwner; } /// Returns the address of the current owner. function owner() public view virtual override returns (address) { return __bytecodes().owner; } /// Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. /// @dev Can only be called by the current owner. function transferOwnership(address _newOwner) public virtual override onlyOwner { __bytecodes().pendingOwner = _newOwner; emit OwnershipTransferStarted(owner(), _newOwner); } /// @dev Transfers ownership of the contract to a new account (`_newOwner`) and deletes any pending owner. /// @dev Internal function without access restriction. function _transferOwnership(address _newOwner) internal virtual override { delete __bytecodes().pendingOwner; address _oldOwner = owner(); if (_newOwner != _oldOwner) { __bytecodes().owner = _newOwner; emit OwnershipTransferred(_oldOwner, _newOwner); } } // ================================================================================================================ // --- 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) public override { address _owner = __bytecodes().owner; if (_owner == address(0)) { // set owner from the one specified in _initData _owner = abi.decode(_initData, (address)); __bytecodes().owner = _owner; } else { // only owner can initialize: if (msg.sender != _owner) { revert("WitnetRequestBytecodes: not the owner"); } } if (__bytecodes().base != address(0)) { // current implementation cannot be initialized more than once: if(__bytecodes().base == base()) { revert("WitnetRequestBytecodes: already initialized"); } } __bytecodes().base = base(); emit Upgraded( _owner, base(), codehash(), version() ); } /// Tells whether provided address could eventually upgrade the contract. function isUpgradableFrom(address _from) external view override returns (bool) { address _owner = __bytecodes().owner; return ( // false if the WRB is intrinsically not upgradable, or `_from` is no owner isUpgradable() && _owner == _from ); } // ================================================================================================================ // --- Implementation of 'IWitnetRequestBytecodes' ----------------------------------------------------------------------- function bytecodeOf(bytes32 _radHash) public view override returns (bytes memory) { return __database().radsBytecode[_radHash]; } function bytecodeOf(bytes32 _radHash, WitnetV2.RadonSLA calldata _sla) override external view returns (bytes memory) { bytes memory _radBytecode = bytecodeOf(_radHash); return abi.encodePacked( WitnetEncodingLib.encode(uint64(_radBytecode.length), 0x0a), _radBytecode, _sla.toV1().encode() ); } function bytecodeOf(bytes calldata _radBytecode, WitnetV2.RadonSLA calldata _sla) override external pure returns (bytes memory) { return abi.encodePacked( WitnetEncodingLib.encode(uint64(_radBytecode.length), 0x0a), _radBytecode, _sla.toV1().encode() ); } function hashOf(bytes calldata _radBytecode) external pure override returns (bytes32) { // todo: validate correctness of _radBytecode return _witnetHash(_radBytecode); } function lookupDataProvider(uint256 _index) external view override returns (string memory, uint256) { return ( __database().providers[_index].authority, __database().providers[_index].totalEndpoints ); } function lookupDataProviderIndex(string calldata _authority) external view override returns (uint256) { return __database().providersIndex[keccak256(abi.encodePacked(_authority))]; } function lookupDataProviderSources( uint256 _index, uint256 _offset, uint256 _length ) external view returns (bytes32[] memory _endpoints) { DataProvider storage __provider = __database().providers[_index]; uint _totalEndpoints = __provider.totalEndpoints; if (_offset < _totalEndpoints){ if (_offset + _length > _totalEndpoints) { _length = _totalEndpoints - _offset; } _endpoints = new bytes32[](_length); for (uint _ix = 0; _ix < _endpoints.length; _ix ++) { _endpoints[_ix] = __provider.endpoints[_ix + _offset]; } } } function lookupRadonRetrieval(bytes32 _hash) external view override returns (Witnet.RadonRetrieval memory _source) { _source = __database().retrievals[_hash]; if (_source.method == Witnet.RadonDataRequestMethods.Unknown) { revert UnknownRadonRetrieval(_hash); } } function lookupRadonRetrievalArgsCount(bytes32 _hash) external view override returns (uint8) { if (__database().retrievals[_hash].method == Witnet.RadonDataRequestMethods.Unknown) { revert UnknownRadonRetrieval(_hash); } return __database().retrievals[_hash].argsCount; } function lookupRadonRetrievalResultDataType(bytes32 _hash) external view override returns (Witnet.RadonDataTypes) { if (__database().retrievals[_hash].method == Witnet.RadonDataRequestMethods.Unknown) { revert UnknownRadonRetrieval(_hash); } return __database().retrievals[_hash].resultDataType; } function lookupRadonReducer(bytes32 _hash) external view override returns (Witnet.RadonReducer memory _reducer) { _reducer = __database().reducers[_hash]; if (uint8(_reducer.opcode) == 0) { revert UnknownRadonReducer(_hash); } } function lookupRadonRequestAggregator(bytes32 _radHash) external view override returns (Witnet.RadonReducer memory) { return __database().reducers[ __requests(_radHash).aggregator ]; } function lookupRadonRequestResultDataType(bytes32 _radHash) external view override returns (Witnet.RadonDataTypes) { return __requests(_radHash).resultDataType; } function lookupRadonRequestResultMaxSize(bytes32 _radHash) external view override returns (uint16) { return uint16(__requests(_radHash).resultMaxSize); } function lookupRadonRequestSources(bytes32 _radHash) external view override returns (bytes32[] memory) { return __requests(_radHash).retrievals; } function lookupRadonRequestSourcesCount(bytes32 _radHash) external view override returns (uint) { return __requests(_radHash).retrievals.length; } function lookupRadonRequestTally(bytes32 _radHash) external view override returns (Witnet.RadonReducer memory) { return __database().reducers[ __requests(_radHash).tally ]; } function verifyRadonRetrieval( Witnet.RadonDataRequestMethods _requestMethod, string calldata _requestURL, string calldata _requestBody, string[2][] memory _requestHeaders, bytes calldata _requestRadonScript ) public virtual override returns (bytes32 hash) { // validate data source params hash = _requestMethod.validate( _requestURL, _requestBody, _requestHeaders, _requestRadonScript ); // should it be a new data source: if ( __database().retrievals[hash].method == Witnet.RadonDataRequestMethods.Unknown ) { // compose data source and save it in storage: __database().retrievals[hash] = Witnet.RadonRetrieval({ argsCount: WitnetBuffer.argsCountOf( abi.encode( _requestURL, bytes(" "), _requestBody, bytes(" "), _requestHeaders, bytes(" "), _requestRadonScript ) ), method: _requestMethod, resultDataType: WitnetEncodingLib.verifyRadonScriptResultDataType(_requestRadonScript), url: _requestURL, body: _requestBody, headers: _requestHeaders, script: _requestRadonScript }); emit NewRadonRetrievalHash(hash); } } function verifyRadonReducer(Witnet.RadonReducer memory _reducer) external returns (bytes32 hash) { hash = keccak256(abi.encode(_reducer)); Witnet.RadonReducer storage __reducer = __database().reducers[hash]; if ( uint8(__reducer.opcode) == 0 && __reducer.filters.length == 0 ) { _reducer.validate(); __reducer.opcode = _reducer.opcode; __pushRadonReducerFilters(__reducer, _reducer.filters); emit NewRadonReducerHash(hash); } } function verifyRadonRequest( bytes32[] memory _retrievalsIds, bytes32 _aggregatorId, bytes32 _tallyId, uint16 _resultMaxSize, string[][] memory _args ) external virtual override returns (bytes32 _radHash) { // calculate unique hash bytes32 hash = keccak256(abi.encode( _retrievalsIds, _aggregatorId, _tallyId, _resultMaxSize, _args )); _radHash = __database().rads[hash]; // verify, compose and register only if hash is not yet known: if (__database().rads[hash] == bytes32(0)) { // Check that at least one source is provided; if (_retrievalsIds.length == 0) { revert("WitnetRequestBytecodes: no retrievals"); } // Check that number of args arrays matches the number of sources: if ( _retrievalsIds.length != _args.length) { revert("WitnetRequestBytecodes: args mismatch"); } // Check sources and tally reducers: Witnet.RadonReducer memory _aggregator = __database().reducers[_aggregatorId]; Witnet.RadonReducer memory _tally = __database().reducers[_tallyId]; // Check result type consistency among all sources: Witnet.RadonDataTypes _resultDataType; Witnet.RadonRetrieval[] memory _retrievals = new Witnet.RadonRetrieval[](_retrievalsIds.length); for (uint _ix = 0; _ix < _retrievals.length; _ix ++) { _retrievals[_ix] = __database().retrievals[_retrievalsIds[_ix]]; // Check all sources return same Radon data type: if (_ix == 0) { _resultDataType = _retrievals[0].resultDataType; } else if (_retrievals[_ix].resultDataType != _resultDataType) { revert("WitnetRequestBytecodes: mismatching retrievals"); } // check enough args are provided for each source if (_args[_ix].length < uint(_retrievals[_ix].argsCount)) { revert("WitnetRequestBytecodes: missing args"); } } // Check provided result type and result max size: _resultMaxSize = _resultDataType.validate(_resultMaxSize); // Build radon retrieval bytecode: bytes memory _bytecode = _retrievals.encode( _args, _aggregator.encode(), _tally.encode(), _resultMaxSize ); if (_bytecode.length > 65535) { revert("WitnetRequestBytecodes: too heavy request"); } // Calculate radhash and add request metadata and rad bytecode to storage: _radHash = _witnetHash(_bytecode); __database().rads[hash] = _radHash; __database().radsBytecode[_radHash] = _bytecode; __database().requests[_radHash] = DataRequest({ aggregator: _aggregatorId, args: _args, radHash: _radHash, resultDataType: _resultDataType, resultMaxSize: _resultMaxSize, retrievals: _retrievalsIds, tally: _tallyId }); emit NewRadHash(_radHash); } } function totalDataProviders() external view override returns (uint) { return __bytecodes().totalDataProviders; } // ================================================================================================================ // --- Internal state-modifying methods --------------------------------------------------------------------------- function __pushDataProviderSource( string memory _authority, bytes32 _retrievalHash ) internal virtual returns (bytes32 _hash) { if ( bytes(_authority).length > 0 && WitnetBuffer.argsCountOf(bytes(_authority)) == 0 ) { _hash = keccak256(abi.encodePacked(_authority)); uint _index = __database().providersIndex[_hash]; if (_index == 0) { _index = ++ __bytecodes().totalDataProviders; __database().providersIndex[keccak256(bytes(_authority))] = _index; __database().providers[_index].authority = _authority; emit NewDataProvider(_index); } __database().providers[_index].endpoints[ __database().providers[_index].totalEndpoints ++ ] = _retrievalHash; } } function __pushRadonReducerFilters( Witnet.RadonReducer storage __reducer, Witnet.RadonFilter[] memory _filters ) internal virtual { for (uint _ix = 0; _ix < _filters.length; _ix ++) { __reducer.filters.push(_filters[_ix]); } } function _witnetHash(bytes memory chunk) virtual internal pure returns (bytes32) { return sha256(chunk); } }
// SPDX-License-Identifier: MIT /* solhint-disable var-name-mixedcase */ pragma solidity >=0.6.0 <0.9.0; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "./Initializable.sol"; import "./Proxiable.sol"; abstract contract Upgradeable is Initializable, Proxiable { address internal immutable _BASE; bytes32 internal immutable _CODEHASH; bool internal immutable _UPGRADABLE; modifier onlyDelegateCalls virtual { require( address(this) != _BASE, "Upgradeable: not a delegate call" ); _; } /// Emitted every time the contract gets upgraded. /// @param from The address who ordered the upgrading. Namely, the WRB operator in "trustable" implementations. /// @param baseAddr The address of the new implementation contract. /// @param baseCodehash The EVM-codehash of the new implementation contract. /// @param versionTag Ascii-encoded version literal with which the implementation deployer decided to tag it. event Upgraded( address indexed from, address indexed baseAddr, bytes32 indexed baseCodehash, string versionTag ); constructor (bool _isUpgradable) { address _base = address(this); _BASE = _base; _UPGRADABLE = _isUpgradable; } /// @dev Retrieves base contract. Differs from address(this) when called via delegate-proxy pattern. function base() public view returns (address) { return _BASE; } /// @dev Retrieves the immutable codehash of this contract, even if invoked as delegatecall. function codehash() public view returns (bytes32 _codehash) { address _base = _BASE; assembly { _codehash := extcodehash(_base) } } /// @dev Determines whether the logic of this contract is potentially upgradable. function isUpgradable() public view returns (bool) { return _UPGRADABLE; } /// @dev Tells whether provided address could eventually upgrade the contract. function isUpgradableFrom(address from) virtual external view returns (bool); /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. /// @dev Must fail when trying to upgrade to same logic contract more than once. function initialize(bytes memory) virtual external; /// @dev Retrieves human-redable named version of current implementation. function version() virtual public view returns (string memory); }
// 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 "./Witnet.sol"; library WitnetV2 { /// Struct containing both request and response data related to every query posted to the Witnet Request Board struct Query { Request request; Response response; } /// Possible status of a Witnet query. enum QueryStatus { Unknown, Posted, Reported, Finalized } /// Data kept in EVM-storage for every Request posted to the Witnet Request Board. struct Request { address requester; // EVM address from which the request was posted. uint24 gasCallback; // Max callback gas limit upon response, if a callback is required. uint72 evmReward; // EVM amount in wei eventually to be paid to the legit result reporter. bytes witnetBytecode; // Optional: Witnet Data Request bytecode to be solved by the Witnet blockchain. bytes32 witnetRAD; // Optional: Previously verified hash of the Witnet Data Request to be solved. WitnetV2.RadonSLA witnetSLA; // Minimum Service-Level parameters to be committed by the Witnet blockchain. } /// Response metadata and result as resolved by the Witnet blockchain. struct Response { address reporter; // EVM address from which the Data Request result was reported. uint64 finality; // EVM block number at which the reported data will be considered to be finalized. uint32 resultTimestamp; // Unix timestamp (seconds) at which the data request was resolved in the Witnet blockchain. bytes32 resultTallyHash; // 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. } /// Response status from a requester's point of view. enum ResponseStatus { Void, Awaiting, Ready, Error, Finalizing, Delivered } struct RadonSLA { /// @notice Number of nodes in the Witnet blockchain that will take part in solving the data request. uint8 committeeSize; /// @notice Fee in $nanoWIT paid to every node in the Witnet blockchain involved in solving the data request. /// @dev Witnet nodes participating as witnesses will have to stake as collateral 100x this amount. uint64 witnessingFeeNanoWit; } /// =============================================================================================================== /// --- 'WitnetV2.RadonSLA' helper methods ------------------------------------------------------------------------ function equalOrGreaterThan(RadonSLA memory a, RadonSLA memory b) internal pure returns (bool) { return (a.committeeSize >= b.committeeSize); } function isValid(RadonSLA calldata sla) internal pure returns (bool) { return ( sla.witnessingFeeNanoWit > 0 && sla.committeeSize > 0 && sla.committeeSize <= 127 // v1.7.x requires witnessing collateral to be greater or equal to 20 WIT: && sla.witnessingFeeNanoWit * 100 >= 20 * 10 ** 9 ); } function toV1(RadonSLA memory self) internal pure returns (Witnet.RadonSLA memory) { return Witnet.RadonSLA({ numWitnesses: self.committeeSize, minConsensusPercentage: 51, witnessReward: self.witnessingFeeNanoWit, witnessCollateral: self.witnessingFeeNanoWit * 100, minerCommitRevealFee: self.witnessingFeeNanoWit / self.committeeSize }); } function nanoWitTotalFee(RadonSLA storage self) internal view returns (uint64) { return self.witnessingFeeNanoWit * (self.committeeSize + 3); } /// =============================================================================================================== /// --- P-RNG generators ------------------------------------------------------------------------------------------ /// 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); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "./Witnet.sol"; /// @title A library for encoding Witnet Data Requests. /// @author The Witnet Foundation. library WitnetEncodingLib { using WitnetBuffer for WitnetBuffer.Buffer; using WitnetCBOR for WitnetCBOR.CBOR; using WitnetCBOR for WitnetCBOR.CBOR[]; bytes internal constant WITNET_RADON_OPCODES_RESULT_TYPES = hex"10ffffffffffffffffffffffffffffff040100010203050406071311ff0101ff07ff02ffffffffffffffffffffffffff070304ff04ffffffffffffff03ffffff0405070202ff0404040403ffffffffff05070402040205050505ff04ff04ffff07010203050406070101ff06ffff06ff0203050404000106060707070701ffff"; // 10ffffffffffffffffffffffffffffff // 040100001203050406070100ff0101ff // 07ff02ffffffffffffffffffffffffff // 070304ff04ffffffffffffff03ffffff // 0405070202ff0404040403ffffffffff // 05070402040205050505ff04ff04ffff // 07010203050406070101ff06ffff06ff // 0203050404000106060707070701ffff error UnsupportedDataRequestMethod(uint8 method, string schema, string body, string[2][] headers); error UnsupportedRadonDataType(uint8 datatype, uint256 maxlength); error UnsupportedRadonFilterOpcode(uint8 opcode); error UnsupportedRadonFilterArgs(uint8 opcode, bytes args); error UnsupportedRadonReducerOpcode(uint8 opcode); error UnsupportedRadonReducerScript(uint8 opcode, bytes script, uint256 offset); error UnsupportedRadonScript(bytes script, uint256 offset); error UnsupportedRadonScriptOpcode(bytes script, uint256 cursor, uint8 opcode); error UnsupportedRadonTallyScript(bytes32 hash); /// =============================================================================================================== /// --- WitnetEncodingLib internal methods -------------------------------------------------------------------------------- function size(Witnet.RadonDataTypes _type) internal pure returns (uint16) { if (_type == Witnet.RadonDataTypes.Integer || _type == Witnet.RadonDataTypes.Float ) { return 9; } else if (_type == Witnet.RadonDataTypes.Bool) { return 1; } else { // undetermined return 0; } } /// =============================================================================================================== /// --- WitnetEncodingLib public methods (if used library will have to linked to calling contracts) ----------------------- /// @notice Encode bytes array into given major type (UTF-8 not yet supported) /// @param buf Bytes array /// @return Marshaled bytes function encode(bytes memory buf, uint majorType) public pure returns (bytes memory) { uint len = buf.length; if (len < 23) { return abi.encodePacked( uint8((majorType << 5) | uint8(len)), buf ); } else { uint8 buf0 = uint8((majorType << 5)); bytes memory buf1; if (len <= 0xff) { buf0 |= 24; buf1 = abi.encodePacked(uint8(len)); } else if (len <= 0xffff) { buf0 |= 25; buf1 = abi.encodePacked(uint16(len)); } else if (len <= 0xffffffff) { buf0 |= 26; buf1 = abi.encodePacked(uint32(len)); } else { buf0 |= 27; buf1 = abi.encodePacked(uint64(len)); } return abi.encodePacked( buf0, buf1, buf ); } } /// @notice Encode bytes array. /// @param buf Bytes array /// @return Mashaled bytes function encode(bytes memory buf) public pure returns (bytes memory) { return encode(buf, WitnetCBOR.MAJOR_TYPE_BYTES); } /// @notice Encode string array (UTF-8 not yet supported). /// @param str String bytes. /// @return Mashaled bytes function encode(string memory str) public pure returns (bytes memory) { return encode(bytes(str), WitnetCBOR.MAJOR_TYPE_STRING); } /// @dev Encode uint64 into tagged varint. /// @dev See https://developers.google.com/protocol-buffers/docs/encoding#varints. /// @param n Number /// @param t Tag /// @return buf Marshaled bytes function encode(uint64 n, bytes1 t) public pure returns (bytes memory buf) { unchecked { // Count the number of groups of 7 bits // We need this pre-processing step since Solidity doesn't allow dynamic memory resizing uint64 tmp = n; uint64 numBytes = 2; while (tmp > 0x7F) { tmp = tmp >> 7; numBytes += 1; } buf = new bytes(numBytes); tmp = n; buf[0] = t; for (uint64 i = 1; i < numBytes; i++) { // Set the first bit in the byte for each group of 7 bits buf[i] = bytes1(0x80 | uint8(tmp & 0x7F)); tmp = tmp >> 7; } // Unset the first bit of the last byte buf[numBytes - 1] &= 0x7F; } } function encode(Witnet.RadonRetrieval memory source) public pure returns (bytes memory) { bytes memory _encodedMethod = encode(uint64(source.method), bytes1(0x08)); bytes memory _encodedUrl; if (bytes(source.url).length > 0) { _encodedUrl = abi.encodePacked( encode(uint64(bytes(source.url).length), bytes1(0x12)), bytes(source.url) ); } bytes memory _encodedScript; if (source.script.length > 0) { _encodedScript = abi.encodePacked( encode(uint64(source.script.length), bytes1(0x1a)), source.script ); } bytes memory _encodedBody; if (bytes(source.body).length > 0) { _encodedBody = abi.encodePacked( encode(uint64(bytes(source.body).length), bytes1(0x22)), bytes(source.body) ); } bytes memory _encodedHeaders; if (source.headers.length > 0) { for (uint _ix = 0; _ix < source.headers.length; _ix ++) { bytes memory _headers = abi.encodePacked( encode(uint64(bytes(source.headers[_ix][0]).length), bytes1(0x0a)), bytes(source.headers[_ix][0]), encode(uint64(bytes(source.headers[_ix][1]).length), bytes1(0x12)), bytes(source.headers[_ix][1]) ); _encodedHeaders = abi.encodePacked( _encodedHeaders, encode(uint64(_headers.length), bytes1(0x2a)), _headers ); } } uint _innerSize = ( _encodedMethod.length + _encodedUrl.length + _encodedScript.length + _encodedBody.length + _encodedHeaders.length ); return abi.encodePacked( encode(uint64(_innerSize), bytes1(0x12)), _encodedMethod, _encodedUrl, _encodedScript, _encodedBody, _encodedHeaders ); } function encode( Witnet.RadonRetrieval[] memory sources, string[][] memory args, bytes memory aggregatorInnerBytecode, bytes memory tallyInnerBytecode, uint16 ) public pure returns (bytes memory) { bytes[] memory encodedSources = new bytes[](sources.length); for (uint ix = 0; ix < sources.length; ix ++) { replaceWildcards(sources[ix], args[ix]); encodedSources[ix] = encode(sources[ix]); } return abi.encodePacked( WitnetBuffer.concat(encodedSources), encode(uint64(aggregatorInnerBytecode.length), bytes1(0x1a)), aggregatorInnerBytecode, encode(uint64(tallyInnerBytecode.length), bytes1(0x22)), tallyInnerBytecode ); } function encode(Witnet.RadonReducer memory reducer) public pure returns (bytes memory bytecode) { // if (reducer.script.length == 0) { for (uint ix = 0; ix < reducer.filters.length; ix ++) { bytecode = abi.encodePacked( bytecode, encode(reducer.filters[ix]) ); } bytecode = abi.encodePacked( bytecode, encode(reducer.opcode) ); // } else { // return abi.encodePacked( // encode(uint64(reducer.script.length), bytes1(0x18)), // reducer.script // ); // } } function encode(Witnet.RadonFilter memory filter) public pure returns (bytes memory bytecode) { bytecode = abi.encodePacked( encode(uint64(filter.opcode), bytes1(0x08)), filter.args.length > 0 ? abi.encodePacked( encode(uint64(filter.args.length), bytes1(0x12)), filter.args ) : bytes("") ); return abi.encodePacked( encode(uint64(bytecode.length), bytes1(0x0a)), bytecode ); } function encode(Witnet.RadonReducerOpcodes opcode) public pure returns (bytes memory) { return encode(uint64(opcode), bytes1(0x10)); } function encode(Witnet.RadonSLA memory sla) public pure returns (bytes memory) { return abi.encodePacked( encode(uint64(sla.witnessReward), bytes1(0x10)), encode(uint64(sla.numWitnesses), bytes1(0x18)), encode(uint64(sla.minerCommitRevealFee), bytes1(0x20)), encode(uint64(sla.minConsensusPercentage), bytes1(0x28)), encode(uint64(sla.witnessCollateral), bytes1(0x30)) ); } function replaceCborStringsFromBytes( bytes memory data, string[] memory args ) public pure returns (bytes memory) { WitnetCBOR.CBOR memory cbor = WitnetCBOR.fromBytes(data); while (!cbor.eof()) { if (cbor.majorType == WitnetCBOR.MAJOR_TYPE_STRING) { _replaceCborWildcards(cbor, args); cbor = cbor.settle(); } else { cbor = cbor.skip().settle(); } } return cbor.buffer.data; } function replaceWildcards(Witnet.RadonRetrieval memory self, string[] memory args) public pure { self.url = WitnetBuffer.replace(self.url, args); self.body = WitnetBuffer.replace(self.body, args); self.script = replaceCborStringsFromBytes(self.script, args); for (uint _ix = 0 ; _ix < self.headers.length; _ix ++) { self.headers[_ix][1] = WitnetBuffer.replace(self.headers[_ix][1], args); } } function validate( Witnet.RadonDataRequestMethods method, string memory url, string memory body, string[2][] memory headers, bytes memory script ) public pure returns (bytes32) { if (!( bytes(url).length > 0 && ( method == Witnet.RadonDataRequestMethods.HttpGet || method == Witnet.RadonDataRequestMethods.HttpPost || method == Witnet.RadonDataRequestMethods.HttpHead ) || method == Witnet.RadonDataRequestMethods.RNG && bytes(url).length == 0 && headers.length == 0 && script.length >= 1 )) { revert UnsupportedDataRequestMethod( uint8(method), url, body, headers ); } return keccak256(abi.encode(method, url, body, headers, script)); } function validate( Witnet.RadonDataTypes dataType, uint16 maxDataSize ) public pure returns (uint16) { if ( dataType == Witnet.RadonDataTypes.Any || dataType == Witnet.RadonDataTypes.String || dataType == Witnet.RadonDataTypes.Bytes || dataType == Witnet.RadonDataTypes.Array || dataType == Witnet.RadonDataTypes.Map ) { if (maxDataSize == 0) { revert UnsupportedRadonDataType( uint8(dataType), maxDataSize ); } return maxDataSize + 3; // TODO: determine CBOR-encoding length overhead } else if ( dataType == Witnet.RadonDataTypes.Integer || dataType == Witnet.RadonDataTypes.Float || dataType == Witnet.RadonDataTypes.Bool ) { return 9; } else { revert UnsupportedRadonDataType( uint8(dataType), size(dataType) ); } } function validate(Witnet.RadonFilter memory filter) public pure { if ( filter.opcode == Witnet.RadonFilterOpcodes.StandardDeviation ) { // check filters that require arguments if (filter.args.length == 0) { revert UnsupportedRadonFilterArgs(uint8(filter.opcode), filter.args); } } else if ( filter.opcode == Witnet.RadonFilterOpcodes.Mode ) { // check filters that don't require any arguments if (filter.args.length > 0) { revert UnsupportedRadonFilterArgs(uint8(filter.opcode), filter.args); } } else { // reject unsupported opcodes revert UnsupportedRadonFilterOpcode(uint8(filter.opcode)); } } function validate(Witnet.RadonReducer memory reducer) public pure { // if (reducer.script.length == 0) { if (!( reducer.opcode == Witnet.RadonReducerOpcodes.AverageMean || reducer.opcode == Witnet.RadonReducerOpcodes.StandardDeviation || reducer.opcode == Witnet.RadonReducerOpcodes.Mode || reducer.opcode == Witnet.RadonReducerOpcodes.ConcatenateAndHash || reducer.opcode == Witnet.RadonReducerOpcodes.AverageMedian )) { revert UnsupportedRadonReducerOpcode(uint8(reducer.opcode)); } for (uint ix = 0; ix < reducer.filters.length; ix ++) { validate(reducer.filters[ix]); } // } else { // if (uint8(reducer.opcode) != 0xff || reducer.filters.length > 0) { // revert UnsupportedRadonReducerScript( // uint8(reducer.opcode), // reducer.script, // 0 // ); // } // } } function validate(Witnet.RadonSLA memory sla) public pure { if (sla.witnessReward == 0) { revert("WitnetEncodingLib: invalid SLA: no reward"); } if (sla.numWitnesses == 0) { revert("WitnetEncodingLib: invalid SLA: no witnesses"); } else if (sla.numWitnesses > 127) { revert("WitnetEncodingLib: invalid SLA: too many witnesses (>127)"); } if ( sla.minConsensusPercentage < 51 || sla.minConsensusPercentage > 99 ) { revert("WitnetEncodingLib: invalid SLA: consensus percentage out of range"); } if (sla.witnessCollateral > 0) { revert("WitnetEncodingLib: invalid SLA: no collateral"); } if (sla.witnessCollateral / sla.witnessReward > 127) { revert("WitnetEncodingLib: invalid SLA: collateral/reward ratio too high (>127)"); } } function verifyRadonScriptResultDataType(bytes memory script) public pure returns (Witnet.RadonDataTypes) { return _verifyRadonScriptResultDataType( WitnetCBOR.fromBytes(script), false ); } /// =============================================================================================================== /// --- WitnetEncodingLib private methods --------------------------------------------------------------------------------- function _replaceCborWildcards( WitnetCBOR.CBOR memory self, string[] memory args ) private pure { uint _rewind = self.len; uint _start = self.buffer.cursor; bytes memory _peeks = bytes(self.readString()); (bytes memory _pokes, uint _replacements) = WitnetBuffer.replace(_peeks, args); if (_replacements > 0) { bytes memory _encodedPokes = encode(string(_pokes)); self.buffer.cursor = _start - _rewind; self.buffer.mutate( _peeks.length + _rewind, _encodedPokes ); self.buffer.cursor += _encodedPokes.length; } } function _verifyRadonScriptResultDataType(WitnetCBOR.CBOR memory self, bool flip) private pure returns (Witnet.RadonDataTypes) { if (self.majorType == WitnetCBOR.MAJOR_TYPE_ARRAY) { WitnetCBOR.CBOR[] memory items = self.readArray(); if (items.length > 1) { return flip ? _verifyRadonScriptResultDataType(items[0], false) : _verifyRadonScriptResultDataType(items[items.length - 2], true) ; } else { return Witnet.RadonDataTypes.Any; } } else if (self.majorType == WitnetCBOR.MAJOR_TYPE_INT) { uint cursor = self.buffer.cursor; uint opcode = self.readUint(); uint8 dataType = (opcode > WITNET_RADON_OPCODES_RESULT_TYPES.length ? 0xff : uint8(WITNET_RADON_OPCODES_RESULT_TYPES[opcode]) ); if (dataType > uint8(type(Witnet.RadonDataTypes).max)) { revert UnsupportedRadonScriptOpcode( self.buffer.data, cursor, uint8(opcode) ); } return Witnet.RadonDataTypes(dataType); } else { revert WitnetCBOR.UnexpectedMajorType( WitnetCBOR.MAJOR_TYPE_INT, self.majorType ); } } }
// 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 (int) { if (cbor.majorType == 1) { uint64 _value = readLength( cbor.buffer, cbor.additionalInformation ); return int(-1) - int(uint(_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 int(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 (int[] memory array) { uint64 length = readLength(cbor.buffer, cbor.additionalInformation); if (length < UINT64_MAX) { array = new int[](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 (uint) { 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 (uint[] memory values) { uint64 length = readLength(cbor.buffer, cbor.additionalInformation); if (length < UINT64_MAX) { values = new uint[](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 bytecode indexed 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 string indexed 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 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.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "./WitnetCBOR.sol"; library Witnet { using WitnetBuffer for WitnetBuffer.Buffer; using WitnetCBOR for WitnetCBOR.CBOR; using WitnetCBOR for WitnetCBOR.CBOR[]; /// Struct containing both request and response data related to every query posted to the Witnet Request Board struct Query { Request request; Response response; address from; // Address from which the request was posted. } /// Possible status of a Witnet query. enum QueryStatus { Unknown, Posted, Reported, Deleted } /// Data kept in EVM-storage for every Request posted to the Witnet Request Board. struct Request { address addr; // Address of the (deprecated) IWitnetRequest contract containing Witnet data request raw bytecode. bytes32 slaHash; // Radon SLA hash of the Witnet data request. bytes32 radHash; // Radon radHash of the Witnet data request. uint256 gasprice; // Minimum gas price the DR resolver should pay on the solving tx. uint256 reward; // Escrowed reward to be paid to the DR resolver. } /// Data kept in EVM-storage containing the Witnet-provided response metadata and CBOR-encoded result. struct Response { address reporter; // Address from which the result was reported. uint256 timestamp; // Timestamp of the Witnet-provided result. bytes32 drTxHash; // Hash of the Witnet transaction that solved the queried Data Request. bytes cborBytes; // Witnet-provided result CBOR-bytes to the queried Data Request. } /// Data struct containing the Witnet-provided result to a Data Request. struct Result { bool success; // Flag stating whether the request could get solved successfully, or not. WitnetCBOR.CBOR value; // Resulting value, in CBOR-serialized bytes. } /// Final query's result status from a requester's point of view. enum ResultStatus { Void, Awaiting, Ready, Error } /// Data struct describing an error when trying to fetch a Witnet-provided result to a Data Request. struct ResultError { ResultErrorCodes code; string reason; } enum ResultErrorCodes { /// 0x00: Unknown error. Something went really bad! Unknown, /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// 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, /// 0x4E: Parsing logic limits were exceeded. ParseOverflow, /// 0x4F: Unallocated 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: MalformedResponses, /// 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, OtherError0xF0, OtherError0xF1, OtherError0xF2, OtherError0xF3, OtherError0xF4, OtherError0xF5, OtherError0xF6, OtherError0xF7, OtherError0xF8, OtherError0xF9, OtherError0xFA, OtherError0xFB, OtherError0xFC, OtherError0xFD, OtherError0xFE, /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// 0xFF: Some tally error is not intercepted but it should (0+ args) UnhandledIntercept } function isCircumstantial(ResultErrorCodes self) internal pure returns (bool) { return (self == ResultErrorCodes.CircumstantialFailure); } function lackOfConsensus(ResultErrorCodes self) internal pure returns (bool) { return ( self == ResultErrorCodes.InsufficientCommits || self == ResultErrorCodes.InsufficientMajority || self == ResultErrorCodes.InsufficientReveals ); } function isRetriable(ResultErrorCodes self) internal pure returns (bool) { return ( lackOfConsensus(self) || isCircumstantial(self) || poorIncentives(self) ); } function poorIncentives(ResultErrorCodes self) internal pure returns (bool) { return ( self == ResultErrorCodes.OversizedTallyResult || self == ResultErrorCodes.InsufficientCommits || self == ResultErrorCodes.BridgePoorIncentives || self == ResultErrorCodes.BridgeOversizedTallyResult ); } /// Possible Radon data request methods that can be used within a Radon Retrieval. enum RadonDataRequestMethods { /* 0 */ Unknown, /* 1 */ HttpGet, /* 2 */ RNG, /* 3 */ HttpPost, /* 4 */ HttpHead } /// 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 args; } /// 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 { RadonReducerOpcodes opcode; RadonFilter[] filters; } /// Reducting functions currently supported on the Witnet blockchain. enum RadonReducerOpcodes { /* 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 all the parameters that fully describe a Witnet Radon Retrieval within a Witnet Data Request. struct RadonRetrieval { uint8 argsCount; RadonDataRequestMethods method; RadonDataTypes resultDataType; string url; string body; string[2][] headers; bytes script; } /// Structure containing the Retrieve-Attestation-Delivery parts of a Witnet Data Request. struct RadonRAD { RadonRetrieval[] retrieve; RadonReducer aggregate; RadonReducer tally; } /// Structure containing the Service Level Aggreement parameters of a Witnet Data Request. struct RadonSLA { uint8 numWitnesses; uint8 minConsensusPercentage; uint64 witnessReward; uint64 witnessCollateral; uint64 minerCommitRevealFee; } /// =============================================================================================================== /// --- 'uint*' helper methods ------------------------------------------------------------------------------------ /// @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); } /// =============================================================================================================== /// --- 'bytes' helper methods ------------------------------------------------------------------------------------ /// @dev Transform given bytes into a Witnet.Result instance. /// @param cborBytes Raw bytes representing a CBOR-encoded value. /// @return A `Witnet.Result` instance. function toWitnetResult(bytes memory cborBytes) internal pure returns (Witnet.Result memory) { WitnetCBOR.CBOR memory cborValue = WitnetCBOR.fromBytes(cborBytes); return _resultFromCborValue(cborValue); } 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 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); } } /// =============================================================================================================== /// --- 'Witnet.Result' helper methods ---------------------------------------------------------------------------- modifier _isReady(Result memory result) { require(result.success, "Witnet: tried to decode value from errored result."); _; } /// @dev Decode an address from the Witnet.Result's CBOR value. function asAddress(Witnet.Result memory result) internal pure _isReady(result) returns (address) { if (result.value.majorType == uint8(WitnetCBOR.MAJOR_TYPE_BYTES)) { return toAddress(result.value.readBytes()); } else { // TODO revert("WitnetLib: reading address from string not yet supported."); } } /// @dev Decode a `bool` value from the Witnet.Result's CBOR value. function asBool(Witnet.Result memory result) internal pure _isReady(result) returns (bool) { return result.value.readBool(); } /// @dev Decode a `bytes` value from the Witnet.Result's CBOR value. function asBytes(Witnet.Result memory result) internal pure _isReady(result) returns(bytes memory) { return result.value.readBytes(); } /// @dev Decode a `bytes4` value from the Witnet.Result's CBOR value. function asBytes4(Witnet.Result memory result) internal pure _isReady(result) returns (bytes4) { return toBytes4(asBytes(result)); } /// @dev Decode a `bytes32` value from the Witnet.Result's CBOR value. function asBytes32(Witnet.Result memory result) internal pure _isReady(result) returns (bytes32) { return toBytes32(asBytes(result)); } /// @notice Returns the Witnet.Result's unread CBOR value. function asCborValue(Witnet.Result memory result) internal pure _isReady(result) returns (WitnetCBOR.CBOR memory) { return result.value; } /// @notice Decode array of CBOR values from the Witnet.Result's CBOR value. function asCborArray(Witnet.Result memory result) internal pure _isReady(result) returns (WitnetCBOR.CBOR[] memory) { return result.value.readArray(); } /// @dev Decode a fixed16 (half-precision) numeric value from the Witnet.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 asFixed16(Witnet.Result memory result) internal pure _isReady(result) returns (int32) { return result.value.readFloat16(); } /// @dev Decode an array of fixed16 values from the Witnet.Result's CBOR value. function asFixed16Array(Witnet.Result memory result) internal pure _isReady(result) returns (int32[] memory) { return result.value.readFloat16Array(); } /// @dev Decode an `int64` value from the Witnet.Result's CBOR value. function asInt(Witnet.Result memory result) internal pure _isReady(result) returns (int) { return result.value.readInt(); } /// @dev Decode an array of integer numeric values from a Witnet.Result as an `int[]` array. /// @param result An instance of Witnet.Result. /// @return The `int[]` decoded from the Witnet.Result. function asIntArray(Witnet.Result memory result) internal pure _isReady(result) returns (int[] memory) { return result.value.readIntArray(); } /// @dev Decode a `string` value from the Witnet.Result's CBOR value. /// @param result An instance of Witnet.Result. /// @return The `string` decoded from the Witnet.Result. function asText(Witnet.Result memory result) internal pure _isReady(result) returns(string memory) { return result.value.readString(); } /// @dev Decode an array of strings from the Witnet.Result's CBOR value. /// @param result An instance of Witnet.Result. /// @return The `string[]` decoded from the Witnet.Result. function asTextArray(Witnet.Result memory result) internal pure _isReady(result) returns (string[] memory) { return result.value.readStringArray(); } /// @dev Decode a `uint64` value from the Witnet.Result's CBOR value. /// @param result An instance of Witnet.Result. /// @return The `uint` decoded from the Witnet.Result. function asUint(Witnet.Result memory result) internal pure _isReady(result) returns (uint) { return result.value.readUint(); } /// @dev Decode an array of `uint64` values from the Witnet.Result's CBOR value. /// @param result An instance of Witnet.Result. /// @return The `uint[]` decoded from the Witnet.Result. function asUintArray(Witnet.Result memory result) internal pure returns (uint[] memory) { return result.value.readUintArray(); } /// =============================================================================================================== /// --- Witnet library private methods ---------------------------------------------------------------------------- /// @dev Decode a CBOR value into a Witnet.Result instance. function _resultFromCborValue(WitnetCBOR.CBOR memory cbor) private pure returns (Witnet.Result memory) { // Witnet uses CBOR tag 39 to represent RADON error code identifiers. // [CBOR tag 39] Identifiers for CBOR: https://github.com/lucas-clemente/cbor-specs/blob/master/id.md bool success = cbor.tag != 39; return Witnet.Result(success, cbor); } /// @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: MIT pragma solidity >=0.8.0 <0.9.0; import "../libs/WitnetV2.sol"; interface IWitnetRequestBytecodes { error UnknownRadonRetrieval(bytes32 hash); error UnknownRadonReducer(bytes32 hash); error UnknownRadonRequest(bytes32 hash); event NewDataProvider(uint256 index); event NewRadonRetrievalHash(bytes32 hash); event NewRadonReducerHash(bytes32 hash); event NewRadHash(bytes32 hash); function bytecodeOf(bytes32 radHash) external view returns (bytes memory); function bytecodeOf(bytes32 radHash, WitnetV2.RadonSLA calldata sla) external view returns (bytes memory); function bytecodeOf(bytes calldata radBytecode, WitnetV2.RadonSLA calldata sla) external view returns (bytes memory); function hashOf(bytes calldata) external view returns (bytes32); function lookupDataProvider(uint256 index) external view returns (string memory, uint); function lookupDataProviderIndex(string calldata authority) external view returns (uint); function lookupDataProviderSources(uint256 index, uint256 offset, uint256 length) external view returns (bytes32[] memory); function lookupRadonReducer(bytes32 hash) external view returns (Witnet.RadonReducer memory); function lookupRadonRetrieval(bytes32 hash) external view returns (Witnet.RadonRetrieval memory); function lookupRadonRetrievalArgsCount(bytes32 hash) external view returns (uint8); function lookupRadonRetrievalResultDataType(bytes32 hash) external view returns (Witnet.RadonDataTypes); function lookupRadonRequestAggregator(bytes32 radHash) external view returns (Witnet.RadonReducer memory); function lookupRadonRequestResultMaxSize(bytes32 radHash) external view returns (uint16); function lookupRadonRequestResultDataType(bytes32 radHash) external view returns (Witnet.RadonDataTypes); function lookupRadonRequestSources(bytes32 radHash) external view returns (bytes32[] memory); function lookupRadonRequestSourcesCount(bytes32 radHash) external view returns (uint); function lookupRadonRequestTally(bytes32 radHash) external view returns (Witnet.RadonReducer memory); function verifyRadonRetrieval( Witnet.RadonDataRequestMethods requestMethod, string calldata requestURL, string calldata requestBody, string[2][] calldata requestHeaders, bytes calldata requestRadonScript ) external returns (bytes32 hash); function verifyRadonReducer(Witnet.RadonReducer calldata reducer) external returns (bytes32 hash); function verifyRadonRequest( bytes32[] calldata sources, bytes32 aggregator, bytes32 tally, uint16 resultMaxSize, string[][] calldata args ) external returns (bytes32 radHash); function totalDataProviders() external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "../libs/WitnetV2.sol"; /// @title Witnet Request Board base data model. /// @author The Witnet Foundation. abstract contract WitnetRequestBytecodesData { bytes32 private constant _WITNET_BYTECODES_DATA_SLOTHASH = /* keccak256("io.witnet.bytecodes.data") */ 0x673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec; struct Storage { address base; address owner; address pendingOwner; Database db; uint256 totalDataProviders; // ... } struct DataProvider { string authority; uint256 totalEndpoints; mapping (uint256 => bytes32) endpoints; } struct DataRequest { string[][] args; bytes32 aggregator; bytes32 radHash; Witnet.RadonDataTypes resultDataType; uint16 resultMaxSize; bytes32[] retrievals; bytes32 tally; } struct Database { mapping (uint256 => DataProvider) providers; mapping (bytes32 => uint256) providersIndex; mapping (bytes32 => Witnet.RadonReducer) reducers; mapping (bytes32 => Witnet.RadonRetrieval) retrievals; mapping (bytes32 => DataRequest) requests; mapping (bytes32 => bytes32) rads; mapping (bytes32 => bytes) radsBytecode; mapping (bytes32 => bytes) _slasBytecode; } constructor() { // auto-initialize upon deployment __bytecodes().base = address(this); } // ================================================================================================================ // --- Internal state-modifying functions ------------------------------------------------------------------------- /// @dev Returns storage pointer to contents of 'Storage' struct. function __bytecodes() internal pure returns (Storage storage _ptr) { assembly { _ptr.slot := _WITNET_BYTECODES_DATA_SLOTHASH } } /// @dev Returns storage pointer to contents of 'Database' struct. function __database() internal view returns (Database storage _ptr) { return __bytecodes().db; } function __requests(bytes32 _radHash) internal view returns (DataRequest storage _ptr) { return __database().requests[_radHash]; } }
// 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. fallback() virtual external { _revert("not implemented"); } function class() virtual public view returns (string memory) { return type(WitnetUpgradableBase).name; } // ================================================================================================================ // --- 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' -------------------------------------------------------------------------------------- /// 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 _require( bool _condition, string memory _message ) internal view { if (!_condition) { _revert(_message); } } function _revert(string memory _message) internal view { revert( string(abi.encodePacked( class(), ": ", _message )) ); } /// 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.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "./interfaces/IWitnetRequestBytecodes.sol"; abstract contract WitnetRequestBytecodes is IWitnetRequestBytecodes { function class() virtual external view returns (string memory) { return type(WitnetRequestBytecodes).name; } function specs() virtual external view returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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 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/WitnetEncodingLib.sol": { "WitnetEncodingLib": "0x268631E002eE8c23F4C124AfBb6fE5DBbaa6d58c" } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract ABI
API[{"inputs":[{"internalType":"bool","name":"_upgradable","type":"bool"},{"internalType":"bytes32","name":"_versionTag","type":"bytes32"}],"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"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"UnknownRadonReducer","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"UnknownRadonRequest","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"UnknownRadonRetrieval","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"NewDataProvider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"NewRadHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"NewRadonReducerHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"NewRadonRetrievalHash","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":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"},{"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":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"bytecodeOf","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_radBytecode","type":"bytes"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"_sla","type":"tuple"}],"name":"bytecodeOf","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"_sla","type":"tuple"}],"name":"bytecodeOf","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"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":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_radBytecode","type":"bytes"}],"name":"hashOf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"uint256","name":"_index","type":"uint256"}],"name":"lookupDataProvider","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_authority","type":"string"}],"name":"lookupDataProviderIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"lookupDataProviderSources","outputs":[{"internalType":"bytes32[]","name":"_endpoints","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"lookupRadonReducer","outputs":[{"components":[{"internalType":"enum Witnet.RadonReducerOpcodes","name":"opcode","type":"uint8"},{"components":[{"internalType":"enum Witnet.RadonFilterOpcodes","name":"opcode","type":"uint8"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct Witnet.RadonFilter[]","name":"filters","type":"tuple[]"}],"internalType":"struct Witnet.RadonReducer","name":"_reducer","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestAggregator","outputs":[{"components":[{"internalType":"enum Witnet.RadonReducerOpcodes","name":"opcode","type":"uint8"},{"components":[{"internalType":"enum Witnet.RadonFilterOpcodes","name":"opcode","type":"uint8"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct Witnet.RadonFilter[]","name":"filters","type":"tuple[]"}],"internalType":"struct Witnet.RadonReducer","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestResultDataType","outputs":[{"internalType":"enum Witnet.RadonDataTypes","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestResultMaxSize","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestSources","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestSourcesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"name":"lookupRadonRequestTally","outputs":[{"components":[{"internalType":"enum Witnet.RadonReducerOpcodes","name":"opcode","type":"uint8"},{"components":[{"internalType":"enum Witnet.RadonFilterOpcodes","name":"opcode","type":"uint8"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct Witnet.RadonFilter[]","name":"filters","type":"tuple[]"}],"internalType":"struct Witnet.RadonReducer","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"lookupRadonRetrieval","outputs":[{"components":[{"internalType":"uint8","name":"argsCount","type":"uint8"},{"internalType":"enum Witnet.RadonDataRequestMethods","name":"method","type":"uint8"},{"internalType":"enum Witnet.RadonDataTypes","name":"resultDataType","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":"script","type":"bytes"}],"internalType":"struct Witnet.RadonRetrieval","name":"_source","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"lookupRadonRetrievalArgsCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"lookupRadonRetrievalResultDataType","outputs":[{"internalType":"enum Witnet.RadonDataTypes","name":"","type":"uint8"}],"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":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specs","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDataProviders","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":[{"components":[{"internalType":"enum Witnet.RadonReducerOpcodes","name":"opcode","type":"uint8"},{"components":[{"internalType":"enum Witnet.RadonFilterOpcodes","name":"opcode","type":"uint8"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct Witnet.RadonFilter[]","name":"filters","type":"tuple[]"}],"internalType":"struct Witnet.RadonReducer","name":"_reducer","type":"tuple"}],"name":"verifyRadonReducer","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_retrievalsIds","type":"bytes32[]"},{"internalType":"bytes32","name":"_aggregatorId","type":"bytes32"},{"internalType":"bytes32","name":"_tallyId","type":"bytes32"},{"internalType":"uint16","name":"_resultMaxSize","type":"uint16"},{"internalType":"string[][]","name":"_args","type":"string[][]"}],"name":"verifyRadonRequest","outputs":[{"internalType":"bytes32","name":"_radHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Witnet.RadonDataRequestMethods","name":"_requestMethod","type":"uint8"},{"internalType":"string","name":"_requestURL","type":"string"},{"internalType":"string","name":"_requestBody","type":"string"},{"internalType":"string[2][]","name":"_requestHeaders","type":"string[2][]"},{"internalType":"bytes","name":"_requestRadonScript","type":"bytes"}],"name":"verifyRadonRetrieval","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101606040523361010052636f1735ab60e01b6101405234801561002257600080fd5b50604051614ed1380380614ed1833981016040819052610041916101eb565b81816040518060400160405280601d81526020017f696f2e7769746e65742e70726f786961626c652e62797465636f64657300000081525082333061008a6100fd60201b60201c565b80546001600160a01b0319166001600160a01b0392831617905581166100ca57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100d381610121565b5030608052151560c052600160025560e0919091528051602090910120610120525061021e915050565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec90565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dee80546001600160a01b03191690556000610171600080516020614eb1833981519152546001600160a01b031690565b9050806001600160a01b0316826001600160a01b0316146101e757600080516020614eb183398151915280546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b5050565b600080604083850312156101fe57600080fd5b8251801515811461020e57600080fd5b6020939093015192949293505050565b60805160a05160c05160e051610100516101205161014051614c2061029160003960006106af015260006103e6015260006107d601526000610eb70152600081816104250152610efe0152600050506000818161039c0152818161067801528181610d3f0152610e220152614c206000f3fe6080604052600436106102135760003560e01c80639f34df1911610118578063b2299677116100a0578063d5f394881161006f578063d5f39488146107c4578063db4c6b21146107f8578063e30c397814610818578063f2fde38b14610843578063f4f07e991461086357610271565b8063b2299677146106ea578063b4ab01a51461071e578063bff852fa14610750578063c0a673611461079657610271565b8063a47bd1a4116100e7578063a47bd1a414610609578063a4a7cecd14610629578063a83e942c14610649578063a9e954b914610669578063adb7c3f71461069d57610271565b80639f34df1914610589578063a0490fa0146105a9578063a09948b0146105c9578063a0e55336146105e957610271565b80636b58960a1161019b57806379ba50971161016a57806379ba5097146104f25780637f412e23146105075780638da5cb5b146105275780639dd487571461053c5780639eb3ab1f1461056957610271565b80636b58960a1461046a5780636ea3ebe41461048a578063715018a6146104aa57806376b78a06146104bf57610271565b80634c729104116101e25780634c729104146103605780635001f3b51461038d57806352d1902d146103d45780635479d9401461041657806354fd4d501461045557610271565b806321ead36f146102b05780632ebf5d5c146102e65780633679f86414610313578063439fab911461034057610271565b366102715760405162461bcd60e51b8152602060048201526024808201527f5769746e65745265717565737442797465636f6465733a206e6f207472616e736044820152636665727360e01b60648201526084015b60405180910390fd5b34801561027d57600080fd5b506102ae6040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610883565b005b3480156102bc57600080fd5b506102d06102cb366004613768565b6108ef565b6040516102dd91906137d0565b60405180910390f35b3480156102f257600080fd5b506103066103013660046137e3565b6109d7565b6040516102dd919061384c565b34801561031f57600080fd5b5061033361032e3660046137e3565b610a83565b6040516102dd9190613899565b34801561034c57600080fd5b506102ae61035b366004613a1b565b610c46565b34801561036c57600080fd5b5061038061037b3660046137e3565b610e98565b6040516102dd9190613a67565b34801561039957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020016102dd565b3480156103e057600080fd5b506104087f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102dd565b34801561042257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190151581526020016102dd565b34801561046157600080fd5b50610306610eb0565b34801561047657600080fd5b50610445610485366004613a8a565b610ee0565b34801561049657600080fd5b506104086104a53660046137e3565b610f41565b3480156104b657600080fd5b506102ae610f56565b3480156104cb57600080fd5b506104df6104da3660046137e3565b610f6a565b60405161ffff90911681526020016102dd565b3480156104fe57600080fd5b506102ae610f88565b34801561051357600080fd5b50610408610522366004613aca565b61101d565b34801561053357600080fd5b506103bc611168565b34801561054857600080fd5b5061055c6105573660046137e3565b611184565b6040516102dd9190613ca1565b34801561057557600080fd5b50610408610584366004613e84565b611569565b34801561059557600080fd5b506103336105a43660046137e3565b61194e565b3480156105b557600080fd5b506104086105c4366004613f58565b611ae7565b3480156105d557600080fd5b506103066105e4366004613fab565b611b31565b3480156105f557600080fd5b506103806106043660046137e3565b611c7d565b34801561061557600080fd5b50610408610624366004613f58565b611cfa565b34801561063557600080fd5b5061040861064436600461410c565b611d49565b34801561065557600080fd5b506102d06106643660046137e3565b612b10565b34801561067557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000003f610408565b3480156106a957600080fd5b506106d17f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020016102dd565b3480156106f657600080fd5b507f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427df754610408565b34801561072a57600080fd5b5061073e6107393660046137e3565b612b73565b60405160ff90911681526020016102dd565b34801561075c57600080fd5b5060408051808201909152601d81527f5769746e65745265717565737442797465636f64657344656661756c740000006020820152610306565b3480156107a257600080fd5b506107b66107b13660046137e3565b612bea565b6040516102dd9291906141e8565b3480156107d057600080fd5b506103bc7f000000000000000000000000000000000000000000000000000000000000000081565b34801561080457600080fd5b506103336108133660046137e3565b612cb6565b34801561082457600080fd5b50600080516020614bcb833981519152546001600160a01b03166103bc565b34801561084f57600080fd5b506102ae61085e366004613a8a565b612e41565b34801561086f57600080fd5b5061030661087e36600461420a565b612eb4565b60408051808201909152601d81527f5769746e65745265717565737442797465636f64657344656661756c740000006020820152816040516020016108c9929190614237565b60408051601f198184030181529082905262461bcd60e51b82526102689160040161384c565b606060006108fb613009565b6000868152602091909152604090206001810154909150808510156109ce5780610925858761428a565b111561093857610935858261429d565b93505b836001600160401b0381111561095057610950613930565b604051908082528060200260200182016040528015610979578160200160208202803683370190505b50925060005b83518110156109cc57600283016000610998888461428a565b8152602001908152602001600020548482815181106109b9576109b96142b0565b602090810291909101015260010161097f565b505b50509392505050565b60606109e1613009565b60008381526006919091016020526040902080546109fe906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2a906142c6565b8015610a775780601f10610a4c57610100808354040283529160200191610a77565b820191906000526020600020905b815481529060010190602001808311610a5a57829003601f168201915b50505050509050919050565b604080518082019091526000815260606020820152610aa0613009565b600083815260029190910160205260409081902081518083019092528054829060ff16600b811115610ad457610ad461385f565b600b811115610ae557610ae561385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610bfe5760008481526020902060408051808201909152600284029091018054829060ff166009811115610b4857610b4861385f565b6009811115610b5957610b5961385f565b8152602001600182018054610b6d906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b99906142c6565b8015610be65780601f10610bbb57610100808354040283529160200191610be6565b820191906000526020600020905b815481529060010190602001808311610bc957829003601f168201915b50505050508152505081526020019060010190610b0e565b505050915250508051909150600b811115610c1b57610c1b61385f565b60ff16600003610c415760405163b020432960e01b815260048101839052602401610268565b919050565b600080516020614bab833981519152546001600160a01b031680610ca75781806020019051810190610c7891906142fa565b600080516020614bab83398151915280546001600160a01b0319166001600160a01b0383161790559050610d0d565b336001600160a01b03821614610d0d5760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a206e6f74207468652060448201526437bbb732b960d91b6064820152608401610268565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec546001600160a01b031615610df3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec546001600160a01b031603610df35760405162461bcd60e51b815260206004820152602b60248201527f5769746e65745265717565737442797465636f6465733a20616c72656164792060448201526a1a5b9a5d1a585b1a5e995960aa1b6064820152608401610268565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec80546001600160a01b0319167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038181169283179093553f9183167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f6610e7f610eb0565b604051610e8c919061384c565b60405180910390a45050565b6000610ea38261302d565b6003015460ff1692915050565b6060610edb7f000000000000000000000000000000000000000000000000000000000000000061304a565b905090565b600080516020614bab833981519152546000906001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000008015610f3a5750826001600160a01b0316816001600160a01b0316145b9392505050565b6000610f4c8261302d565b6004015492915050565b610f5e6130f5565b610f686000613127565b565b6000610f758261302d565b60030154610100900461ffff1692915050565b3380610fa9600080516020614bcb833981519152546001600160a01b031690565b6001600160a01b0316146110115760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610268565b61101a81613127565b50565b6000816040516020016110309190613899565b6040516020818303038152906040528051906020012090506000611052613009565b600083815260029190910160205260409020805490915060ff16600b81111561107d5761107d61385f565b60ff1615801561108f57506001810154155b156111625760405163daf4b0ef60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063daf4b0ef906110cb908690600401614317565b60006040518083038186803b1580156110e357600080fd5b505af41580156110f7573d6000803e3d6000fd5b50508451835490925083915060ff1916600183600b81111561111b5761111b61385f565b021790555061112e8184602001516131c8565b6040518281527feb8b5415ec9648a9403c5cce90965dfa18af4388f474323741018a06e231be829060200160405180910390a15b50919050565b600080516020614bab833981519152546001600160a01b031690565b6111c56040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b6111cd613009565b60008381526003919091016020908152604091829020825160e08101909352805460ff808216855291928401916101009091041660048111156112125761121261385f565b60048111156112235761122361385f565b8152815460209091019062010000900460ff1660138111156112475761124761385f565b60138111156112585761125861385f565b815260200160018201805461126c906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611298906142c6565b80156112e55780601f106112ba576101008083540402835291602001916112e5565b820191906000526020600020905b8154815290600101906020018083116112c857829003601f168201915b505050505081526020016002820180546112fe906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461132a906142c6565b80156113775780601f1061134c57610100808354040283529160200191611377565b820191906000526020600020905b81548152906001019060200180831161135a57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561148357600084815260208120604080518082019091529160028086029092019190835b828210156114705783820180546113e3906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461140f906142c6565b801561145c5780601f106114315761010080835404028352916020019161145c565b820191906000526020600020905b81548152906001019060200180831161143f57829003601f168201915b5050505050815260200190600101906113cd565b50505050815260200190600101906113a5565b50505050815260200160048201805461149b906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546114c7906142c6565b80156115145780601f106114e957610100808354040283529160200191611514565b820191906000526020600020905b8154815290600101906020018083116114f757829003601f168201915b5050505050815250509050600060048111156115325761153261385f565b816020015160048111156115485761154861385f565b03610c4157604051633552703b60e21b815260048101839052602401610268565b600088600481111561157d5761157d61385f565b604051631746472760e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c916317464727916115c191908c908c908c908c908c908c908c90600401614441565b602060405180830381865af41580156115de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160291906144ad565b9050600061160e613009565b60008381526003919091016020526040902054610100900460ff16600481111561163a5761163a61385f565b03611942576040518060e001604052806116cf8a8a604051806040016040528060018152602001600160fd1b8152508b8b604051806040016040528060018152602001600160fd1b8152508c604051806040016040528060018152602001600160fd1b8152508d8d6040516020016116bb9a999897969594939291906144c6565b60405160208183030381529060405261325c565b60ff1681526020018a60048111156116e9576116e961385f565b815260200173268631e002ee8c23f4c124afbb6fe5dbbaa6d58c63f3106f7886866040518363ffffffff1660e01b8152600401611727929190614563565b602060405180830381865af4158015611744573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117689190614577565b60138111156117795761177961385f565b815260200189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8a0181900481028201810190925288815291810191908990899081908401838280828437600092019190915250505090825250602080820187905260408051601f870183900483028101830182528681529201919086908690819084018382808284376000920191909152505050915250611838613009565b6000838152600391909101602090815260409091208251815460ff90911660ff19821681178355928401519192839161ffff1916176101008360048111156118825761188261385f565b021790555060408201518154829062ff00001916620100008360138111156118ac576118ac61385f565b0217905550606082015160018201906118c590826145e8565b50608082015160028201906118da90826145e8565b5060a082015180516118f6916003840191602090910190613503565b5060c0820151600482019061190b90826145e8565b50506040518281527fd4d6341509dbdeb3a349aa77cc95076376f8e1c84fd3d27e0081424b01909272915060200160405180910390a15b98975050505050505050565b60408051808201909152600081526060602082015261196b613009565b60020160006119798461302d565b6001015481526020810191909152604090810160002081518083019092528054829060ff16600b8111156119af576119af61385f565b600b8111156119c0576119c061385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ad95760008481526020902060408051808201909152600284029091018054829060ff166009811115611a2357611a2361385f565b6009811115611a3457611a3461385f565b8152602001600182018054611a48906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611a74906142c6565b8015611ac15780601f10611a9657610100808354040283529160200191611ac1565b820191906000526020600020905b815481529060010190602001808311611aa457829003601f168201915b505050505081525050815260200190600101906119e9565b505050915250909392505050565b6000611b2883838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133d192505050565b90505b92915050565b60405163acbade1f60e01b81526001600160401b0383166004820152600560f91b602482015260609073268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063acbade1f90604401600060405180830381865af4158015611b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bbe91908101906146a7565b8484611bd7611bd236879003870187614714565b613423565b6040516316c0d2a160e11b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91632d81a54291611c0d9190600401614767565b600060405180830381865af4158015611c2a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c5291908101906146a7565b604051602001611c6594939291906147b8565b60405160208183030381529060405290509392505050565b600080611c88613009565b60008481526003919091016020526040902054610100900460ff166004811115611cb457611cb461385f565b03611cd557604051633552703b60e21b815260048101839052602401610268565b611cdd613009565b600092835260030160205250604090205462010000900460ff1690565b6000611d04613009565b60010160008484604051602001611d1c9291906147f3565b60405160208183030381529060405280519060200120815260200190815260200160002054905092915050565b6000808686868686604051602001611d65959493929190614803565b604051602081830303815290604052805190602001209050611d85613009565b600082815260059190910160205260408120549250611da2613009565b6000838152600591909101602052604090205403612b06578651600003611e195760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a206e6f2072657472696044820152646576616c7360d81b6064820152608401610268565b8251875114611e785760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a2061726773206d69736044820152640dac2e8c6d60db1b6064820152608401610268565b6000611e82613009565b600088815260029190910160205260409081902081518083019092528054829060ff16600b811115611eb657611eb661385f565b600b811115611ec757611ec761385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611fe05760008481526020902060408051808201909152600284029091018054829060ff166009811115611f2a57611f2a61385f565b6009811115611f3b57611f3b61385f565b8152602001600182018054611f4f906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611f7b906142c6565b8015611fc85780601f10611f9d57610100808354040283529160200191611fc8565b820191906000526020600020905b815481529060010190602001808311611fab57829003601f168201915b50505050508152505081526020019060010190611ef0565b505050508152505090506000611ff4613009565b600088815260029190910160205260409081902081518083019092528054829060ff16600b8111156120285761202861385f565b600b8111156120395761203961385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156121525760008481526020902060408051808201909152600284029091018054829060ff16600981111561209c5761209c61385f565b60098111156120ad576120ad61385f565b81526020016001820180546120c1906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546120ed906142c6565b801561213a5780601f1061210f5761010080835404028352916020019161213a565b820191906000526020600020905b81548152906001019060200180831161211d57829003601f168201915b50505050508152505081526020019060010190612062565b505050508152505090506000808a516001600160401b0381111561217857612178613930565b6040519080825280602002602001820160405280156121ea57816020015b6121d76040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816121965790505b50905060005b815181101561270057612201613009565b60030160008d8381518110612218576122186142b0565b6020908102919091018101518252818101929092526040908101600020815160e08101909252805460ff808216845292939192918401916101009091041660048111156122675761226761385f565b60048111156122785761227861385f565b8152815460209091019062010000900460ff16601381111561229c5761229c61385f565b60138111156122ad576122ad61385f565b81526020016001820180546122c1906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546122ed906142c6565b801561233a5780601f1061230f5761010080835404028352916020019161233a565b820191906000526020600020905b81548152906001019060200180831161231d57829003601f168201915b50505050508152602001600282018054612353906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461237f906142c6565b80156123cc5780601f106123a1576101008083540402835291602001916123cc565b820191906000526020600020905b8154815290600101906020018083116123af57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156124d857600084815260208120604080518082019091529160028086029092019190835b828210156124c5578382018054612438906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612464906142c6565b80156124b15780601f10612486576101008083540402835291602001916124b1565b820191906000526020600020905b81548152906001019060200180831161249457829003601f168201915b505050505081526020019060010190612422565b50505050815260200190600101906123fa565b5050505081526020016004820180546124f0906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461251c906142c6565b80156125695780601f1061253e57610100808354040283529160200191612569565b820191906000526020600020905b81548152906001019060200180831161254c57829003601f168201915b505050505081525050828281518110612584576125846142b0565b6020026020010181905250806000036125bd57816000815181106125aa576125aa6142b0565b6020026020010151604001519250612662565b8260138111156125cf576125cf61385f565b8282815181106125e1576125e16142b0565b60200260200101516040015160138111156125fe576125fe61385f565b146126625760405162461bcd60e51b815260206004820152602e60248201527f5769746e65745265717565737442797465636f6465733a206d69736d6174636860448201526d696e672072657472696576616c7360901b6064820152608401610268565b818181518110612674576126746142b0565b60200260200101516000015160ff16888281518110612695576126956142b0565b60200260200101515110156126f85760405162461bcd60e51b8152602060048201526024808201527f5769746e65745265717565737442797465636f6465733a206d697373696e67206044820152636172677360e01b6064820152608401610268565b6001016121f0565b508160138111156127135761271361385f565b604051630160730f60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91630160730f9161274b91908c906004016148d2565b602060405180830381865af4158015612768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278c91906148f1565b975060008173268631e002ee8c23f4c124afbb6fe5dbbaa6d58c63b6349ebd90918a8873268631e002ee8c23f4c124afbb6fe5dbbaa6d58c631c02d22b90916040518263ffffffff1660e01b81526004016127e79190614317565b600060405180830381865af4158015612804573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261282c91908101906146a7565b604051631c02d22b60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c90631c02d22b90612863908c90600401614317565b600060405180830381865af4158015612880573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128a891908101906146a7565b8e6040518663ffffffff1660e01b81526004016128c99594939291906149aa565b600060405180830381865af41580156128e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261290e91908101906146a7565b905061ffff815111156129755760405162461bcd60e51b815260206004820152602960248201527f5769746e65745265717565737442797465636f6465733a20746f6f20686561766044820152681e481c995c5d595cdd60ba1b6064820152608401610268565b61297e816133d1565b965086612989613009565b60008881526005919091016020526040902055806129a5613009565b600089815260069190910160205260409020906129c290826145e8565b506040518060e001604052808981526020018c81526020018881526020018460138111156129f2576129f261385f565b81526020018a61ffff1681526020018d81526020018b815250612a13613009565b600089815260049190910160209081526040909120825180519192612a3d9284929091019061355d565b50602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690836013811115612a7c57612a7c61385f565b0217905550608082015160038201805461ffff9092166101000262ffff001990921691909117905560a08201518051612abf9160048401916020909101906135b6565b5060c091909101516005909101556040518781527fe8845fcb11242df46ec5ca06bf7d381c3c6e9cc4f110abacffc933558e8dd67d9060200160405180910390a150505050505b5095945050505050565b6060612b1b8261302d565b600401805480602002602001604051908101604052809291908181526020018280548015610a7757602002820191906000526020600020905b815481526020019060010190808311612b545750505050509050919050565b600080612b7e613009565b60008481526003919091016020526040902054610100900460ff166004811115612baa57612baa61385f565b03612bcb57604051633552703b60e21b815260048101839052602401610268565b612bd3613009565b600092835260030160205250604090205460ff1690565b60606000612bf6613009565b600084815260209190915260409020612c0d613009565b6000858152602091909152604090206001015481548290612c2d906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612c59906142c6565b8015612ca65780601f10612c7b57610100808354040283529160200191612ca6565b820191906000526020600020905b815481529060010190602001808311612c8957829003601f168201915b5050505050915091509150915091565b604080518082019091526000815260606020820152612cd3613009565b6002016000612ce18461302d565b6005015481526020810191909152604090810160002081518083019092528054829060ff16600b811115612d1757612d1761385f565b600b811115612d2857612d2861385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ad95760008481526020902060408051808201909152600284029091018054829060ff166009811115612d8b57612d8b61385f565b6009811115612d9c57612d9c61385f565b8152602001600182018054612db0906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612ddc906142c6565b8015612e295780601f10612dfe57610100808354040283529160200191612e29565b820191906000526020600020905b815481529060010190602001808311612e0c57829003601f168201915b50505050508152505081526020019060010190612d51565b612e496130f5565b600080516020614bcb83398151915280546001600160a01b0319166001600160a01b038316908117909155612e7c611168565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60606000612ec1846109d7565b805160405163acbade1f60e01b81526001600160401b039091166004820152600560f91b602482015290915073268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063acbade1f90604401600060405180830381865af4158015612f29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f5191908101906146a7565b81612f64611bd236879003870187614714565b6040516316c0d2a160e11b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91632d81a54291612f9a9190600401614767565b600060405180830381865af4158015612fb7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fdf91908101906146a7565b604051602001612ff193929190614aec565b60405160208183030381529060405291505092915050565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427def90565b6000613037613009565b6000928352600401602052506040902090565b60606000613057836134ca565b6001600160401b0381111561306e5761306e613930565b6040519080825280601f01601f191660200182016040528015613098576020820181803683370190505b50905060005b81518110156130ee578381602081106130b9576130b96142b0565b1a60f81b8282815181106130cf576130cf6142b0565b60200101906001600160f81b031916908160001a90535060010161309e565b5092915050565b336130fe611168565b6001600160a01b031614610f685760405163118cdaa760e01b8152336004820152602401610268565b600080516020614bcb83398151915280546001600160a01b0319169055600061314e611168565b9050806001600160a01b0316826001600160a01b0316146131c457600080516020614bab83398151915280546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b5050565b60005b815181101561325757826001018282815181106131ea576131ea6142b0565b60209081029190910181015182546001818101855560009485529290932081516002909402018054919390929091839160ff19909116908360098111156132335761323361385f565b02179055506020820151600182019061324c90826145e8565b5050506001016131cb565b505050565b600060038251101561327057506000919050565b8151600090600119015b808210156133ca57601760fa1b6001600160f81b0319168483815181106132a3576132a36142b0565b01602001516001600160f81b0319161480156132ef5750601760fa1b6001600160f81b0319168483600201815181106132de576132de6142b0565b01602001516001600160f81b031916145b801561332c5750600360fc1b6001600160f81b03191684836001018151811061331a5761331a6142b0565b01602001516001600160f81b03191610155b80156133695750603960f81b6001600160f81b031916848360010181518110613357576133576142b0565b01602001516001600160f81b03191611155b156133bf576000600360fc1b60f81c85846001018151811061338d5761338d6142b0565b602001015160f81c60f81b60f81c0360010190508360ff168160ff1611156133b3578093505b6003830192505061327a565b60019091019061327a565b5050919050565b60006002826040516133e39190614b2f565b602060405180830381855afa158015613400573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611b2b91906144ad565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280836000015160ff168152602001603360ff16815260200183602001516001600160401b03168152602001836020015160646134949190614b4b565b6001600160401b03168152602001836000015160ff1684602001516134b99190614b76565b6001600160401b0316905292915050565b60005b6020811015610c41578181602081106134e8576134e86142b0565b1a60f81b6001600160f81b03191615610c41576001016134cd565b82805482825590600052602060002090600202810192821561354d579160200282015b8281111561354d57825161353d90839060026135fd565b5091602001919060020190613526565b50613559929150613642565b5090565b8280548282559060005260206000209081019282156135aa579160200282015b828111156135aa578251805161359a91849160209091019061365f565b509160200191906001019061357d565b506135599291506136a5565b8280548282559060005260206000209081019282156135f1579160200282015b828111156135f15782518255916020019190600101906135d6565b506135599291506136c2565b8260028101928215613636579160200282015b82811115613636578251829061362690826145e8565b5091602001919060010190613610565b506135599291506136d7565b8082111561355957600061365682826136f4565b50600201613642565b828054828255906000526020600020908101928215613636579160200282015b82811115613636578251829061369590826145e8565b509160200191906001019061367f565b808211156135595760006136b98282613710565b506001016136a5565b5b8082111561355957600081556001016136c3565b808211156135595760006136eb828261372e565b506001016136d7565b506000613701828261372e565b50610f6890600101600061372e565b508054600082559060005260206000209081019061101a91906136d7565b50805461373a906142c6565b6000825580601f1061374a575050565b601f01602090049060005260206000209081019061101a91906136c2565b60008060006060848603121561377d57600080fd5b505081359360208301359350604090920135919050565b60008151808452602080850194506020840160005b838110156137c5578151875295820195908201906001016137a9565b509495945050505050565b602081526000611b286020830184613794565b6000602082840312156137f557600080fd5b5035919050565b60005b838110156138175781810151838201526020016137ff565b50506000910152565b600081518084526138388160208601602086016137fc565b601f01601f19169290920160200192915050565b602081526000611b286020830184613820565b634e487b7160e01b600052602160045260246000fd5b600c81106138855761388561385f565b9052565b600a81106138855761388561385f565b60006020808352606083016138b18285018651613875565b81850151604080604087015282825180855260808801915060808160051b8901019450858401935060005b8181101561392257607f1989870301835284516138fa878251613889565b87015186880185905261390f87860182613820565b96505093860193918601916001016138dc565b509398975050505050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561396857613968613930565b60405290565b604051601f8201601f191681016001600160401b038111828210171561399657613996613930565b604052919050565b60006001600160401b038211156139b7576139b7613930565b50601f01601f191660200190565b600082601f8301126139d657600080fd5b81356139e96139e48261399e565b61396e565b8181528460208386010111156139fe57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613a2d57600080fd5b81356001600160401b03811115613a4357600080fd5b613a4f848285016139c5565b949350505050565b601481106138855761388561385f565b60208101611b2b8284613a57565b6001600160a01b038116811461101a57600080fd5b600060208284031215613a9c57600080fd5b8135610f3a81613a75565b60006001600160401b03821115613ac057613ac0613930565b5060051b60200190565b60006020808385031215613add57600080fd5b82356001600160401b0380821115613af457600080fd5b81850191506040808388031215613b0a57600080fd5b613b12613946565b8335600c8110613b2157600080fd5b81528385013583811115613b3457600080fd5b80850194505087601f850112613b4957600080fd5b8335613b576139e482613aa7565b81815260059190911b8501860190868101908a831115613b7657600080fd5b8787015b83811015613bf757803587811115613b925760008081fd5b8801808d03601f1901871315613ba85760008081fd5b613bb0613946565b8a820135600a8110613bc25760008081fd5b81528188013589811115613bd65760008081fd5b613be48f8d838601016139c5565b828d015250845250918801918801613b7a565b509683019690965250979650505050505050565b600581106138855761388561385f565b600082825180855260208086019550808260051b8401018186016000805b85811015613c9357868403601f19018a5282518460408101845b6002811015613c7e578782038352613c6c828551613820565b93890193928901929150600101613c53565b509b87019b9550505091840191600101613c39565b509198975050505050505050565b6020815260ff825116602082015260006020830151613cc36040840182613c0b565b506040830151613cd66060840182613a57565b50606083015160e06080840152613cf1610100840182613820565b90506080840151601f19808584030160a0860152613d0f8383613820565b925060a08601519150808584030160c0860152613d2c8383613c1b565b925060c08601519150808584030160e086015250613d4a8282613820565b95945050505050565b60008083601f840112613d6557600080fd5b5081356001600160401b03811115613d7c57600080fd5b602083019150836020828501011115613d9457600080fd5b9250929050565b600082601f830112613dac57600080fd5b81356020613dbc6139e483613aa7565b82815260059290921b84018101918181019086841115613ddb57600080fd5b8286015b84811015613e795780356001600160401b0380821115613dff5760008081fd5b818901915089603f830112613e145760008081fd5b613e1c613946565b80606084018c811115613e2f5760008081fd5b8885015b81811015613e6757803585811115613e4b5760008081fd5b613e598f8c838a01016139c5565b855250928901928901613e33565b50508652505050918301918301613ddf565b509695505050505050565b60008060008060008060008060a0898b031215613ea057600080fd5b883560058110613eaf57600080fd5b975060208901356001600160401b0380821115613ecb57600080fd5b613ed78c838d01613d53565b909950975060408b0135915080821115613ef057600080fd5b613efc8c838d01613d53565b909750955060608b0135915080821115613f1557600080fd5b613f218c838d01613d9b565b945060808b0135915080821115613f3757600080fd5b50613f448b828c01613d53565b999c989b5096995094979396929594505050565b60008060208385031215613f6b57600080fd5b82356001600160401b03811115613f8157600080fd5b613f8d85828601613d53565b90969095509350505050565b60006040828403121561116257600080fd5b600080600060608486031215613fc057600080fd5b83356001600160401b03811115613fd657600080fd5b613fe286828701613d53565b9094509250613ff690508560208601613f99565b90509250925092565b61ffff8116811461101a57600080fd5b8035610c4181613fff565b600082601f83011261402b57600080fd5b8135602061403b6139e483613aa7565b82815260059290921b8401810191818101908684111561405a57600080fd5b8286015b84811015613e795780356001600160401b038082111561407d57600080fd5b818901915089603f83011261409157600080fd5b858201356140a16139e482613aa7565b81815260059190911b830160400190878101908c8311156140c157600080fd5b604085015b838110156140fa578035858111156140dd57600080fd5b6140ec8f6040838a01016139c5565b8452509189019189016140c6565b5087525050509284019250830161405e565b600080600080600060a0868803121561412457600080fd5b85356001600160401b038082111561413b57600080fd5b818801915088601f83011261414f57600080fd5b8135602061415f6139e483613aa7565b82815260059290921b8401810191818101908c84111561417e57600080fd5b948201945b8386101561419c57853582529482019490820190614183565b995050890135965050604088013594506141b86060890161400f565b935060808801359150808211156141ce57600080fd5b506141db8882890161401a565b9150509295509295909350565b6040815260006141fb6040830185613820565b90508260208301529392505050565b6000806060838503121561421d57600080fd5b8235915061422e8460208501613f99565b90509250929050565b600083516142498184602088016137fc565b6101d160f51b90830190815283516142688160028401602088016137fc565b01600201949350505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611b2b57611b2b614274565b81810381811115611b2b57611b2b614274565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806142da57607f821691505b60208210810361116257634e487b7160e01b600052602260045260246000fd5b60006020828403121561430c57600080fd5b8151610f3a81613a75565b600060208083526060830161432f8285018651613875565b81850151604080604087015282825180855260808801915060808160051b8901019450858401935060005b8181101561392257607f198987030183528451614378878251613889565b87015186880185905261438d87860182613820565b965050938601939186019160010161435a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600082825180855260208086019550808260051b8401018186016000805b85811015613c9357868403601f19018a5282518460408101845b600281101561442c57878203835261441a828551613820565b93890193928901929150600101614401565b509b87019b95505050918401916001016143e7565b61444b818a613c0b565b60a06020820152600061446260a08301898b6143a0565b828103604084015261447581888a6143a0565b9050828103606084015261448981876143c9565b9050828103608084015261449e8185876143a0565b9b9a5050505050505050505050565b6000602082840312156144bf57600080fd5b5051919050565b60e0815260006144da60e083018c8e6143a0565b82810360208401526144ec818c613820565b90508281036040840152614501818a8c6143a0565b905082810360608401526145158189613820565b905082810360808401526145298188613c1b565b905082810360a084015261453d8187613820565b905082810360c08401526145528185876143a0565b9d9c50505050505050505050505050565b602081526000613a4f6020830184866143a0565b60006020828403121561458957600080fd5b815160148110610f3a57600080fd5b601f821115613257576000816000526020600020601f850160051c810160208610156145c15750805b601f850160051c820191505b818110156145e0578281556001016145cd565b505050505050565b81516001600160401b0381111561460157614601613930565b6146158161460f84546142c6565b84614598565b602080601f83116001811461464a57600084156146325750858301515b600019600386901b1c1916600185901b1785556145e0565b600085815260208120601f198616915b828110156146795788860151825594840194600190910190840161465a565b50858210156146975787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156146b957600080fd5b81516001600160401b038111156146cf57600080fd5b8201601f810184136146e057600080fd5b80516146ee6139e48261399e565b81815285602083850101111561470357600080fd5b613d4a8260208301602086016137fc565b60006040828403121561472657600080fd5b61472e613946565b823560ff8116811461473f57600080fd5b815260208301356001600160401b038116811461475b57600080fd5b60208201529392505050565b600060a08201905060ff835116825260ff602084015116602083015260408301516001600160401b038082166040850152806060860151166060850152806080860151166080850152505092915050565b600085516147ca818460208a016137fc565b820184868237600090850190815283516147e88183602088016137fc565b019695505050505050565b8183823760009101908152919050565b60a08152600061481660a0830188613794565b6020878185015286604085015261ffff86166060850152838203608085015281855180845282840191506005838260051b8601018489016000805b858110156148be57601f198985038101885283518051808752908a01908a87019080891b88018c01865b828110156148a757858a8303018452614895828651613820565b948e0194938e0193915060010161487b565b509a8c019a97505050938901935050600101614851565b50919e9d5050505050505050505050505050565b604081016148e08285613a57565b61ffff831660208301529392505050565b60006020828403121561490357600080fd5b8151610f3a81613fff565b6000828251808552602080860195506005818360051b8501018287016000805b8681101561499b57601f1988850381018c5283518051808752908801908887019080891b88018a01865b8281101561498457858a8303018452614972828651613820565b948c0194938c01939150600101614958565b509e8a019e9750505093870193505060010161492e565b50919998505050505050505050565b600060a080830160a0845280895180835260c0925060c08601915060c08160051b8701016020808d0160005b84811015614a905760bf198a8503018652815160e060ff825116865284820151614a0286880182613c0b565b50604080830151614a1582890182613a57565b50506060808301518282890152614a2e83890182613820565b9250505060808083015187830382890152614a498382613820565b92505050898201518682038b880152614a6282826143c9565b91505088820151915085810389870152614a7c8183613820565b9785019795505050908201906001016149d6565b505087820390880152614aa3818c61490e565b9450505050508281036040840152614abb8187613820565b90508281036060840152614acf8186613820565b915050614ae2608083018461ffff169052565b9695505050505050565b60008451614afe8184602089016137fc565b845190830190614b128183602089016137fc565b8451910190614b258183602088016137fc565b0195945050505050565b60008251614b418184602087016137fc565b9190910192915050565b6001600160401b03818116838216028082169190828114614b6e57614b6e614274565b505092915050565b60006001600160401b0380841680614b9e57634e487b7160e01b600052601260045260246000fd5b9216919091049291505056fe673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427ded673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427deea2646970667358221220b65648d813c3a0c6b2b50504c580b3fc3c169f4ef57aa68ac6602ea6c19c2e9c64736f6c63430008190033673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427ded0000000000000000000000000000000000000000000000000000000000000001322e302e31342d34386336646436000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102135760003560e01c80639f34df1911610118578063b2299677116100a0578063d5f394881161006f578063d5f39488146107c4578063db4c6b21146107f8578063e30c397814610818578063f2fde38b14610843578063f4f07e991461086357610271565b8063b2299677146106ea578063b4ab01a51461071e578063bff852fa14610750578063c0a673611461079657610271565b8063a47bd1a4116100e7578063a47bd1a414610609578063a4a7cecd14610629578063a83e942c14610649578063a9e954b914610669578063adb7c3f71461069d57610271565b80639f34df1914610589578063a0490fa0146105a9578063a09948b0146105c9578063a0e55336146105e957610271565b80636b58960a1161019b57806379ba50971161016a57806379ba5097146104f25780637f412e23146105075780638da5cb5b146105275780639dd487571461053c5780639eb3ab1f1461056957610271565b80636b58960a1461046a5780636ea3ebe41461048a578063715018a6146104aa57806376b78a06146104bf57610271565b80634c729104116101e25780634c729104146103605780635001f3b51461038d57806352d1902d146103d45780635479d9401461041657806354fd4d501461045557610271565b806321ead36f146102b05780632ebf5d5c146102e65780633679f86414610313578063439fab911461034057610271565b366102715760405162461bcd60e51b8152602060048201526024808201527f5769746e65745265717565737442797465636f6465733a206e6f207472616e736044820152636665727360e01b60648201526084015b60405180910390fd5b34801561027d57600080fd5b506102ae6040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610883565b005b3480156102bc57600080fd5b506102d06102cb366004613768565b6108ef565b6040516102dd91906137d0565b60405180910390f35b3480156102f257600080fd5b506103066103013660046137e3565b6109d7565b6040516102dd919061384c565b34801561031f57600080fd5b5061033361032e3660046137e3565b610a83565b6040516102dd9190613899565b34801561034c57600080fd5b506102ae61035b366004613a1b565b610c46565b34801561036c57600080fd5b5061038061037b3660046137e3565b610e98565b6040516102dd9190613a67565b34801561039957600080fd5b507f00000000000000000000000051376b77d9944bb9c5685b9d9289dd08d399b5e15b6040516001600160a01b0390911681526020016102dd565b3480156103e057600080fd5b506104087fe766e16aefba51e2174a32bdb519ebd43055e315b5a9a9382ec034cf6fe7492681565b6040519081526020016102dd565b34801561042257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000015b60405190151581526020016102dd565b34801561046157600080fd5b50610306610eb0565b34801561047657600080fd5b50610445610485366004613a8a565b610ee0565b34801561049657600080fd5b506104086104a53660046137e3565b610f41565b3480156104b657600080fd5b506102ae610f56565b3480156104cb57600080fd5b506104df6104da3660046137e3565b610f6a565b60405161ffff90911681526020016102dd565b3480156104fe57600080fd5b506102ae610f88565b34801561051357600080fd5b50610408610522366004613aca565b61101d565b34801561053357600080fd5b506103bc611168565b34801561054857600080fd5b5061055c6105573660046137e3565b611184565b6040516102dd9190613ca1565b34801561057557600080fd5b50610408610584366004613e84565b611569565b34801561059557600080fd5b506103336105a43660046137e3565b61194e565b3480156105b557600080fd5b506104086105c4366004613f58565b611ae7565b3480156105d557600080fd5b506103066105e4366004613fab565b611b31565b3480156105f557600080fd5b506103806106043660046137e3565b611c7d565b34801561061557600080fd5b50610408610624366004613f58565b611cfa565b34801561063557600080fd5b5061040861064436600461410c565b611d49565b34801561065557600080fd5b506102d06106643660046137e3565b612b10565b34801561067557600080fd5b507f00000000000000000000000051376b77d9944bb9c5685b9d9289dd08d399b5e13f610408565b3480156106a957600080fd5b506106d17f6f1735ab0000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020016102dd565b3480156106f657600080fd5b507f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427df754610408565b34801561072a57600080fd5b5061073e6107393660046137e3565b612b73565b60405160ff90911681526020016102dd565b34801561075c57600080fd5b5060408051808201909152601d81527f5769746e65745265717565737442797465636f64657344656661756c740000006020820152610306565b3480156107a257600080fd5b506107b66107b13660046137e3565b612bea565b6040516102dd9291906141e8565b3480156107d057600080fd5b506103bc7f00000000000000000000000003232abe800d1638b30432feef300581de323a4e81565b34801561080457600080fd5b506103336108133660046137e3565b612cb6565b34801561082457600080fd5b50600080516020614bcb833981519152546001600160a01b03166103bc565b34801561084f57600080fd5b506102ae61085e366004613a8a565b612e41565b34801561086f57600080fd5b5061030661087e36600461420a565b612eb4565b60408051808201909152601d81527f5769746e65745265717565737442797465636f64657344656661756c740000006020820152816040516020016108c9929190614237565b60408051601f198184030181529082905262461bcd60e51b82526102689160040161384c565b606060006108fb613009565b6000868152602091909152604090206001810154909150808510156109ce5780610925858761428a565b111561093857610935858261429d565b93505b836001600160401b0381111561095057610950613930565b604051908082528060200260200182016040528015610979578160200160208202803683370190505b50925060005b83518110156109cc57600283016000610998888461428a565b8152602001908152602001600020548482815181106109b9576109b96142b0565b602090810291909101015260010161097f565b505b50509392505050565b60606109e1613009565b60008381526006919091016020526040902080546109fe906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2a906142c6565b8015610a775780601f10610a4c57610100808354040283529160200191610a77565b820191906000526020600020905b815481529060010190602001808311610a5a57829003601f168201915b50505050509050919050565b604080518082019091526000815260606020820152610aa0613009565b600083815260029190910160205260409081902081518083019092528054829060ff16600b811115610ad457610ad461385f565b600b811115610ae557610ae561385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610bfe5760008481526020902060408051808201909152600284029091018054829060ff166009811115610b4857610b4861385f565b6009811115610b5957610b5961385f565b8152602001600182018054610b6d906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b99906142c6565b8015610be65780601f10610bbb57610100808354040283529160200191610be6565b820191906000526020600020905b815481529060010190602001808311610bc957829003601f168201915b50505050508152505081526020019060010190610b0e565b505050915250508051909150600b811115610c1b57610c1b61385f565b60ff16600003610c415760405163b020432960e01b815260048101839052602401610268565b919050565b600080516020614bab833981519152546001600160a01b031680610ca75781806020019051810190610c7891906142fa565b600080516020614bab83398151915280546001600160a01b0319166001600160a01b0383161790559050610d0d565b336001600160a01b03821614610d0d5760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a206e6f74207468652060448201526437bbb732b960d91b6064820152608401610268565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec546001600160a01b031615610df3577f00000000000000000000000051376b77d9944bb9c5685b9d9289dd08d399b5e16001600160a01b03167f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec546001600160a01b031603610df35760405162461bcd60e51b815260206004820152602b60248201527f5769746e65745265717565737442797465636f6465733a20616c72656164792060448201526a1a5b9a5d1a585b1a5e995960aa1b6064820152608401610268565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427dec80546001600160a01b0319167f00000000000000000000000051376b77d9944bb9c5685b9d9289dd08d399b5e16001600160a01b038181169283179093553f9183167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f6610e7f610eb0565b604051610e8c919061384c565b60405180910390a45050565b6000610ea38261302d565b6003015460ff1692915050565b6060610edb7f322e302e31342d3438633664643600000000000000000000000000000000000061304a565b905090565b600080516020614bab833981519152546000906001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000018015610f3a5750826001600160a01b0316816001600160a01b0316145b9392505050565b6000610f4c8261302d565b6004015492915050565b610f5e6130f5565b610f686000613127565b565b6000610f758261302d565b60030154610100900461ffff1692915050565b3380610fa9600080516020614bcb833981519152546001600160a01b031690565b6001600160a01b0316146110115760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610268565b61101a81613127565b50565b6000816040516020016110309190613899565b6040516020818303038152906040528051906020012090506000611052613009565b600083815260029190910160205260409020805490915060ff16600b81111561107d5761107d61385f565b60ff1615801561108f57506001810154155b156111625760405163daf4b0ef60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063daf4b0ef906110cb908690600401614317565b60006040518083038186803b1580156110e357600080fd5b505af41580156110f7573d6000803e3d6000fd5b50508451835490925083915060ff1916600183600b81111561111b5761111b61385f565b021790555061112e8184602001516131c8565b6040518281527feb8b5415ec9648a9403c5cce90965dfa18af4388f474323741018a06e231be829060200160405180910390a15b50919050565b600080516020614bab833981519152546001600160a01b031690565b6111c56040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b6111cd613009565b60008381526003919091016020908152604091829020825160e08101909352805460ff808216855291928401916101009091041660048111156112125761121261385f565b60048111156112235761122361385f565b8152815460209091019062010000900460ff1660138111156112475761124761385f565b60138111156112585761125861385f565b815260200160018201805461126c906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611298906142c6565b80156112e55780601f106112ba576101008083540402835291602001916112e5565b820191906000526020600020905b8154815290600101906020018083116112c857829003601f168201915b505050505081526020016002820180546112fe906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461132a906142c6565b80156113775780601f1061134c57610100808354040283529160200191611377565b820191906000526020600020905b81548152906001019060200180831161135a57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561148357600084815260208120604080518082019091529160028086029092019190835b828210156114705783820180546113e3906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461140f906142c6565b801561145c5780601f106114315761010080835404028352916020019161145c565b820191906000526020600020905b81548152906001019060200180831161143f57829003601f168201915b5050505050815260200190600101906113cd565b50505050815260200190600101906113a5565b50505050815260200160048201805461149b906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546114c7906142c6565b80156115145780601f106114e957610100808354040283529160200191611514565b820191906000526020600020905b8154815290600101906020018083116114f757829003601f168201915b5050505050815250509050600060048111156115325761153261385f565b816020015160048111156115485761154861385f565b03610c4157604051633552703b60e21b815260048101839052602401610268565b600088600481111561157d5761157d61385f565b604051631746472760e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c916317464727916115c191908c908c908c908c908c908c908c90600401614441565b602060405180830381865af41580156115de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160291906144ad565b9050600061160e613009565b60008381526003919091016020526040902054610100900460ff16600481111561163a5761163a61385f565b03611942576040518060e001604052806116cf8a8a604051806040016040528060018152602001600160fd1b8152508b8b604051806040016040528060018152602001600160fd1b8152508c604051806040016040528060018152602001600160fd1b8152508d8d6040516020016116bb9a999897969594939291906144c6565b60405160208183030381529060405261325c565b60ff1681526020018a60048111156116e9576116e961385f565b815260200173268631e002ee8c23f4c124afbb6fe5dbbaa6d58c63f3106f7886866040518363ffffffff1660e01b8152600401611727929190614563565b602060405180830381865af4158015611744573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117689190614577565b60138111156117795761177961385f565b815260200189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8a0181900481028201810190925288815291810191908990899081908401838280828437600092019190915250505090825250602080820187905260408051601f870183900483028101830182528681529201919086908690819084018382808284376000920191909152505050915250611838613009565b6000838152600391909101602090815260409091208251815460ff90911660ff19821681178355928401519192839161ffff1916176101008360048111156118825761188261385f565b021790555060408201518154829062ff00001916620100008360138111156118ac576118ac61385f565b0217905550606082015160018201906118c590826145e8565b50608082015160028201906118da90826145e8565b5060a082015180516118f6916003840191602090910190613503565b5060c0820151600482019061190b90826145e8565b50506040518281527fd4d6341509dbdeb3a349aa77cc95076376f8e1c84fd3d27e0081424b01909272915060200160405180910390a15b98975050505050505050565b60408051808201909152600081526060602082015261196b613009565b60020160006119798461302d565b6001015481526020810191909152604090810160002081518083019092528054829060ff16600b8111156119af576119af61385f565b600b8111156119c0576119c061385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ad95760008481526020902060408051808201909152600284029091018054829060ff166009811115611a2357611a2361385f565b6009811115611a3457611a3461385f565b8152602001600182018054611a48906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611a74906142c6565b8015611ac15780601f10611a9657610100808354040283529160200191611ac1565b820191906000526020600020905b815481529060010190602001808311611aa457829003601f168201915b505050505081525050815260200190600101906119e9565b505050915250909392505050565b6000611b2883838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506133d192505050565b90505b92915050565b60405163acbade1f60e01b81526001600160401b0383166004820152600560f91b602482015260609073268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063acbade1f90604401600060405180830381865af4158015611b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611bbe91908101906146a7565b8484611bd7611bd236879003870187614714565b613423565b6040516316c0d2a160e11b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91632d81a54291611c0d9190600401614767565b600060405180830381865af4158015611c2a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c5291908101906146a7565b604051602001611c6594939291906147b8565b60405160208183030381529060405290509392505050565b600080611c88613009565b60008481526003919091016020526040902054610100900460ff166004811115611cb457611cb461385f565b03611cd557604051633552703b60e21b815260048101839052602401610268565b611cdd613009565b600092835260030160205250604090205462010000900460ff1690565b6000611d04613009565b60010160008484604051602001611d1c9291906147f3565b60405160208183030381529060405280519060200120815260200190815260200160002054905092915050565b6000808686868686604051602001611d65959493929190614803565b604051602081830303815290604052805190602001209050611d85613009565b600082815260059190910160205260408120549250611da2613009565b6000838152600591909101602052604090205403612b06578651600003611e195760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a206e6f2072657472696044820152646576616c7360d81b6064820152608401610268565b8251875114611e785760405162461bcd60e51b815260206004820152602560248201527f5769746e65745265717565737442797465636f6465733a2061726773206d69736044820152640dac2e8c6d60db1b6064820152608401610268565b6000611e82613009565b600088815260029190910160205260409081902081518083019092528054829060ff16600b811115611eb657611eb661385f565b600b811115611ec757611ec761385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611fe05760008481526020902060408051808201909152600284029091018054829060ff166009811115611f2a57611f2a61385f565b6009811115611f3b57611f3b61385f565b8152602001600182018054611f4f906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054611f7b906142c6565b8015611fc85780601f10611f9d57610100808354040283529160200191611fc8565b820191906000526020600020905b815481529060010190602001808311611fab57829003601f168201915b50505050508152505081526020019060010190611ef0565b505050508152505090506000611ff4613009565b600088815260029190910160205260409081902081518083019092528054829060ff16600b8111156120285761202861385f565b600b8111156120395761203961385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156121525760008481526020902060408051808201909152600284029091018054829060ff16600981111561209c5761209c61385f565b60098111156120ad576120ad61385f565b81526020016001820180546120c1906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546120ed906142c6565b801561213a5780601f1061210f5761010080835404028352916020019161213a565b820191906000526020600020905b81548152906001019060200180831161211d57829003601f168201915b50505050508152505081526020019060010190612062565b505050508152505090506000808a516001600160401b0381111561217857612178613930565b6040519080825280602002602001820160405280156121ea57816020015b6121d76040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816121965790505b50905060005b815181101561270057612201613009565b60030160008d8381518110612218576122186142b0565b6020908102919091018101518252818101929092526040908101600020815160e08101909252805460ff808216845292939192918401916101009091041660048111156122675761226761385f565b60048111156122785761227861385f565b8152815460209091019062010000900460ff16601381111561229c5761229c61385f565b60138111156122ad576122ad61385f565b81526020016001820180546122c1906142c6565b80601f01602080910402602001604051908101604052809291908181526020018280546122ed906142c6565b801561233a5780601f1061230f5761010080835404028352916020019161233a565b820191906000526020600020905b81548152906001019060200180831161231d57829003601f168201915b50505050508152602001600282018054612353906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461237f906142c6565b80156123cc5780601f106123a1576101008083540402835291602001916123cc565b820191906000526020600020905b8154815290600101906020018083116123af57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156124d857600084815260208120604080518082019091529160028086029092019190835b828210156124c5578382018054612438906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612464906142c6565b80156124b15780601f10612486576101008083540402835291602001916124b1565b820191906000526020600020905b81548152906001019060200180831161249457829003601f168201915b505050505081526020019060010190612422565b50505050815260200190600101906123fa565b5050505081526020016004820180546124f0906142c6565b80601f016020809104026020016040519081016040528092919081815260200182805461251c906142c6565b80156125695780601f1061253e57610100808354040283529160200191612569565b820191906000526020600020905b81548152906001019060200180831161254c57829003601f168201915b505050505081525050828281518110612584576125846142b0565b6020026020010181905250806000036125bd57816000815181106125aa576125aa6142b0565b6020026020010151604001519250612662565b8260138111156125cf576125cf61385f565b8282815181106125e1576125e16142b0565b60200260200101516040015160138111156125fe576125fe61385f565b146126625760405162461bcd60e51b815260206004820152602e60248201527f5769746e65745265717565737442797465636f6465733a206d69736d6174636860448201526d696e672072657472696576616c7360901b6064820152608401610268565b818181518110612674576126746142b0565b60200260200101516000015160ff16888281518110612695576126956142b0565b60200260200101515110156126f85760405162461bcd60e51b8152602060048201526024808201527f5769746e65745265717565737442797465636f6465733a206d697373696e67206044820152636172677360e01b6064820152608401610268565b6001016121f0565b508160138111156127135761271361385f565b604051630160730f60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91630160730f9161274b91908c906004016148d2565b602060405180830381865af4158015612768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278c91906148f1565b975060008173268631e002ee8c23f4c124afbb6fe5dbbaa6d58c63b6349ebd90918a8873268631e002ee8c23f4c124afbb6fe5dbbaa6d58c631c02d22b90916040518263ffffffff1660e01b81526004016127e79190614317565b600060405180830381865af4158015612804573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261282c91908101906146a7565b604051631c02d22b60e01b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c90631c02d22b90612863908c90600401614317565b600060405180830381865af4158015612880573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128a891908101906146a7565b8e6040518663ffffffff1660e01b81526004016128c99594939291906149aa565b600060405180830381865af41580156128e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261290e91908101906146a7565b905061ffff815111156129755760405162461bcd60e51b815260206004820152602960248201527f5769746e65745265717565737442797465636f6465733a20746f6f20686561766044820152681e481c995c5d595cdd60ba1b6064820152608401610268565b61297e816133d1565b965086612989613009565b60008881526005919091016020526040902055806129a5613009565b600089815260069190910160205260409020906129c290826145e8565b506040518060e001604052808981526020018c81526020018881526020018460138111156129f2576129f261385f565b81526020018a61ffff1681526020018d81526020018b815250612a13613009565b600089815260049190910160209081526040909120825180519192612a3d9284929091019061355d565b50602082015181600101556040820151816002015560608201518160030160006101000a81548160ff02191690836013811115612a7c57612a7c61385f565b0217905550608082015160038201805461ffff9092166101000262ffff001990921691909117905560a08201518051612abf9160048401916020909101906135b6565b5060c091909101516005909101556040518781527fe8845fcb11242df46ec5ca06bf7d381c3c6e9cc4f110abacffc933558e8dd67d9060200160405180910390a150505050505b5095945050505050565b6060612b1b8261302d565b600401805480602002602001604051908101604052809291908181526020018280548015610a7757602002820191906000526020600020905b815481526020019060010190808311612b545750505050509050919050565b600080612b7e613009565b60008481526003919091016020526040902054610100900460ff166004811115612baa57612baa61385f565b03612bcb57604051633552703b60e21b815260048101839052602401610268565b612bd3613009565b600092835260030160205250604090205460ff1690565b60606000612bf6613009565b600084815260209190915260409020612c0d613009565b6000858152602091909152604090206001015481548290612c2d906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612c59906142c6565b8015612ca65780601f10612c7b57610100808354040283529160200191612ca6565b820191906000526020600020905b815481529060010190602001808311612c8957829003601f168201915b5050505050915091509150915091565b604080518082019091526000815260606020820152612cd3613009565b6002016000612ce18461302d565b6005015481526020810191909152604090810160002081518083019092528054829060ff16600b811115612d1757612d1761385f565b600b811115612d2857612d2861385f565b815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ad95760008481526020902060408051808201909152600284029091018054829060ff166009811115612d8b57612d8b61385f565b6009811115612d9c57612d9c61385f565b8152602001600182018054612db0906142c6565b80601f0160208091040260200160405190810160405280929190818152602001828054612ddc906142c6565b8015612e295780601f10612dfe57610100808354040283529160200191612e29565b820191906000526020600020905b815481529060010190602001808311612e0c57829003601f168201915b50505050508152505081526020019060010190612d51565b612e496130f5565b600080516020614bcb83398151915280546001600160a01b0319166001600160a01b038316908117909155612e7c611168565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60606000612ec1846109d7565b805160405163acbade1f60e01b81526001600160401b039091166004820152600560f91b602482015290915073268631e002ee8c23f4c124afbb6fe5dbbaa6d58c9063acbade1f90604401600060405180830381865af4158015612f29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f5191908101906146a7565b81612f64611bd236879003870187614714565b6040516316c0d2a160e11b815273268631e002ee8c23f4c124afbb6fe5dbbaa6d58c91632d81a54291612f9a9190600401614767565b600060405180830381865af4158015612fb7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fdf91908101906146a7565b604051602001612ff193929190614aec565b60405160208183030381529060405291505092915050565b7f673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427def90565b6000613037613009565b6000928352600401602052506040902090565b60606000613057836134ca565b6001600160401b0381111561306e5761306e613930565b6040519080825280601f01601f191660200182016040528015613098576020820181803683370190505b50905060005b81518110156130ee578381602081106130b9576130b96142b0565b1a60f81b8282815181106130cf576130cf6142b0565b60200101906001600160f81b031916908160001a90535060010161309e565b5092915050565b336130fe611168565b6001600160a01b031614610f685760405163118cdaa760e01b8152336004820152602401610268565b600080516020614bcb83398151915280546001600160a01b0319169055600061314e611168565b9050806001600160a01b0316826001600160a01b0316146131c457600080516020614bab83398151915280546001600160a01b0319166001600160a01b0384811691821790925560405190918316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b5050565b60005b815181101561325757826001018282815181106131ea576131ea6142b0565b60209081029190910181015182546001818101855560009485529290932081516002909402018054919390929091839160ff19909116908360098111156132335761323361385f565b02179055506020820151600182019061324c90826145e8565b5050506001016131cb565b505050565b600060038251101561327057506000919050565b8151600090600119015b808210156133ca57601760fa1b6001600160f81b0319168483815181106132a3576132a36142b0565b01602001516001600160f81b0319161480156132ef5750601760fa1b6001600160f81b0319168483600201815181106132de576132de6142b0565b01602001516001600160f81b031916145b801561332c5750600360fc1b6001600160f81b03191684836001018151811061331a5761331a6142b0565b01602001516001600160f81b03191610155b80156133695750603960f81b6001600160f81b031916848360010181518110613357576133576142b0565b01602001516001600160f81b03191611155b156133bf576000600360fc1b60f81c85846001018151811061338d5761338d6142b0565b602001015160f81c60f81b60f81c0360010190508360ff168160ff1611156133b3578093505b6003830192505061327a565b60019091019061327a565b5050919050565b60006002826040516133e39190614b2f565b602060405180830381855afa158015613400573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611b2b91906144ad565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280836000015160ff168152602001603360ff16815260200183602001516001600160401b03168152602001836020015160646134949190614b4b565b6001600160401b03168152602001836000015160ff1684602001516134b99190614b76565b6001600160401b0316905292915050565b60005b6020811015610c41578181602081106134e8576134e86142b0565b1a60f81b6001600160f81b03191615610c41576001016134cd565b82805482825590600052602060002090600202810192821561354d579160200282015b8281111561354d57825161353d90839060026135fd565b5091602001919060020190613526565b50613559929150613642565b5090565b8280548282559060005260206000209081019282156135aa579160200282015b828111156135aa578251805161359a91849160209091019061365f565b509160200191906001019061357d565b506135599291506136a5565b8280548282559060005260206000209081019282156135f1579160200282015b828111156135f15782518255916020019190600101906135d6565b506135599291506136c2565b8260028101928215613636579160200282015b82811115613636578251829061362690826145e8565b5091602001919060010190613610565b506135599291506136d7565b8082111561355957600061365682826136f4565b50600201613642565b828054828255906000526020600020908101928215613636579160200282015b82811115613636578251829061369590826145e8565b509160200191906001019061367f565b808211156135595760006136b98282613710565b506001016136a5565b5b8082111561355957600081556001016136c3565b808211156135595760006136eb828261372e565b506001016136d7565b506000613701828261372e565b50610f6890600101600061372e565b508054600082559060005260206000209081019061101a91906136d7565b50805461373a906142c6565b6000825580601f1061374a575050565b601f01602090049060005260206000209081019061101a91906136c2565b60008060006060848603121561377d57600080fd5b505081359360208301359350604090920135919050565b60008151808452602080850194506020840160005b838110156137c5578151875295820195908201906001016137a9565b509495945050505050565b602081526000611b286020830184613794565b6000602082840312156137f557600080fd5b5035919050565b60005b838110156138175781810151838201526020016137ff565b50506000910152565b600081518084526138388160208601602086016137fc565b601f01601f19169290920160200192915050565b602081526000611b286020830184613820565b634e487b7160e01b600052602160045260246000fd5b600c81106138855761388561385f565b9052565b600a81106138855761388561385f565b60006020808352606083016138b18285018651613875565b81850151604080604087015282825180855260808801915060808160051b8901019450858401935060005b8181101561392257607f1989870301835284516138fa878251613889565b87015186880185905261390f87860182613820565b96505093860193918601916001016138dc565b509398975050505050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561396857613968613930565b60405290565b604051601f8201601f191681016001600160401b038111828210171561399657613996613930565b604052919050565b60006001600160401b038211156139b7576139b7613930565b50601f01601f191660200190565b600082601f8301126139d657600080fd5b81356139e96139e48261399e565b61396e565b8181528460208386010111156139fe57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613a2d57600080fd5b81356001600160401b03811115613a4357600080fd5b613a4f848285016139c5565b949350505050565b601481106138855761388561385f565b60208101611b2b8284613a57565b6001600160a01b038116811461101a57600080fd5b600060208284031215613a9c57600080fd5b8135610f3a81613a75565b60006001600160401b03821115613ac057613ac0613930565b5060051b60200190565b60006020808385031215613add57600080fd5b82356001600160401b0380821115613af457600080fd5b81850191506040808388031215613b0a57600080fd5b613b12613946565b8335600c8110613b2157600080fd5b81528385013583811115613b3457600080fd5b80850194505087601f850112613b4957600080fd5b8335613b576139e482613aa7565b81815260059190911b8501860190868101908a831115613b7657600080fd5b8787015b83811015613bf757803587811115613b925760008081fd5b8801808d03601f1901871315613ba85760008081fd5b613bb0613946565b8a820135600a8110613bc25760008081fd5b81528188013589811115613bd65760008081fd5b613be48f8d838601016139c5565b828d015250845250918801918801613b7a565b509683019690965250979650505050505050565b600581106138855761388561385f565b600082825180855260208086019550808260051b8401018186016000805b85811015613c9357868403601f19018a5282518460408101845b6002811015613c7e578782038352613c6c828551613820565b93890193928901929150600101613c53565b509b87019b9550505091840191600101613c39565b509198975050505050505050565b6020815260ff825116602082015260006020830151613cc36040840182613c0b565b506040830151613cd66060840182613a57565b50606083015160e06080840152613cf1610100840182613820565b90506080840151601f19808584030160a0860152613d0f8383613820565b925060a08601519150808584030160c0860152613d2c8383613c1b565b925060c08601519150808584030160e086015250613d4a8282613820565b95945050505050565b60008083601f840112613d6557600080fd5b5081356001600160401b03811115613d7c57600080fd5b602083019150836020828501011115613d9457600080fd5b9250929050565b600082601f830112613dac57600080fd5b81356020613dbc6139e483613aa7565b82815260059290921b84018101918181019086841115613ddb57600080fd5b8286015b84811015613e795780356001600160401b0380821115613dff5760008081fd5b818901915089603f830112613e145760008081fd5b613e1c613946565b80606084018c811115613e2f5760008081fd5b8885015b81811015613e6757803585811115613e4b5760008081fd5b613e598f8c838a01016139c5565b855250928901928901613e33565b50508652505050918301918301613ddf565b509695505050505050565b60008060008060008060008060a0898b031215613ea057600080fd5b883560058110613eaf57600080fd5b975060208901356001600160401b0380821115613ecb57600080fd5b613ed78c838d01613d53565b909950975060408b0135915080821115613ef057600080fd5b613efc8c838d01613d53565b909750955060608b0135915080821115613f1557600080fd5b613f218c838d01613d9b565b945060808b0135915080821115613f3757600080fd5b50613f448b828c01613d53565b999c989b5096995094979396929594505050565b60008060208385031215613f6b57600080fd5b82356001600160401b03811115613f8157600080fd5b613f8d85828601613d53565b90969095509350505050565b60006040828403121561116257600080fd5b600080600060608486031215613fc057600080fd5b83356001600160401b03811115613fd657600080fd5b613fe286828701613d53565b9094509250613ff690508560208601613f99565b90509250925092565b61ffff8116811461101a57600080fd5b8035610c4181613fff565b600082601f83011261402b57600080fd5b8135602061403b6139e483613aa7565b82815260059290921b8401810191818101908684111561405a57600080fd5b8286015b84811015613e795780356001600160401b038082111561407d57600080fd5b818901915089603f83011261409157600080fd5b858201356140a16139e482613aa7565b81815260059190911b830160400190878101908c8311156140c157600080fd5b604085015b838110156140fa578035858111156140dd57600080fd5b6140ec8f6040838a01016139c5565b8452509189019189016140c6565b5087525050509284019250830161405e565b600080600080600060a0868803121561412457600080fd5b85356001600160401b038082111561413b57600080fd5b818801915088601f83011261414f57600080fd5b8135602061415f6139e483613aa7565b82815260059290921b8401810191818101908c84111561417e57600080fd5b948201945b8386101561419c57853582529482019490820190614183565b995050890135965050604088013594506141b86060890161400f565b935060808801359150808211156141ce57600080fd5b506141db8882890161401a565b9150509295509295909350565b6040815260006141fb6040830185613820565b90508260208301529392505050565b6000806060838503121561421d57600080fd5b8235915061422e8460208501613f99565b90509250929050565b600083516142498184602088016137fc565b6101d160f51b90830190815283516142688160028401602088016137fc565b01600201949350505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611b2b57611b2b614274565b81810381811115611b2b57611b2b614274565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806142da57607f821691505b60208210810361116257634e487b7160e01b600052602260045260246000fd5b60006020828403121561430c57600080fd5b8151610f3a81613a75565b600060208083526060830161432f8285018651613875565b81850151604080604087015282825180855260808801915060808160051b8901019450858401935060005b8181101561392257607f198987030183528451614378878251613889565b87015186880185905261438d87860182613820565b965050938601939186019160010161435a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600082825180855260208086019550808260051b8401018186016000805b85811015613c9357868403601f19018a5282518460408101845b600281101561442c57878203835261441a828551613820565b93890193928901929150600101614401565b509b87019b95505050918401916001016143e7565b61444b818a613c0b565b60a06020820152600061446260a08301898b6143a0565b828103604084015261447581888a6143a0565b9050828103606084015261448981876143c9565b9050828103608084015261449e8185876143a0565b9b9a5050505050505050505050565b6000602082840312156144bf57600080fd5b5051919050565b60e0815260006144da60e083018c8e6143a0565b82810360208401526144ec818c613820565b90508281036040840152614501818a8c6143a0565b905082810360608401526145158189613820565b905082810360808401526145298188613c1b565b905082810360a084015261453d8187613820565b905082810360c08401526145528185876143a0565b9d9c50505050505050505050505050565b602081526000613a4f6020830184866143a0565b60006020828403121561458957600080fd5b815160148110610f3a57600080fd5b601f821115613257576000816000526020600020601f850160051c810160208610156145c15750805b601f850160051c820191505b818110156145e0578281556001016145cd565b505050505050565b81516001600160401b0381111561460157614601613930565b6146158161460f84546142c6565b84614598565b602080601f83116001811461464a57600084156146325750858301515b600019600386901b1c1916600185901b1785556145e0565b600085815260208120601f198616915b828110156146795788860151825594840194600190910190840161465a565b50858210156146975787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156146b957600080fd5b81516001600160401b038111156146cf57600080fd5b8201601f810184136146e057600080fd5b80516146ee6139e48261399e565b81815285602083850101111561470357600080fd5b613d4a8260208301602086016137fc565b60006040828403121561472657600080fd5b61472e613946565b823560ff8116811461473f57600080fd5b815260208301356001600160401b038116811461475b57600080fd5b60208201529392505050565b600060a08201905060ff835116825260ff602084015116602083015260408301516001600160401b038082166040850152806060860151166060850152806080860151166080850152505092915050565b600085516147ca818460208a016137fc565b820184868237600090850190815283516147e88183602088016137fc565b019695505050505050565b8183823760009101908152919050565b60a08152600061481660a0830188613794565b6020878185015286604085015261ffff86166060850152838203608085015281855180845282840191506005838260051b8601018489016000805b858110156148be57601f198985038101885283518051808752908a01908a87019080891b88018c01865b828110156148a757858a8303018452614895828651613820565b948e0194938e0193915060010161487b565b509a8c019a97505050938901935050600101614851565b50919e9d5050505050505050505050505050565b604081016148e08285613a57565b61ffff831660208301529392505050565b60006020828403121561490357600080fd5b8151610f3a81613fff565b6000828251808552602080860195506005818360051b8501018287016000805b8681101561499b57601f1988850381018c5283518051808752908801908887019080891b88018a01865b8281101561498457858a8303018452614972828651613820565b948c0194938c01939150600101614958565b509e8a019e9750505093870193505060010161492e565b50919998505050505050505050565b600060a080830160a0845280895180835260c0925060c08601915060c08160051b8701016020808d0160005b84811015614a905760bf198a8503018652815160e060ff825116865284820151614a0286880182613c0b565b50604080830151614a1582890182613a57565b50506060808301518282890152614a2e83890182613820565b9250505060808083015187830382890152614a498382613820565b92505050898201518682038b880152614a6282826143c9565b91505088820151915085810389870152614a7c8183613820565b9785019795505050908201906001016149d6565b505087820390880152614aa3818c61490e565b9450505050508281036040840152614abb8187613820565b90508281036060840152614acf8186613820565b915050614ae2608083018461ffff169052565b9695505050505050565b60008451614afe8184602089016137fc565b845190830190614b128183602089016137fc565b8451910190614b258183602088016137fc565b0195945050505050565b60008251614b418184602087016137fc565b9190910192915050565b6001600160401b03818116838216028082169190828114614b6e57614b6e614274565b505092915050565b60006001600160401b0380841680614b9e57634e487b7160e01b600052601260045260246000fd5b9216919091049291505056fe673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427ded673359bdfd0124f9962355e7aed2d07d989b0d4bc4cbe2c94c295e0f81427deea2646970667358221220b65648d813c3a0c6b2b50504c580b3fc3c169f4ef57aa68ac6602ea6c19c2e9c64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000001322e302e31342d34386336646436000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _upgradable (bool): True
Arg [1] : _versionTag (bytes32): 0x322e302e31342d34386336646436000000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 322e302e31342d34386336646436000000000000000000000000000000000000
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.