Source Code
Overview
POL Balance
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6447818 | 325 days ago | Contract Creation | 0 POL |
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:
WitnetPriceFeedsDefault
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "../WitnetUpgradableBase.sol"; import "../../WitnetPriceFeeds.sol"; import "../../data/WitnetPriceFeedsData.sol"; import "../../libs/WitnetPriceFeedsLib.sol"; import "../../patterns/Ownable2Step.sol"; /// @title WitnetPriceFeeds: Price Feeds live repository reliant on the Witnet Oracle blockchain. /// @author Guillermo Díaz <[email protected]> contract WitnetPriceFeedsDefault is Ownable2Step, WitnetPriceFeeds, WitnetPriceFeedsData, WitnetUpgradableBase { using Witnet for bytes; using Witnet for Witnet.Result; using WitnetV2 for WitnetV2.Response; using WitnetV2 for WitnetV2.RadonSLA; function class() virtual override(WitnetFeeds, WitnetUpgradableBase) public view returns (string memory) { return type(WitnetPriceFeedsDefault).name; } bytes4 immutable public override specs = type(IWitnetPriceFeeds).interfaceId; WitnetOracle immutable public override witnet; WitnetV2.RadonSLA private __defaultRadonSLA; uint16 private __baseFeeOverheadPercentage; constructor( WitnetOracle _wrb, bool _upgradable, bytes32 _versionTag ) Ownable(address(msg.sender)) WitnetUpgradableBase( _upgradable, _versionTag, "io.witnet.proxiable.feeds.price" ) { witnet = _wrb; } // solhint-disable-next-line payable-fallback fallback() override external { if ( msg.sig == IWitnetPriceSolver.solve.selector && msg.sender == address(this) ) { address _solver = __records_(bytes4(bytes8(msg.data) << 32)).solver; require( _solver != address(0), "WitnetPriceFeeds: unsettled solver" ); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), _solver, ptr, calldatasize(), 0, 0) let size := returndatasize() returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } else { revert("WitnetPriceFeeds: not implemented"); } } // ================================================================================================================ // --- 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 = owner(); if (_owner == address(0)) { // set owner as specified by first argument in _initData _owner = abi.decode(_initData, (address)); _transferOwnership(_owner); // settle default Radon SLA upon first initialization __defaultRadonSLA = WitnetV2.RadonSLA({ committeeSize: 10, witnessingFeeNanoWit: 2 * 10 ** 8 // 0.2 $WIT }); // settle default base fee overhead percentage __baseFeeOverheadPercentage = 10; } else { // only the owner can initialize: require( msg.sender == _owner, "WitnetPriceFeeds: not the owner" ); } if ( __proxiable().codehash != bytes32(0) && __proxiable().codehash == codehash() ) { revert("WitnetPriceFeeds: already upgraded"); } __proxiable().codehash = codehash(); require( address(witnet).code.length > 0, "WitnetPriceFeeds: inexistent oracle" ); require( witnet.specs() == type(IWitnetOracle).interfaceId, "WitnetPriceFeeds: uncompliant oracle" ); 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 = owner(); return ( // false if the WRB is intrinsically not upgradable, or `_from` is no owner isUpgradable() && _owner == _from ); } // ================================================================================================================ // --- Implements 'IFeeds' ---------------------------------------------------------------------------------------- /// @notice Returns unique hash determined by the combination of data sources being used /// @notice on non-routed price feeds, and dependencies of routed price feeds. /// @dev Ergo, `footprint()` changes if any data source is modified, or the dependecy tree /// @dev on any routed price feed is altered. function footprint() virtual override public view returns (bytes4 _footprint) { if (__storage().ids.length > 0) { _footprint = _footprintOf(__storage().ids[0]); for (uint _ix = 1; _ix < __storage().ids.length; _ix ++) { _footprint ^= _footprintOf(__storage().ids[_ix]); } } } function hash(string memory caption) virtual override public pure returns (bytes4) { return bytes4(keccak256(bytes(caption))); } function lookupCaption(bytes4 feedId) override public view returns (string memory) { return __records_(feedId).caption; } function supportedFeeds() virtual override external view returns (bytes4[] memory _ids, string[] memory _captions, bytes32[] memory _solvers) { _ids = __storage().ids; _captions = new string[](_ids.length); _solvers = new bytes32[](_ids.length); for (uint _ix = 0; _ix < _ids.length; _ix ++) { Record storage __record = __records_(_ids[_ix]); _captions[_ix] = __record.caption; _solvers[_ix] = address(__record.solver) == address(0) ? __record.radHash : bytes32(bytes20(__record.solver)); } } function supportsCaption(string calldata caption) virtual override external view returns (bool) { bytes4 feedId = hash(caption); return hash(__records_(feedId).caption) == feedId; } function totalFeeds() override external view returns (uint256) { return __storage().ids.length; } // ================================================================================================================ // --- Implements 'IWitnetFeeds' ---------------------------------------------------------------------------------- function defaultRadonSLA() override public view returns (Witnet.RadonSLA memory) { return __defaultRadonSLA.toV1(); } function estimateUpdateBaseFee(uint256 _evmGasPrice) virtual override public view returns (uint) { return (witnet.estimateBaseFee(_evmGasPrice, 32) * (100 + __baseFeeOverheadPercentage) ) / 100; } function lastValidQueryId(bytes4 feedId) override public view returns (uint256) { return _lastValidQueryId(feedId); } function lastValidResponse(bytes4 feedId) override public view returns (WitnetV2.Response memory) { return witnet.getQueryResponse(_lastValidQueryId(feedId)); } function latestUpdateQueryId(bytes4 feedId) override public view returns (uint256) { return __records_(feedId).latestUpdateQueryId; } function latestUpdateRequest(bytes4 feedId) override external view returns (WitnetV2.Request memory) { return witnet.getQueryRequest(latestUpdateQueryId(feedId)); } function latestUpdateResponse(bytes4 feedId) override external view returns (WitnetV2.Response memory) { return witnet.getQueryResponse(latestUpdateQueryId(feedId)); } function latestUpdateResultError(bytes4 feedId) override external view returns (Witnet.ResultError memory) { return witnet.getQueryResultError(latestUpdateQueryId(feedId)); } function latestUpdateResponseStatus(bytes4 feedId) override public view returns (WitnetV2.ResponseStatus) { return _checkQueryResponseStatus(latestUpdateQueryId(feedId)); } function lookupWitnetBytecode(bytes4 feedId) override external view returns (bytes memory) { Record storage __record = __records_(feedId); require( __record.radHash != 0, "WitnetPriceFeeds: no RAD hash" ); return registry().bytecodeOf(__record.radHash); } function lookupWitnetRadHash(bytes4 feedId) override public view returns (bytes32) { return __records_(feedId).radHash; } function lookupWitnetRetrievals(bytes4 feedId) override external view returns (Witnet.RadonRetrieval[] memory _retrievals) { bytes32[] memory _hashes = registry().lookupRadonRequestSources(lookupWitnetRadHash(feedId)); _retrievals = new Witnet.RadonRetrieval[](_hashes.length); for (uint _ix = 0; _ix < _retrievals.length; _ix ++) { _retrievals[_ix] = registry().lookupRadonRetrieval(_hashes[_ix]); } } function registry() public view virtual override returns (WitnetRequestBytecodes) { return WitnetOracle(address(witnet)).registry(); } function requestUpdate(bytes4 feedId) external payable virtual override returns (uint256) { return __requestUpdate(feedId, __defaultRadonSLA); } function requestUpdate(bytes4 feedId, WitnetV2.RadonSLA calldata updateSLA) public payable virtual override returns (uint256 _usedFunds) { require( updateSLA.equalOrGreaterThan(__defaultRadonSLA), "WitnetPriceFeeds: unsecure update" ); return __requestUpdate(feedId, updateSLA); } // ================================================================================================================ // --- Implements 'IWitnetFeedsAdmin' ----------------------------------------------------------------------------- function owner() virtual override (IWitnetFeedsAdmin, Ownable) public view returns (address) { return Ownable.owner(); } function acceptOwnership() virtual override (IWitnetFeedsAdmin, Ownable2Step) public { Ownable2Step.acceptOwnership(); } function baseFeeOverheadPercentage() virtual override external view returns (uint16) { return __baseFeeOverheadPercentage; } function pendingOwner() virtual override (IWitnetFeedsAdmin, Ownable2Step) public view returns (address) { return Ownable2Step.pendingOwner(); } function transferOwnership(address _newOwner) virtual override (IWitnetFeedsAdmin, Ownable2Step) public onlyOwner { Ownable.transferOwnership(_newOwner); } function deleteFeed(string calldata caption) virtual override external onlyOwner { bytes4 feedId = hash(caption); bytes4[] storage __ids = __storage().ids; Record storage __record = __records_(feedId); uint _index = __record.index; require(_index != 0, "WitnetPriceFeeds: unknown feed"); { bytes4 _lastFeedId = __ids[__ids.length - 1]; __ids[_index - 1] = _lastFeedId; __ids.pop(); __records_(_lastFeedId).index = _index; delete __storage().records[feedId]; } emit WitnetFeedDeleted(feedId); } function deleteFeeds() virtual override external onlyOwner { bytes4[] storage __ids = __storage().ids; for (uint _ix = __ids.length; _ix > 0; _ix --) { bytes4 _feedId = __ids[_ix - 1]; delete __storage().records[_feedId]; __ids.pop(); emit WitnetFeedDeleted(_feedId); } } function settleBaseFeeOverheadPercentage(uint16 _baseFeeOverheadPercentage) virtual override external onlyOwner { __baseFeeOverheadPercentage = _baseFeeOverheadPercentage; } function settleDefaultRadonSLA(WitnetV2.RadonSLA calldata defaultSLA) override public onlyOwner { require(defaultSLA.isValid(), "WitnetPriceFeeds: invalid SLA"); __defaultRadonSLA = defaultSLA; emit WitnetRadonSLA(defaultSLA); } function settleFeedRequest(string calldata caption, bytes32 radHash) override public onlyOwner { require( registry().lookupRadonRequestResultDataType(radHash) == dataType, "WitnetPriceFeeds: bad result data type" ); bytes4 feedId = hash(caption); Record storage __record = __records_(feedId); if (__record.index == 0) { // settle new feed: __record.caption = caption; __record.decimals = _validateCaption(caption); __record.index = __storage().ids.length + 1; __record.radHash = radHash; __storage().ids.push(feedId); } else if (__record.radHash != radHash) { // update radHash on existing feed: __record.radHash = radHash; __record.solver = address(0); } emit WitnetFeedSettled(feedId, radHash); } function settleFeedRequest(string calldata caption, WitnetRequest request) override external onlyOwner { settleFeedRequest(caption, request.radHash()); } function settleFeedRequest( string calldata caption, WitnetRequestTemplate template, string[][] calldata args ) override external onlyOwner { settleFeedRequest(caption, template.verifyRadonRequest(args)); } function settleFeedSolver( string calldata caption, address solver, string[] calldata deps ) override external onlyOwner { require( solver != address(0), "WitnetPriceFeeds: no solver address" ); bytes4 feedId = hash(caption); Record storage __record = __records_(feedId); if (__record.index == 0) { // settle new feed: __record.caption = caption; __record.decimals = _validateCaption(caption); __record.index = __storage().ids.length + 1; __record.solver = solver; __storage().ids.push(feedId); } else if (__record.solver != solver) { // update radHash on existing feed: __record.radHash = 0; __record.solver = solver; } // validate solver first-level dependencies { // solhint-disable-next-line avoid-low-level-calls (bool _success, bytes memory _reason) = solver.delegatecall(abi.encodeWithSelector( IWitnetPriceSolver.validate.selector, feedId, deps )); if (!_success) { assembly { _reason := add(_reason, 4) } revert(string(abi.encodePacked( "WitnetPriceFeedUpgradable: solver validation failed: ", string(abi.decode(_reason,(string))) ))); } } // smoke-test the solver { // solhint-disable-next-line avoid-low-level-calls (bool _success, bytes memory _reason) = address(this).staticcall(abi.encodeWithSelector( IWitnetPriceSolver.solve.selector, feedId )); if (!_success) { assembly { _reason := add(_reason, 4) } revert(string(abi.encodePacked( "WitnetPriceFeeds: smoke-test failed: ", string(abi.decode(_reason,(string))) ))); } } emit WitnetFeedSolverSettled(feedId, solver); } // ================================================================================================================ // --- Implements 'IWitnetPriceFeeds' ----------------------------------------------------------------------------- function lookupDecimals(bytes4 feedId) override external view returns (uint8) { return __records_(feedId).decimals; } function lookupPriceSolver(bytes4 feedId) override external view returns (IWitnetPriceSolver _solverAddress, string[] memory _solverDeps) { _solverAddress = IWitnetPriceSolver(__records_(feedId).solver); bytes4[] memory _deps = _depsOf(feedId); _solverDeps = new string[](_deps.length); for (uint _ix = 0; _ix < _deps.length; _ix ++) { _solverDeps[_ix] = lookupCaption(_deps[_ix]); } } function latestPrice(bytes4 feedId) virtual override public view returns (IWitnetPriceSolver.Price memory) { uint _queryId = _lastValidQueryId(feedId); if (_queryId > 0) { WitnetV2.Response memory _lastValidResponse = lastValidResponse(feedId); Witnet.Result memory _latestResult = _lastValidResponse.resultCborBytes.toWitnetResult(); return IWitnetPriceSolver.Price({ value: _latestResult.asUint(), timestamp: _lastValidResponse.resultTimestamp, tallyHash: _lastValidResponse.resultTallyHash, status: latestUpdateResponseStatus(feedId) }); } else { address _solver = __records_(feedId).solver; if (_solver != address(0)) { // solhint-disable-next-line avoid-low-level-calls (bool _success, bytes memory _result) = address(this).staticcall(abi.encodeWithSelector( IWitnetPriceSolver.solve.selector, feedId )); if (!_success) { assembly { _result := add(_result, 4) } revert(string(abi.encodePacked( "WitnetPriceFeeds: ", string(abi.decode(_result, (string))) ))); } else { return abi.decode(_result, (IWitnetPriceSolver.Price)); } } else { return IWitnetPriceSolver.Price({ value: 0, timestamp: 0, tallyHash: 0, status: latestUpdateResponseStatus(feedId) }); } } } function latestPrices(bytes4[] calldata feedIds) virtual override external view returns (IWitnetPriceSolver.Price[] memory _prices) { _prices = new IWitnetPriceSolver.Price[](feedIds.length); for (uint _ix = 0; _ix < feedIds.length; _ix ++) { _prices[_ix] = latestPrice(feedIds[_ix]); } } // ================================================================================================================ // --- Implements 'IWitnetPriceSolverDeployer' --------------------------------------------------------------------- function deployPriceSolver(bytes calldata initcode, bytes calldata constructorParams) virtual override external onlyOwner returns (address _solver) { _solver = WitnetPriceFeedsLib.deployPriceSolver(initcode, constructorParams); emit WitnetPriceSolverDeployed( _solver, _solver.codehash, constructorParams ); } function determinePriceSolverAddress(bytes calldata initcode, bytes calldata constructorParams) virtual override public view returns (address _address) { return WitnetPriceFeedsLib.determinePriceSolverAddress(initcode, constructorParams); } // ================================================================================================================ // --- Implements 'IERC2362' -------------------------------------------------------------------------------------- function valueFor(bytes32 feedId) virtual override external view returns (int256 _value, uint256 _timestamp, uint256 _status) { IWitnetPriceSolver.Price memory _latestPrice = latestPrice(bytes4(feedId)); return ( int(_latestPrice.value), _latestPrice.timestamp, _latestPrice.status == WitnetV2.ResponseStatus.Ready ? 200 : ( _latestPrice.status == WitnetV2.ResponseStatus.Awaiting || _latestPrice.status == WitnetV2.ResponseStatus.Finalizing ) ? 404 : 400 ); } // ================================================================================================================ // --- Internal methods ------------------------------------------------------------------------------------------- function _checkQueryResponseStatus(uint _queryId) internal view returns (WitnetV2.ResponseStatus) { if (_queryId > 0) { return witnet.getQueryResponseStatus(_queryId); } else { return WitnetV2.ResponseStatus.Ready; } } function _footprintOf(bytes4 _id4) virtual internal view returns (bytes4) { if (__records_(_id4).radHash != bytes32(0)) { return bytes4(keccak256(abi.encode(_id4, __records_(_id4).radHash))); } else { return bytes4(keccak256(abi.encode(_id4, __records_(_id4).solverDepsFlag))); } } function _lastValidQueryId(bytes4 feedId) virtual internal view returns (uint256) { uint _latestUpdateQueryId = latestUpdateQueryId(feedId); if ( _latestUpdateQueryId > 0 && witnet.getQueryResponseStatus(_latestUpdateQueryId) == WitnetV2.ResponseStatus.Ready ) { return _latestUpdateQueryId; } else { return __records_(feedId).lastValidQueryId; } } function _validateCaption(string calldata caption) internal view returns (uint8) { try WitnetPriceFeedsLib.validateCaption(__prefix, caption) returns (uint8 _decimals) { return _decimals; } catch Error(string memory reason) { revert(string(abi.encodePacked( "WitnetPriceFeeds: ", reason ))); } } function __requestUpdate(bytes4[] memory _deps, WitnetV2.RadonSLA memory sla) virtual internal returns (uint256 _usedFunds) { uint _partial = msg.value / _deps.length; for (uint _ix = 0; _ix < _deps.length; _ix ++) { _usedFunds += this.requestUpdate{value: _partial}(_deps[_ix], sla); } } function __requestUpdate(bytes4 feedId, WitnetV2.RadonSLA memory querySLA) virtual internal returns (uint256 _usedFunds) { Record storage __feed = __records_(feedId); if (__feed.radHash != 0) { _usedFunds = estimateUpdateBaseFee(tx.gasprice); require( msg.value >= _usedFunds, "WitnetPriceFeeds: insufficient reward" ); uint _latestId = __feed.latestUpdateQueryId; WitnetV2.ResponseStatus _latestStatus = _checkQueryResponseStatus(_latestId); if (_latestStatus == WitnetV2.ResponseStatus.Awaiting) { // latest update is still pending, so just increase the reward // accordingly to current tx gasprice: WitnetV2.Request memory _request = witnet.getQueryRequest(_latestId); int _deltaReward = int(int72(_request.evmReward)) - int(_usedFunds); if (_deltaReward > 0) { _usedFunds = uint(_deltaReward); witnet.upgradeQueryEvmReward{value: _usedFunds}(_latestId); // solhint-disable avoid-tx-origin emit WitnetFeedUpdateRequested( tx.origin, feedId, _latestId, _usedFunds ); } else { _usedFunds = 0; } } else { // Check if latest update ended successfully: if (_latestStatus == WitnetV2.ResponseStatus.Ready) { // If so, remove previous last valid query from the WRB: if (__feed.lastValidQueryId > 0) { witnet.fetchQueryResponse(__feed.lastValidQueryId); } __feed.lastValidQueryId = _latestId; } else { // Otherwise, try to delete latest query, as it was faulty // and we are about to post a new update request: try witnet.fetchQueryResponse(_latestId) {} catch {} } // Post update request to the WRB: _latestId = witnet.postRequest{value: _usedFunds}( __feed.radHash, querySLA ); // Update latest query id: __feed.latestUpdateQueryId = _latestId; // solhint-disable avoid-tx-origin: emit WitnetFeedUpdateRequested( tx.origin, feedId, _latestId, _usedFunds, querySLA ); } } else if (__feed.solver != address(0)) { _usedFunds = __requestUpdate( _depsOf(feedId), querySLA ); } else { revert("WitnetPriceFeeds: unknown feed"); } if (_usedFunds < msg.value) { // transfer back unused funds: payable(msg.sender).transfer(msg.value - _usedFunds); } } }
// 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.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "../interfaces/IWitnetPriceSolver.sol"; import "../interfaces/IWitnetPriceSolverDeployer.sol"; import "../libs/Slices.sol"; /// @title Ancillary deployable library for WitnetPriceFeeds. /// @dev Features: /// @dev - deployment of counter-factual IWitnetPriceSolver instances. /// @dev - validation of feed caption strings. /// @author The Witnet Foundation. library WitnetPriceFeedsLib { using Slices for string; using Slices for Slices.Slice; function deployPriceSolver( bytes calldata initcode, bytes calldata constructorParams ) external returns (address _solver) { _solver = determinePriceSolverAddress(initcode, constructorParams); if (_solver.code.length == 0) { bytes memory _bytecode = _completeInitCode(initcode, constructorParams); address _createdContract; assembly { _createdContract := create2( 0, add(_bytecode, 0x20), mload(_bytecode), 0 ) } // assert(_solver == _createdContract); // fails on TEN chains _solver = _createdContract; require( IWitnetPriceSolver(_solver).specs() == type(IWitnetPriceSolver).interfaceId, "WitnetPriceFeedsLib: uncompliant solver implementation" ); } } function determinePriceSolverAddress( bytes calldata initcode, bytes calldata constructorParams ) public view returns (address) { return address( uint160(uint(keccak256( abi.encodePacked( bytes1(0xff), address(this), bytes32(0), keccak256(_completeInitCode(initcode, constructorParams)) ) ))) ); } function validateCaption(bytes32 prefix, string calldata caption) external pure returns (uint8) { require( bytes6(bytes(caption)) == bytes6(prefix), "WitnetPriceFeedsLib: bad caption prefix" ); Slices.Slice memory _caption = caption.toSlice(); Slices.Slice memory _delim = string("-").toSlice(); string[] memory _parts = new string[](_caption.count(_delim) + 1); for (uint _ix = 0; _ix < _parts.length; _ix ++) { _parts[_ix] = _caption.split(_delim).toString(); } (uint _decimals, bool _success) = Witnet.tryUint(_parts[_parts.length - 1]); require(_success, "WitnetPriceFeedsLib: bad decimals"); return uint8(_decimals); } function _completeInitCode(bytes calldata initcode, bytes calldata constructorParams) private pure returns (bytes memory) { return abi.encodePacked( initcode, constructorParams ); } }
// 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: APACHE-2.0 pragma solidity >=0.8.0 <0.9.0; /* * @title String & Slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'Slice'. A Slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length Slice). Since a Slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on Slice that need to return * a Slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original Slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second Slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * Slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new Slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ library Slices { struct Slice { uint _len; uint _ptr; } function _memcpy(uint _dest, uint _src, uint _len) private pure { // Copy word-length chunks while possible for(; _len >= 32; _len -= 32) { assembly { mstore(_dest, mload(_src)) } _dest += 32; _src += 32; } // Copy remaining bytes uint _mask = type(uint).max; if (_len > 0) { _mask = 256 ** (32 - _len) - 1; } assembly { let srcpart := and(mload(_src), not(_mask)) let destpart := and(mload(_dest), _mask) mstore(_dest, or(destpart, srcpart)) } } /* * @dev Returns a Slice containing the entire string. * @param self The string to make a Slice from. * @return A newly allocated Slice containing the entire string. */ function toSlice(string memory self) internal pure returns (Slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return Slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & type(uint128).max == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & type(uint64).max == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & type(uint32).max == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & type(uint16).max == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & type(uint8).max == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a Slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a Slice. * @return A new Slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (Slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new Slice containing the same data as the current Slice. * @param self The Slice to copy. * @return A new Slice containing the same data as `self`. */ function copy(Slice memory self) internal pure returns (Slice memory) { return Slice(self._len, self._ptr); } /* * @dev Copies a Slice to a new string. * @param self The Slice to copy. * @return A newly allocated string containing the Slice's text. */ function toString(Slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } _memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the Slice. Note that this operation * takes time proportional to the length of the Slice; avoid using it * in loops, and call `Slice.empty()` if you only need to know whether * the Slice is empty or not. * @param self The Slice to operate on. * @return The length of the Slice in runes. */ function len(Slice memory self) internal pure returns (uint _l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (_l = 0; ptr < end; _l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the Slice is empty (has a length of 0). * @param self The Slice to operate on. * @return True if the Slice is empty, False otherwise. */ function empty(Slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first Slice to compare. * @param other The second Slice to compare. * @return The result of the comparison. */ function compare(Slice memory self, Slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint mask = type(uint).max; // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } unchecked { uint diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first Slice to compare. * @param self The second Slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(Slice memory self, Slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the Slice into `rune`, advancing the * Slice to point to the next rune and returning `self`. * @param self The Slice to operate on. * @param rune The Slice that will contain the first rune. * @return `rune`. */ function nextRune(Slice memory self, Slice memory rune) internal pure returns (Slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint _l; uint _b; // Load the first byte of the rune into the LSBs of _b assembly { _b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (_b < 0x80) { _l = 1; } else if(_b < 0xE0) { _l = 2; } else if(_b < 0xF0) { _l = 3; } else { _l = 4; } // Check for truncated codepoints if (_l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += _l; self._len -= _l; rune._len = _l; return rune; } /* * @dev Returns the first rune in the Slice, advancing the Slice to point * to the next rune. * @param self The Slice to operate on. * @return A Slice containing only the first rune from `self`. */ function nextRune(Slice memory self) internal pure returns (Slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the Slice. * @param self The Slice to operate on. * @return The number of the first codepoint in the Slice. */ function ord(Slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the Slice. * @param self The Slice to hash. * @return The hash of the Slice. */ function keccak(Slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return True if the Slice starts with the provided text, false otherwise. */ function startsWith(Slice memory self, Slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return `self` */ function beyond(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the Slice ends with `needle`. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return True if the Slice starts with the provided text, false otherwise. */ function endsWith(Slice memory self, Slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return `self` */ function until(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the Slice. `self` is set to the empty Slice * if `needle` is not found. * @param self The Slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty Slice. * @param self The Slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the Slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and `token` is set to the entirety of `self`. * @param self The Slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the Slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and the entirety of `self` is returned. * @param self The Slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) { split(self, needle, token); } /* * @dev Splits the Slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and `token` is set to the entirety of `self`. * @param self The Slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the Slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and the entirety of `self` is returned. * @param self The Slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The Slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(Slice memory self, Slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The Slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(Slice memory self, Slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first Slice to concatenate. * @param other The second Slice to concatenate. * @return The concatenation of the two strings. */ function concat(Slice memory self, Slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } _memcpy(retptr, self._ptr, self._len); _memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(Slice memory self, Slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(uint i = 0; i < parts.length; i++) { _memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { _memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; interface IWitnetRequestFactory { event WitnetRequestTemplateBuilt(address template, bool parameterized); function buildRequestTemplate( bytes32[] memory sourcesIds, bytes32 aggregatorId, bytes32 tallyId, uint16 resultDataMaxSize ) external returns (address template); }
// 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; interface IWitnetPriceSolverDeployer { event WitnetPriceSolverDeployed(address solver, bytes32 codehash, bytes constructorParams); function deployPriceSolver(bytes calldata initcode, bytes calldata additionalParams) external returns (address); function determinePriceSolverAddress(bytes calldata initcode, bytes calldata additionalParams) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "../libs/WitnetV2.sol"; interface IWitnetPriceSolver { struct Price { uint value; uint timestamp; bytes32 tallyHash; WitnetV2.ResponseStatus status; } function class() external pure returns (string memory); function delegator() external view returns (address); function solve(bytes4 feedId) external view returns (Price memory); function specs() external pure returns (bytes4); function validate(bytes4 feedId, string[] calldata initdata) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "./IWitnetPriceSolver.sol"; interface IWitnetPriceFeeds { /// ====================================================================================================== /// --- IFeeds extension --------------------------------------------------------------------------------- function lookupDecimals(bytes4 feedId) external view returns (uint8); function lookupPriceSolver(bytes4 feedId) external view returns ( IWitnetPriceSolver solverAddress, string[] memory solverDeps ); /// ====================================================================================================== /// --- IWitnetFeeds extension --------------------------------------------------------------------------- function latestPrice(bytes4 feedId) external view returns (IWitnetPriceSolver.Price memory); function latestPrices(bytes4[] calldata feedIds) external view returns (IWitnetPriceSolver.Price[] memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "../libs/WitnetV2.sol"; interface IWitnetOracleEvents { /// Emitted every time a new query containing some verified data request is posted to the WRB. event WitnetQuery( uint256 id, uint256 evmReward, WitnetV2.RadonSLA witnetSLA ); /// Emitted when a query with no callback gets reported into the WRB. event WitnetQueryResponse( uint256 id, uint256 evmGasPrice ); /// Emitted when a query with a callback gets successfully reported into the WRB. event WitnetQueryResponseDelivered( uint256 id, uint256 evmGasPrice, uint256 evmCallbackGas ); /// Emitted when a query with a callback cannot get reported into the WRB. event WitnetQueryResponseDeliveryFailed( uint256 id, bytes resultCborBytes, uint256 evmGasPrice, uint256 evmCallbackActualGas, string evmCallbackRevertReason ); /// Emitted when the reward of some not-yet reported query is upgraded. event WitnetQueryRewardUpgraded( uint256 id, uint256 evmReward ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "../libs/WitnetV2.sol"; interface IWitnetOracle { /// @notice Estimate the minimum reward required for posting a data request. /// @dev Underestimates if the size of returned data is greater than `resultMaxSize`. /// @param gasPrice Expected gas price to pay upon posting the data request. /// @param resultMaxSize Maximum expected size of returned data (in bytes). function estimateBaseFee(uint256 gasPrice, uint16 resultMaxSize) external view returns (uint256); /// @notice Estimate the minimum reward required for posting a data request. /// @dev Fails if the RAD hash was not previously verified on the WitnetRequestBytecodes registry. /// @param gasPrice Expected gas price to pay upon posting the data request. /// @param radHash The RAD hash of the data request to be solved by Witnet. function estimateBaseFee(uint256 gasPrice, bytes32 radHash) external view returns (uint256); /// @notice Estimate the minimum reward required for posting a data request with a callback. /// @param gasPrice Expected gas price to pay upon posting the data request. /// @param callbackGasLimit Maximum gas to be spent when reporting the data request result. function estimateBaseFeeWithCallback(uint256 gasPrice, uint24 callbackGasLimit) external view returns (uint256); /// @notice Retrieves a copy of all Witnet-provable data related to a previously posted request, /// removing the whole query from the WRB storage. /// @dev Fails if the query was not in 'Reported' status, or called from an address different to /// @dev the one that actually posted the given request. /// @param queryId The unique query identifier. function fetchQueryResponse(uint256 queryId) external returns (WitnetV2.Response memory); /// @notice Gets the whole Query data contents, if any, no matter its current status. function getQuery(uint256 queryId) external view returns (WitnetV2.Query memory); /// @notice Gets the current EVM reward the report can claim, if not done yet. function getQueryEvmReward(uint256 queryId) external view returns (uint256); /// @notice Retrieves the RAD hash and SLA parameters of the given query. /// @param queryId The unique query identifier. function getQueryRequest(uint256 queryId) external view returns (WitnetV2.Request memory); /// @notice Retrieves the whole `Witnet.Response` record referred to a previously posted Witnet Data Request. /// @param queryId The unique query identifier. function getQueryResponse(uint256 queryId) external view returns (WitnetV2.Response memory); /// @notice Returns query's result current status from a requester's point of view: /// @notice - 0 => Void: the query is either non-existent or deleted; /// @notice - 1 => Awaiting: the query has not yet been reported; /// @notice - 2 => Ready: the query response was finalized, and contains a result with no erros. /// @notice - 3 => Error: the query response was finalized, and contains a result with errors. /// @param queryId The unique query identifier. function getQueryResponseStatus(uint256 queryId) external view returns (WitnetV2.ResponseStatus); /// @notice Retrieves the CBOR-encoded buffer containing the Witnet-provided result to the given query. /// @param queryId The unique query identifier. function getQueryResultCborBytes(uint256 queryId) external view returns (bytes memory); /// @notice Gets error code identifying some possible failure on the resolution of the given query. /// @param queryId The unique query identifier. function getQueryResultError(uint256 queryId) external view returns (Witnet.ResultError memory); /// @notice Gets current status of given query. function getQueryStatus(uint256 queryId) external view returns (WitnetV2.QueryStatus); /// @notice Get current status of all given query ids. function getQueryStatusBatch(uint256[] calldata queryIds) external view returns (WitnetV2.QueryStatus[] memory); /// @notice Returns next query id to be generated by the Witnet Request Board. function getNextQueryId() external view returns (uint256); /// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and /// @notice solved by the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be /// @notice transferred to the reporter who relays back the Witnet-provable result to this request. /// @dev Reasons to fail: /// @dev - the RAD hash was not previously verified by the WitnetRequestBytecodes registry; /// @dev - invalid SLA parameters were provided; /// @dev - insufficient value is paid as reward. /// @param queryRAD The RAD hash of the data request to be solved by Witnet. /// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain. /// @return queryId Unique query identifier. function postRequest( bytes32 queryRAD, WitnetV2.RadonSLA calldata querySLA ) external payable returns (uint256 queryId); /// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and solved by /// @notice the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be transferred to the /// @notice reporter who relays back the Witnet-provable result to this request. The Witnet-provable result will be reported /// @notice directly to the requesting contract. If the report callback fails for any reason, an `WitnetQueryResponseDeliveryFailed` /// @notice will be triggered, and the Witnet audit trail will be saved in storage, but not so the actual CBOR-encoded result. /// @dev Reasons to fail: /// @dev - the caller is not a contract implementing the IWitnetConsumer interface; /// @dev - the RAD hash was not previously verified by the WitnetRequestBytecodes registry; /// @dev - invalid SLA parameters were provided; /// @dev - insufficient value is paid as reward. /// @param queryRAD The RAD hash of the data request to be solved by Witnet. /// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain. /// @param queryCallbackGasLimit Maximum gas to be spent when reporting the data request result. /// @return queryId Unique query identifier. function postRequestWithCallback( bytes32 queryRAD, WitnetV2.RadonSLA calldata querySLA, uint24 queryCallbackGasLimit ) external payable returns (uint256 queryId); /// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and solved by /// @notice the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be transferred to the /// @notice reporter who relays back the Witnet-provable result to this request. The Witnet-provable result will be reported /// @notice directly to the requesting contract. If the report callback fails for any reason, a `WitnetQueryResponseDeliveryFailed` /// @notice event will be triggered, and the Witnet audit trail will be saved in storage, but not so the CBOR-encoded result. /// @dev Reasons to fail: /// @dev - the caller is not a contract implementing the IWitnetConsumer interface; /// @dev - the provided bytecode is empty; /// @dev - invalid SLA parameters were provided; /// @dev - insufficient value is paid as reward. /// @param queryUnverifiedBytecode The (unverified) bytecode containing the actual data request to be solved by the Witnet blockchain. /// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain. /// @param queryCallbackGasLimit Maximum gas to be spent when reporting the data request result. /// @return queryId Unique query identifier. function postRequestWithCallback( bytes calldata queryUnverifiedBytecode, WitnetV2.RadonSLA calldata querySLA, uint24 queryCallbackGasLimit ) external payable returns (uint256 queryId); /// @notice Increments the reward of a previously posted request by adding the transaction value to it. /// @param queryId The unique query identifier. function upgradeQueryEvmReward(uint256 queryId) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "../libs/WitnetV2.sol"; import "../WitnetRequest.sol"; interface IWitnetFeedsAdmin { function acceptOwnership() external; function baseFeeOverheadPercentage() external view returns (uint16); function deleteFeed(string calldata caption) external; function deleteFeeds() external; function owner() external view returns (address); function pendingOwner() external returns (address); function settleBaseFeeOverheadPercentage(uint16) external; function settleDefaultRadonSLA(WitnetV2.RadonSLA calldata) external; function settleFeedRequest(string calldata caption, bytes32 radHash) external; function settleFeedRequest(string calldata caption, WitnetRequest request) external; function settleFeedRequest(string calldata caption, WitnetRequestTemplate template, string[][] calldata) external; function settleFeedSolver (string calldata caption, address solver, string[] calldata deps) external; function transferOwnership(address) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "../WitnetOracle.sol"; import "../WitnetRequestBytecodes.sol"; interface IWitnetFeeds { event WitnetFeedDeleted(bytes4 feedId); event WitnetFeedSettled(bytes4 feedId, bytes32 radHash); event WitnetFeedSolverSettled(bytes4 feedId, address solver); event WitnetRadonSLA(WitnetV2.RadonSLA sla); event WitnetFeedUpdateRequested( address indexed origin, bytes4 indexed feedId, uint256 witnetQueryId, uint256 witnetQueryEvmReward, WitnetV2.RadonSLA witnetQuerySLA ); event WitnetFeedUpdateRequested( address indexed origin, bytes4 indexed feedId, uint256 witnetQueryId, uint256 witnetQueryReward ); function dataType() external view returns (Witnet.RadonDataTypes); function prefix() external view returns (string memory); function registry() external view returns (WitnetRequestBytecodes); function witnet() external view returns (WitnetOracle); function defaultRadonSLA() external view returns (Witnet.RadonSLA memory); function estimateUpdateBaseFee(uint256 evmGasPrice) external view returns (uint); function lastValidQueryId(bytes4 feedId) external view returns (uint256); function lastValidResponse(bytes4 feedId) external view returns (WitnetV2.Response memory); function latestUpdateQueryId(bytes4 feedId) external view returns (uint256); function latestUpdateRequest(bytes4 feedId) external view returns (WitnetV2.Request memory); function latestUpdateResponse(bytes4 feedId) external view returns (WitnetV2.Response memory); function latestUpdateResponseStatus(bytes4 feedId) external view returns (WitnetV2.ResponseStatus); function latestUpdateResultError(bytes4 feedId) external view returns (Witnet.ResultError memory); function lookupWitnetBytecode(bytes4 feedId) external view returns (bytes memory); function lookupWitnetRadHash(bytes4 feedId) external view returns (bytes32); function lookupWitnetRetrievals(bytes4 feedId) external view returns (Witnet.RadonRetrieval[] memory); function requestUpdate(bytes4 feedId) external payable returns (uint256 usedFunds); function requestUpdate(bytes4 feedId, WitnetV2.RadonSLA calldata updateSLA) external payable returns (uint256 usedFunds); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; interface IFeeds { function footprint() external view returns (bytes4); function hash(string calldata caption) external pure returns (bytes4); function lookupCaption(bytes4) external view returns (string memory); function supportedFeeds() external view returns (bytes4[] memory, string[] memory, bytes32[] memory); function supportsCaption(string calldata) external view returns (bool); function totalFeeds() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; /// @title WitnetFeeds data model. /// @author The Witnet Foundation. abstract contract WitnetPriceFeedsData { bytes32 private constant _WITNET_FEEDS_DATA_SLOTHASH = /* keccak256("io.witnet.feeds.data") */ 0xe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff; struct Storage { bytes32 reserved; bytes4[] ids; mapping (bytes4 => Record) records; } struct Record { string caption; uint8 decimals; uint256 index; uint256 lastValidQueryId; uint256 latestUpdateQueryId; bytes32 radHash; address solver; // logic contract address for reducing values on routed feeds. int256 solverReductor; // as to reduce resulting number of decimals on routed feeds. bytes32 solverDepsFlag; // as to store ids of up to 8 depending feeds. } // ================================================================================================ // --- Internal functions ------------------------------------------------------------------------- /// @notice Returns storage pointer to where Storage data is located. function __storage() internal pure returns (Storage storage _ptr) { assembly { _ptr.slot := _WITNET_FEEDS_DATA_SLOTHASH } } /// @notice Returns storage pointer to where Record for given feedId is located. function __records_(bytes4 feedId) internal view returns (Record storage) { return __storage().records[feedId]; } /// @notice Returns array of feed ids from which given feed's value depends. /// @dev Returns empty array on either unsupported or not-routed feeds. /// @dev The maximum number of dependencies is hard-limited to 8, as to limit number /// @dev of SSTORE operations (`__storage().records[feedId].solverDepsFlag`), /// @dev no matter the actual number of depending feeds involved. function _depsOf(bytes4 feedId) internal view returns (bytes4[] memory _deps) { bytes32 _solverDepsFlag = __storage().records[feedId].solverDepsFlag; _deps = new bytes4[](8); uint _len; for (_len = 0; _len < 8; _len ++) { _deps[_len] = bytes4(_solverDepsFlag); if (_deps[_len] == 0) { break; } else { _solverDepsFlag <<= 32; } } assembly { // reset length to actual number of dependencies: mstore(_deps, _len) } } }
// 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 "./WitnetRequestBytecodes.sol"; import "./WitnetOracle.sol"; import "./WitnetRequestFactory.sol"; abstract contract WitnetRequestTemplate { event WitnetRequestBuilt(address indexed request, bytes32 indexed radHash, string[][] args); function class() virtual external view returns (string memory); function factory() virtual external view returns (WitnetRequestFactory); function registry() virtual external view returns (WitnetRequestBytecodes); function specs() virtual external view returns (bytes4); function version() virtual external view returns (string memory); function witnet() virtual external view returns (WitnetOracle); function aggregator() virtual external view returns (bytes32); function parameterized() virtual external view returns (bool); function resultDataMaxSize() virtual external view returns (uint16); function resultDataType() virtual external view returns (Witnet.RadonDataTypes); function retrievals() virtual external view returns (bytes32[] memory); function tally() virtual external view returns (bytes32); function getRadonAggregator() virtual external view returns (Witnet.RadonReducer memory); function getRadonRetrievalByIndex(uint256) virtual external view returns (Witnet.RadonRetrieval memory); function getRadonRetrievalsCount() virtual external view returns (uint256); function getRadonTally() virtual external view returns (Witnet.RadonReducer memory); function buildRequest(string[][] calldata args) virtual external returns (address); function verifyRadonRequest(string[][] calldata args) virtual external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "./WitnetRequestBytecodes.sol"; import "./WitnetOracle.sol"; import "./interfaces/IWitnetRequestFactory.sol"; abstract contract WitnetRequestFactory is IWitnetRequestFactory { function class() virtual external view returns (string memory); function registry() virtual external view returns (WitnetRequestBytecodes); function specs() virtual external view returns (bytes4); function witnet() virtual external view returns (WitnetOracle); }
// 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 pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "./WitnetRequestTemplate.sol"; abstract contract WitnetRequest is WitnetRequestTemplate { /// introspection methods function template() virtual external view returns (WitnetRequestTemplate); /// request-exclusive fields function args() virtual external view returns (string[][] memory); function bytecode() virtual external view returns (bytes memory); function radHash() virtual external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "./WitnetFeeds.sol"; import "./interfaces/IWitnetPriceFeeds.sol"; import "./interfaces/IWitnetPriceSolverDeployer.sol"; /// @title WitnetPriceFeeds: Price Feeds live repository reliant on the Witnet Oracle blockchain. /// @author The Witnet Foundation. abstract contract WitnetPriceFeeds is WitnetFeeds, IWitnetPriceFeeds, IWitnetPriceSolverDeployer { constructor() WitnetFeeds(Witnet.RadonDataTypes.Integer, "Price-") {} }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "./WitnetRequestBytecodes.sol"; import "./WitnetRequestFactory.sol"; import "./interfaces/IWitnetOracle.sol"; import "./interfaces/IWitnetOracleEvents.sol"; /// @title Witnet Request Board functionality base contract. /// @author The Witnet Foundation. abstract contract WitnetOracle is IWitnetOracle, IWitnetOracleEvents { function class() virtual external view returns (string memory) { return type(WitnetOracle).name; } function channel() virtual external view returns (bytes4); function factory() virtual external view returns (WitnetRequestFactory); function registry() virtual external view returns (WitnetRequestBytecodes); function specs() virtual external view returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; import "./interfaces/IFeeds.sol"; import "./interfaces/IWitnetFeeds.sol"; import "./interfaces/IWitnetFeedsAdmin.sol"; import "ado-contracts/contracts/interfaces/IERC2362.sol"; abstract contract WitnetFeeds is IERC2362, IFeeds, IWitnetFeeds, IWitnetFeedsAdmin, IWitnetOracleEvents { Witnet.RadonDataTypes immutable public override dataType; function class() virtual external view returns (string memory); function specs() virtual external view returns (bytes4); function witnet() virtual external view returns (WitnetOracle); constructor( Witnet.RadonDataTypes _dataType, string memory _prefix ) { dataType = _dataType; __prefix = Witnet.toBytes32(bytes(_prefix)); } bytes32 immutable internal __prefix; function prefix() override public view returns (string memory) { return Witnet.toString(__prefix); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0 <0.9.0; /** * @dev EIP2362 Interface for pull oracles * https://github.com/adoracles/EIPs/blob/erc-2362/EIPS/eip-2362.md */ interface IERC2362 { /** * @dev Exposed function pertaining to EIP standards * @param _id bytes32 ID of the query * @return int,uint,uint returns the value, timestamp, and status code of query */ function valueFor(bytes32 _id) external view returns(int256,uint256,uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.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/WitnetPriceFeedsLib.sol": { "WitnetPriceFeedsLib": "0x579b4aD5E67E5B491a33A033A02A70769D7AF837" } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract ABI
API[{"inputs":[{"internalType":"contract WitnetOracle","name":"_wrb","type":"address"},{"internalType":"bool","name":"_upgradable","type":"bool"},{"internalType":"bytes32","name":"_versionTag","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyBuffer","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"InvalidLengthEncoding","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":"uint256","name":"read","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"UnexpectedMajorType","type":"error"},{"inputs":[{"internalType":"uint256","name":"unexpected","type":"uint256"}],"name":"UnsupportedMajorType","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"WitnetFeedDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"bytes32","name":"radHash","type":"bytes32"}],"name":"WitnetFeedSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"address","name":"solver","type":"address"}],"name":"WitnetFeedSolverSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"origin","type":"address"},{"indexed":true,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"witnetQueryId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"witnetQueryEvmReward","type":"uint256"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"indexed":false,"internalType":"struct WitnetV2.RadonSLA","name":"witnetQuerySLA","type":"tuple"}],"name":"WitnetFeedUpdateRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"origin","type":"address"},{"indexed":true,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"witnetQueryId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"witnetQueryReward","type":"uint256"}],"name":"WitnetFeedUpdateRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"solver","type":"address"},{"indexed":false,"internalType":"bytes32","name":"codehash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"WitnetPriceSolverDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"indexed":false,"internalType":"struct WitnetV2.RadonSLA","name":"witnetSLA","type":"tuple"}],"name":"WitnetQuery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"}],"name":"WitnetQueryResponse","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackGas","type":"uint256"}],"name":"WitnetQueryResponseDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackActualGas","type":"uint256"},{"indexed":false,"internalType":"string","name":"evmCallbackRevertReason","type":"string"}],"name":"WitnetQueryResponseDeliveryFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"}],"name":"WitnetQueryRewardUpgraded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"indexed":false,"internalType":"struct WitnetV2.RadonSLA","name":"sla","type":"tuple"}],"name":"WitnetRadonSLA","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseFeeOverheadPercentage","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"class","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"codehash","outputs":[{"internalType":"bytes32","name":"_codehash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataType","outputs":[{"internalType":"enum Witnet.RadonDataTypes","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultRadonSLA","outputs":[{"components":[{"internalType":"uint8","name":"numWitnesses","type":"uint8"},{"internalType":"uint8","name":"minConsensusPercentage","type":"uint8"},{"internalType":"uint64","name":"witnessReward","type":"uint64"},{"internalType":"uint64","name":"witnessCollateral","type":"uint64"},{"internalType":"uint64","name":"minerCommitRevealFee","type":"uint64"}],"internalType":"struct Witnet.RadonSLA","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"deleteFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deleteFeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"deployPriceSolver","outputs":[{"internalType":"address","name":"_solver","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"determinePriceSolverAddress","outputs":[{"internalType":"address","name":"_address","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_evmGasPrice","type":"uint256"}],"name":"estimateUpdateBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"footprint","outputs":[{"internalType":"bytes4","name":"_footprint","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"hash","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_initData","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isUpgradable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"}],"name":"isUpgradableFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lastValidQueryId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lastValidResponse","outputs":[{"components":[{"internalType":"address","name":"reporter","type":"address"},{"internalType":"uint64","name":"finality","type":"uint64"},{"internalType":"uint32","name":"resultTimestamp","type":"uint32"},{"internalType":"bytes32","name":"resultTallyHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"}],"internalType":"struct WitnetV2.Response","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestPrice","outputs":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"tallyHash","type":"bytes32"},{"internalType":"enum WitnetV2.ResponseStatus","name":"status","type":"uint8"}],"internalType":"struct IWitnetPriceSolver.Price","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"feedIds","type":"bytes4[]"}],"name":"latestPrices","outputs":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"tallyHash","type":"bytes32"},{"internalType":"enum WitnetV2.ResponseStatus","name":"status","type":"uint8"}],"internalType":"struct IWitnetPriceSolver.Price[]","name":"_prices","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateQueryId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateRequest","outputs":[{"components":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"uint24","name":"gasCallback","type":"uint24"},{"internalType":"uint72","name":"evmReward","type":"uint72"},{"internalType":"bytes","name":"witnetBytecode","type":"bytes"},{"internalType":"bytes32","name":"witnetRAD","type":"bytes32"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"witnetSLA","type":"tuple"}],"internalType":"struct WitnetV2.Request","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResponse","outputs":[{"components":[{"internalType":"address","name":"reporter","type":"address"},{"internalType":"uint64","name":"finality","type":"uint64"},{"internalType":"uint32","name":"resultTimestamp","type":"uint32"},{"internalType":"bytes32","name":"resultTallyHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"}],"internalType":"struct WitnetV2.Response","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResponseStatus","outputs":[{"internalType":"enum WitnetV2.ResponseStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResultError","outputs":[{"components":[{"internalType":"enum Witnet.ResultErrorCodes","name":"code","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"internalType":"struct Witnet.ResultError","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupCaption","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupPriceSolver","outputs":[{"internalType":"contract IWitnetPriceSolver","name":"_solverAddress","type":"address"},{"internalType":"string[]","name":"_solverDeps","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitnetBytecode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitnetRadHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupWitnetRetrievals","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":"_retrievals","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract WitnetRequestBytecodes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"updateSLA","type":"tuple"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"_usedFunds","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_baseFeeOverheadPercentage","type":"uint16"}],"name":"settleBaseFeeOverheadPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"defaultSLA","type":"tuple"}],"name":"settleDefaultRadonSLA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"bytes32","name":"radHash","type":"bytes32"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"contract WitnetRequest","name":"request","type":"address"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"contract WitnetRequestTemplate","name":"template","type":"address"},{"internalType":"string[][]","name":"args","type":"string[][]"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"string[]","name":"deps","type":"string[]"}],"name":"settleFeedSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specs","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supportedFeeds","outputs":[{"internalType":"bytes4[]","name":"_ids","type":"bytes4[]"},{"internalType":"string[]","name":"_captions","type":"string[]"},{"internalType":"bytes32[]","name":"_solvers","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"supportsCaption","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"feedId","type":"bytes32"}],"name":"valueFor","outputs":[{"internalType":"int256","name":"_value","type":"int256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_status","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witnet","outputs":[{"internalType":"contract WitnetOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101c0604052336101405263346916ef60e11b6101805234801561002257600080fd5b506040516162c23803806162c283398101604081905261004191610251565b81816040518060400160405280601f81526020017f696f2e7769746e65742e70726f786961626c652e66656564732e707269636500815250823360046040518060400160405280600681526020016550726963652d60d01b8152508160138111156100ae576100ae6102a5565b60808160138111156100c2576100c26102a5565b9052506100ce81610142565b60a05250506001600160a01b03811661010157604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61010a81610155565b503060c0521515610100526001600255610120919091528051602090910120610160525050506001600160a01b03166101a0526102e7565b600061014f826020610171565b92915050565b600180546001600160a01b031916905561016e81610201565b50565b600060208260ff161115610187576101876102bb565b60008260ff1684511161019b5783516101a0565b8260ff165b905060005b818110156101f957806008028582815181106101c3576101c36102d1565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c92909217916001016101a5565b505092915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060006060848603121561026657600080fd5b83516001600160a01b038116811461027d57600080fd5b6020850151909350801515811461029357600080fd5b80925050604084015190509250925092565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a051615ec2610400600039600081816105740152818161169101528181611726015281816118b801528181611b97015281816123570152818161272a01528181612aed01528181612e9d01528181613172015281816134da015281816135780152818161368e0152818161372b015281816137c00152613d19015260006109cb0152600061064d01526000610b2501526000611a4101526000818161067e0152611ab00152600050506000818161061701528181610961015281816115d10152818161164d0152818161180b015261182d015260008181611b6701526132760152600081816106f50152611e020152615ec26000f3fe6080604052600436106103505760003560e01c80638da5cb5b116101c6578063d5f39488116100f7578063f2fde38b11610095578063f9f34bb61161006f578063f9f34bb614610c7e578063fae91a5114610cab578063ff24fb4f14610ccb578063ff75890f14610ceb57610350565b8063f2fde38b14610c03578063f78eea8314610c23578063f9b4a27f14610c5e57610350565b8063e30c3978116100d1578063e30c397814610b7e578063eb92b29b14610b93578063ef1dff2b14610bb6578063f14cb81214610bd657610350565b8063d5f3948814610b13578063d6a3614f14610b47578063e1c9e3c014610b6957610350565b8063b411ee9411610164578063c064d3721161013e578063c064d37214610a79578063c3d98ea814610a99578063c5010d1714610ac6578063d3471e3414610ae657610350565b8063b411ee94146109ed578063b8d38c9614610a13578063bff852fa14610a3357610350565b8063a9e954b9116101a0578063a9e954b914610952578063abc86c6e14610986578063ac82c60814610999578063adb7c3f7146109b957610350565b80638da5cb5b146108f45780638df3fdfd14610912578063a55b471c1461093257610350565b80635be93984116102a057806379ba50971161023e57806384292f071161021857806384292f071461086557806386ac03e01461088557806389a87b16146108a55780638a416ea9146108d257610350565b806379ba50971461080e5780637b10399914610823578063806d7e8f1461083857610350565b80636b58960a1161027a5780636b58960a146107565780636d1178e514610776578063715018a6146107e457806375dadb32146107f957610350565b80635be93984146106c35780636175ff00146106e35780636ab221f81461072457610350565b806346d1d21a1161030d5780635001f3b5116102e75780635001f3b51461060857806352d1902d1461063b5780635479d9401461066f57806354fd4d50146106ae57610350565b806346d1d21a1461056257806349492ef1146105ae5780634efef9c0146105db57610350565b8063029db9581461048a5780630306732e146104bd57806303f3813d146104e1578063384ac938146105015780633e088e121461052f578063439fab9114610542575b34801561035c57600080fd5b506000356001600160e01b03191663e0d20f7360e01b14801561037e57503330145b156104365760006103a5602061039436846144ae565b6001600160c01b031916901b610d0b565b600601546001600160a01b03169050806104115760405162461bcd60e51b815260206004820152602260248201527f5769746e6574507269636546656564733a20756e736574746c656420736f6c7660448201526132b960f11b60648201526084015b60405180910390fd5b60405136600082376000803683855af43d806000843e818015610432578184f35b8184fd5b60405162461bcd60e51b815260206004820152602160248201527f5769746e6574507269636546656564733a206e6f7420696d706c656d656e74656044820152601960fa1b6064820152608401610408565b005b34801561049657600080fd5b506104aa6104a53660046144f2565b610d45565b6040519081526020015b60405180910390f35b3480156104c957600080fd5b506104d2610d56565b6040516104b4939291906145b9565b3480156104ed57600080fd5b506104886104fc3660046146f4565b610fb5565b34801561050d57600080fd5b5061052161051c3660046144f2565b6113ab565b6040516104b4929190614778565b6104aa61053d3660046144f2565b61147d565b34801561054e57600080fd5b5061048861055d3660046148d6565b6114b1565b34801561056e57600080fd5b506105967f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016104b4565b3480156105ba57600080fd5b506105ce6105c93660046144f2565b6118a1565b6040516104b49190614934565b3480156105e757600080fd5b506105fb6105f63660046144f2565b611951565b6040516104b4919061496b565b34801561061457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610596565b34801561064757600080fd5b506104aa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561067b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190151581526020016104b4565b3480156106ba57600080fd5b506105fb611a3a565b3480156106cf57600080fd5b506104aa6106de3660046144f2565b611a6a565b3480156106ef57600080fd5b506107177f000000000000000000000000000000000000000000000000000000000000000081565b6040516104b49190614992565b34801561073057600080fd5b5061074461073f3660046144f2565b611a7f565b60405160ff90911681526020016104b4565b34801561076257600080fd5b5061069e6107713660046149a0565b611a97565b34801561078257600080fd5b5061078b611af2565b6040516104b49190600060a08201905060ff835116825260ff602084015116602083015260408301516001600160401b038082166040850152806060860151166060850152806080860151166080850152505092915050565b3480156107f057600080fd5b50610488611b4c565b34801561080557600080fd5b506105fb611b60565b34801561081a57600080fd5b50610488611b8b565b34801561082f57600080fd5b50610596611b93565b34801561084457600080fd5b506108586108533660046144f2565b611c17565b6040516104b49190614a53565b34801561087157600080fd5b50610488610880366004614b39565b611df8565b34801561089157600080fd5b506104886108a0366004614b84565b6120a6565b3480156108b157600080fd5b506108c56108c03660046144f2565b612311565b6040516104b49190614bc5565b3480156108de57600080fd5b506108e76123f0565b6040516104b49190614c54565b34801561090057600080fd5b506000546001600160a01b0316610596565b34801561091e57600080fd5b506104aa61092d3660046144f2565b6124aa565b34801561093e57600080fd5b5061059661094d366004614c69565b6124bf565b34801561095e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000003f6104aa565b6104aa610994366004614ce6565b612598565b3480156109a557600080fd5b506104886109b4366004614d1c565b612652565b3480156109c557600080fd5b506108e77f000000000000000000000000000000000000000000000000000000000000000081565b3480156109f957600080fd5b506108e7610a083660046148d6565b805160209091012090565b348015610a1f57600080fd5b50610488610a2e366004614d72565b6126c6565b348015610a3f57600080fd5b5060408051808201909152601781527f5769746e65745072696365466565647344656661756c7400000000000000000060208201526105fb565b348015610a8557600080fd5b506104aa610a94366004614d96565b6126e6565b348015610aa557600080fd5b50610ab9610ab43660046144f2565b6127a9565b6040516104b49190614de9565b348015610ad257600080fd5b5061069e610ae1366004614b84565b6129bc565b348015610af257600080fd5b50610b06610b013660046144f2565b612abe565b6040516104b49190614df7565b348015610b1f57600080fd5b506105967f000000000000000000000000000000000000000000000000000000000000000081565b348015610b5357600080fd5b50600080516020615e6d833981519152546104aa565b348015610b7557600080fd5b50610488612b86565b348015610b8a57600080fd5b50610596612cfe565b348015610b9f57600080fd5b5060045460405161ffff90911681526020016104b4565b348015610bc257600080fd5b506105fb610bd13660046144f2565b612d12565b348015610be257600080fd5b50610bf6610bf13660046144f2565b612dad565b6040516104b49190614e51565b348015610c0f57600080fd5b50610488610c1e3660046149a0565b612dc0565b348015610c2f57600080fd5b50610c43610c3e366004614d96565b612dd4565b604080519384526020840192909252908201526060016104b4565b348015610c6a57600080fd5b50610b06610c793660046144f2565b612e6e565b348015610c8a57600080fd5b50610c9e610c99366004614e5f565b612ed3565b6040516104b49190614e94565b348015610cb757600080fd5b50610488610cc6366004614ee2565b612faa565b348015610cd757600080fd5b50610488610ce63660046146f4565b613051565b348015610cf757600080fd5b50610596610d06366004614c69565b6130b2565b6001600160e01b03191660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b6000610d5082613141565b92915050565b600080516020615e6d83398151915280546040805160208084028201810190925282815260609384938493830182828015610ddd57602002820191906000526020600020906000905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610d9f5790505b5050505050925082516001600160401b03811115610dfd57610dfd61479c565b604051908082528060200260200182016040528015610e3057816020015b6060815260200190600190039081610e1b5790505b50915082516001600160401b03811115610e4c57610e4c61479c565b604051908082528060200260200182016040528015610e75578160200160208202803683370190505b50905060005b8351811015610faf576000610ea8858381518110610e9b57610e9b614efe565b6020026020010151610d0b565b9050806000018054610eb990614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590614f14565b8015610f325780601f10610f0757610100808354040283529160200191610f32565b820191906000526020600020905b815481529060010190602001808311610f1557829003601f168201915b5050505050848381518110610f4957610f49614efe565b602090810291909101015260068101546001600160a01b031615610f8357600681015460601b6bffffffffffffffffffffffff1916610f89565b80600501545b838381518110610f9b57610f9b614efe565b602090810291909101015250600101610e7b565b50909192565b610fbd613217565b6001600160a01b03831661101f5760405162461bcd60e51b815260206004820152602360248201527f5769746e6574507269636546656564733a206e6f20736f6c766572206164647260448201526265737360e81b6064820152608401610408565b600061106086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b9050600061106d82610d0b565b9050806002015460000361113d5780611087878983614f98565b506110928787613244565b60018201805460ff191660ff92909216919091179055600080516020615e4d8339815191526001908101546110c69161506d565b60028201556006810180546001600160a01b0319166001600160a01b038716179055600080516020615e4d8339815191526001908101805491820181556000908152602090206008820401805463ffffffff60079093166004026101000a928302191660e085901c92909202919091179055611179565b60068101546001600160a01b0386811691161461117957600060058201556006810180546001600160a01b0319166001600160a01b0387161790555b600080866001600160a01b031663e6f8715860e01b8588886040516024016111a3939291906150ee565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111e1919061516a565b600060405180830381855af49150503d806000811461121c576040519150601f19603f3d011682016040523d82523d6000602084013e611221565b606091505b50915091508161127b576004810190508080602001905181019061124591906151de565b6040516020016112559190615212565b60408051601f198184030181529082905262461bcd60e51b82526104089160040161496b565b5050600080306001600160a01b031663e0d20f7360e01b856040516024016112a39190614c54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112e1919061516a565b600060405180830381855afa9150503d806000811461131c576040519150601f19603f3d011682016040523d82523d6000602084013e611321565b606091505b509150915081611355576004810190508080602001905181019061134591906151de565b6040516020016112559190615275565b5050604080516001600160e01b0319841681526001600160a01b03871660208201527f850802cc670161a9f185e45414c2fe7efb5e71b23a8e32a53caffb7dd000aca3910160405180910390a150505050505050565b600060606113b883610d0b565b600601546001600160a01b0316915060006113d28461332a565b905080516001600160401b038111156113ed576113ed61479c565b60405190808252806020026020018201604052801561142057816020015b606081526020019060019003908161140b5790505b50915060005b81518110156114765761145182828151811061144457611444614efe565b6020026020010151612d12565b83828151811061146357611463614efe565b6020908102919091010152600101611426565b5050915091565b6040805180820190915260035460ff8116825261010090046001600160401b03166020820152600090610d50908390613414565b6000546001600160a01b03168061152a57818060200190518101906114d691906152c8565b90506114e18161394f565b60408051808201909152600a808252630bebc2006020909201919091526003805468ffffffffffffffffff1916640bebc2000a1790556004805461ffff19169091179055611582565b336001600160a01b038216146115825760405162461bcd60e51b815260206004820152601f60248201527f5769746e6574507269636546656564733a206e6f7420746865206f776e6572006044820152606401610408565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54158015906115f357507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f00000000000000000000000000000000000000000000000000000000000000003f145b1561164b5760405162461bcd60e51b815260206004820152602260248201527f5769746e6574507269636546656564733a20616c726561647920757067726164604482015261195960f21b6064820152608401610408565b7f00000000000000000000000000000000000000000000000000000000000000003f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b6117125760405162461bcd60e51b815260206004820152602360248201527f5769746e6574507269636546656564733a20696e6578697374656e74206f7261604482015262636c6560e81b6064820152608401610408565b63baeca88b60e01b6001600160e01b0319167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a691906152e5565b6001600160e01b031916146118095760405162461bcd60e51b8152602060048201526024808201527f5769746e6574507269636546656564733a20756e636f6d706c69616e74206f7260448201526361636c6560e01b6064820152608401610408565b7f00000000000000000000000000000000000000000000000000000000000000003f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f6611888611a3a565b604051611895919061496b565b60405180910390a45050565b6040805180820190915260008152606060208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a77fc1a46118ee84611a6a565b6040518263ffffffff1660e01b815260040161190c91815260200190565b600060405180830381865afa158015611929573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d509190810190615302565b6060600061195e83610d0b565b60058101549091506000036119b55760405162461bcd60e51b815260206004820152601d60248201527f5769746e6574507269636546656564733a206e6f2052414420686173680000006044820152606401610408565b6119bd611b93565b6001600160a01b0316632ebf5d5c82600501546040518263ffffffff1660e01b81526004016119ee91815260200190565b600060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a3391908101906151de565b9392505050565b6060611a657f0000000000000000000000000000000000000000000000000000000000000000613968565b905090565b6000611a7582610d0b565b6004015492915050565b6000611a8a82610d0b565b6001015460ff1692915050565b600080611aac6000546001600160a01b031690565b90507f00000000000000000000000000000000000000000000000000000000000000008015611a335750826001600160a01b0316816001600160a01b0316149392505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805180820190915260035460ff8116825261010090046001600160401b03166020820152611a6590613a0c565b611b54613217565b611b5e600061394f565b565b6060611a657f0000000000000000000000000000000000000000000000000000000000000000613ab3565b611b5e613b57565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6591906152c8565b60606000611c23611b93565b6001600160a01b031663a83e942c611c3a856124aa565b6040518263ffffffff1660e01b8152600401611c5891815260200190565b600060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c9d91908101906153ac565b905080516001600160401b03811115611cb857611cb861479c565b604051908082528060200260200182016040528015611d2a57816020015b611d176040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b815260200190600190039081611cd65790505b50915060005b8251811015611df157611d41611b93565b6001600160a01b0316639dd48757838381518110611d6157611d61614efe565b60200260200101516040518263ffffffff1660e01b8152600401611d8791815260200190565b600060405180830381865afa158015611da4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611dcc9190810190615577565b838281518110611dde57611dde614efe565b6020908102919091010152600101611d30565b5050919050565b611e00613217565b7f00000000000000000000000000000000000000000000000000000000000000006013811115611e3257611e3261491e565b611e3a611b93565b6001600160a01b0316634c729104836040518263ffffffff1660e01b8152600401611e6791815260200190565b602060405180830381865afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea89190615682565b6013811115611eb957611eb961491e565b14611f155760405162461bcd60e51b815260206004820152602660248201527f5769746e6574507269636546656564733a2062616420726573756c742064617460448201526561207479706560d01b6064820152608401610408565b6000611f5684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b90506000611f6382610d0b565b905080600201546000036120375780611f7d858783614f98565b50611f888585613244565b60018201805460ff191660ff92909216919091179055600080516020615e4d833981519152600190810154611fbc9161506d565b600282015560058101839055600080516020615e6d83398151915280546001810182556000919091527fb7ef506da7909f25321b247725840c95fced7275a59588a4236c0671ab1d82216008820401805463ffffffff60079093166004026101000a928302191660e085901c9290920291909117905561205c565b8281600501541461205c57600581018390556006810180546001600160a01b03191690555b604080516001600160e01b031984168152602081018590527f37206f9df7db3fe5c4edfea9c5ce9ea406912fc4133f5c67200273da0c09e7b1910160405180910390a15050505050565b6120ae613217565b60006120ef83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b9050600080516020615e6d833981519152600061210b83610d0b565b600281015490915060008190036121645760405162461bcd60e51b815260206004820152601e60248201527f5769746e6574507269636546656564733a20756e6b6e6f776e206665656400006044820152606401610408565b825460009084906121779060019061569d565b8154811061218757612187614efe565b6000918252602090912060088204015460079091166004026101000a900460e01b905080846121b760018561569d565b815481106121c7576121c7614efe565b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555083805480612207576122076156b0565b600082815260209020600860001990920191820401805463ffffffff600460078516026101000a021916905590558161223f82610d0b565b600201556001600160e01b0319851660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602052604081209061228682826143fb565b5060018101805460ff191690556000600282018190556003820181905560048201819055600582018190556006820180546001600160a01b031916905560078201819055600890910155506040517f5296cc0e8dad8eeece6ce7d0928746294283b850d6261e03e7028a84de61f0b690612301908690614c54565b60405180910390a1505050505050565b6123556040805160c081018252600080825260208083018290528284018290526060808401526080830182905283518085019094528184528301529060a082015290565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630aa4112a61238d84611a6a565b6040518263ffffffff1660e01b81526004016123ab91815260200190565b600060405180830381865afa1580156123c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d509190810190615750565b600080516020615e6d83398151915254600090156124a757612457600080516020615e4d83398151915260010160008154811061242f5761242f614efe565b90600052602060002090600891828204019190066004029054906101000a900460e01b613bd2565b905060015b600080516020615e6d833981519152548110156124a557612499600080516020615e4d833981519152600101828154811061242f5761242f614efe565b9091189060010161245c565b505b90565b60006124b582610d0b565b6005015492915050565b60006124c9613217565b604051632956d1c760e21b815273579b4ad5e67e5b491a33a033a02a70769d7af8379063a55b471c90612506908890889088908890600401615811565b602060405180830381865af4158015612523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254791906152c8565b90507f3c07c0cbdabca8310d65b09f79c58655b46c3035d57c452177e3d49972ff5cec81826001600160a01b03163f85856040516125889493929190615838565b60405180910390a1949350505050565b6040805180820190915260035460ff8116825261010090046001600160401b031660208201526000906125e4906125d436859003850185615860565b9051905160ff9182169116101590565b61263a5760405162461bcd60e51b815260206004820152602160248201527f5769746e6574507269636546656564733a20756e7365637572652075706461746044820152606560f81b6064820152608401610408565b611a338361264d36859003850185615860565b613414565b61265a613217565b6126c18383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa15801561269d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088091906158a5565b505050565b6126ce613217565b6004805461ffff191661ffff92909216919091179055565b6004546000906064906126fd9061ffff16826158be565b604051630f7b104360e31b8152600481018590526020602482015261ffff91909116906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637bd8821890604401602060405180830381865afa158015612771573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279591906158a5565b61279f91906158d9565b610d509190615906565b6127d16040805160808101825260008082526020820181905291810182905290606082015290565b60006127dc83613141565b9050801561285a5760006127ef84612e6e565b905060006128008260800151613c61565b9050604051806080016040528061281683613c7f565b8152602001836040015163ffffffff1681526020018360600151815260200161283e87612dad565b600581111561284f5761284f61491e565b905295945050505050565b600061286584610d0b565b600601546001600160a01b03169050801561297057600080306001600160a01b031663e0d20f7360e01b876040516024016128a09190614c54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516128de919061516a565b600060405180830381855afa9150503d8060008114612919576040519150601f19603f3d011682016040523d82523d6000602084013e61291e565b606091505b509150915081612952576004810190508080602001905181019061294291906151de565b604051602001611255919061591a565b808060200190518101906129669190615963565b9695505050505050565b604051806080016040528060008152602001600081526020016000801b815260200161299b86612dad565b60058111156129ac576129ac61491e565b9052949350505050565b50919050565b6000806129fe84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b90506001600160e01b03198116612aab612a1783610d0b565b8054612a2290614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054612a4e90614f14565b8015612a9b5780601f10612a7057610100808354040283529160200191612a9b565b820191906000526020600020905b815481529060010190602001808311612a7e57829003601f168201915b5050505050805160209091012090565b6001600160e01b03191614949350505050565b6040805160a08101825260008082526020820181905291810182905260608082019290925260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f61921b2612b2384611a6a565b6040518263ffffffff1660e01b8152600401612b4191815260200190565b600060405180830381865afa158015612b5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5091908101906159cc565b612b8e613217565b600080516020615e6d83398151915280545b8015612cfa57600082612bb460018461569d565b81548110612bc457612bc4614efe565b90600052602060002090600891828204019190066004029054906101000a900460e01b9050612bfe600080516020615e4d83398151915290565b6001600160e01b0319821660009081526002919091016020526040812090612c2682826143fb565b5060018101805460ff191690556000600282018190556003820181905560048201819055600582018190556006820180546001600160a01b0319169055600782018190556008909101558254839080612c8157612c816156b0565b600082815260209020600860001990920191820401805463ffffffff600460078516026101000a021916905590556040517f5296cc0e8dad8eeece6ce7d0928746294283b850d6261e03e7028a84de61f0b690612cdf908390614c54565b60405180910390a15080612cf281615a88565b915050612ba0565b5050565b6000611a656001546001600160a01b031690565b6060612d1d82610d0b565b8054612d2890614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054612d5490614f14565b8015612da15780601f10612d7657610100808354040283529160200191612da1565b820191906000526020600020905b815481529060010190602001808311612d8457829003601f168201915b50505050509050919050565b6000610d50612dbb83611a6a565b613cfb565b612dc8613217565b612dd181613d94565b50565b600080600080612de3856127a9565b8051602082015191925090600283606001516005811115612e0657612e0661491e565b14612e5857600183606001516005811115612e2357612e2361491e565b1480612e445750600483606001516005811115612e4257612e4261491e565b145b612e5057610190612e5b565b610194612e5b565b60c85b919550935061ffff169150509193909250565b6040805160a08101825260008082526020820181905291810182905260608082019290925260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f61921b2612b2384613141565b6060816001600160401b03811115612eed57612eed61479c565b604051908082528060200260200182016040528015612f4657816020015b612f336040805160808101825260008082526020820181905291810182905290606082015290565b815260200190600190039081612f0b5790505b50905060005b82811015612fa357612f7e848483818110612f6957612f69614efe565b9050602002016020810190610ab491906144f2565b828281518110612f9057612f90614efe565b6020908102919091010152600101612f4c565b5092915050565b612fb2613217565b612fbb81613dc6565b6130075760405162461bcd60e51b815260206004820152601d60248201527f5769746e6574507269636546656564733a20696e76616c696420534c410000006044820152606401610408565b8060036130148282615a9f565b9050507f084efe053ac15af09a2db38bb176035f1d94cbc8a775c7761e662f7f11ae6940816040516130469190615af1565b60405180910390a150565b613059613217565b6130ab8585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161308c929190615b7d565b6020604051808303816000875af115801561269d573d6000803e3d6000fd5b5050505050565b6040516001628a76f160e01b0319815260009073579b4ad5e67e5b491a33a033a02a70769d7af8379063ff75890f906130f5908890889088908890600401615811565b602060405180830381865af4158015613112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313691906152c8565b90505b949350505050565b60008061314d83611a6a565b90506000811180156131f85750600260405163234fe6e360e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063234fe6e390602401602060405180830381865afa1580156131c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e59190615c0d565b60058111156131f6576131f661491e565b145b156132035792915050565b61320c83610d0b565b600301549392505050565b6000546001600160a01b03163314611b5e5760405163118cdaa760e01b8152336004820152602401610408565b60405163e78d44d960e01b815260009073579b4ad5e67e5b491a33a033a02a70769d7af8379063e78d44d9906132a2907f00000000000000000000000000000000000000000000000000000000000000009087908790600401615c28565b602060405180830381865af49250505080156132db575060408051601f3d908101601f191682019092526132d891810190615c42565b60015b613323576132e7615c5f565b806308c379a00361331757506132fb615c7a565b806133065750613319565b80604051602001611255919061591a565b505b3d6000803e3d6000fd5b9050610d50565b6001600160e01b0319811660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602090815260409182902060089081015483518281526101208101909452606093909290919082016101008036833701905050915060005b600881101561340c57818382815181106133af576133af614efe565b60200260200101906001600160e01b03191690816001600160e01b031916815250508281815181106133e3576133e3614efe565b60209081029190910101516001600160e01b0319161561340c57602082901b9150600101613393565b825250919050565b60008061342084610d0b565b600581015490915015613895576134363a6126e6565b9150813410156134965760405162461bcd60e51b815260206004820152602560248201527f5769746e6574507269636546656564733a20696e73756666696369656e742072604482015264195dd85c9960da1b6064820152608401610408565b600481015460006134a682613cfb565b905060018160058111156134bc576134bc61491e565b0361364f57604051630552089560e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630aa4112a90602401600060405180830381865afa158015613529573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135519190810190615750565b9050600085826040015160080b6135689190615d03565b90506000811315613643578095507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ec5946db87866040518363ffffffff1660e01b81526004016135c591815260200190565b6000604051808303818588803b1580156135de57600080fd5b505af11580156135f2573d6000803e3d6000fd5b505060408051888152602081018b90526001600160e01b03198d1694503293507fc75bbe35e1d3486439c776ccf0fb47aede3d28e1bf548e01357b57132974cd9692500160405180910390a3613648565b600095505b505061388e565b60028160058111156136635761366361491e565b036137155760038301541561370957600383015460405163045bf42f60e11b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906308b7e85e906024016000604051808303816000875af11580156136df573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261370791908101906159cc565b505b600383018290556137a4565b60405163045bf42f60e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906308b7e85e906024016000604051808303816000875af192505050801561379d57506040513d6000823e601f3d908101601f1916820160405261379a91908101906159cc565b60015b156137a457505b6005830154604051631ee15bd160e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691633dc2b7a29187916137f7918a90600401615d23565b60206040518083038185885af1158015613815573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061383a91906158a5565b600484018190556040519092506001600160e01b031987169032907e9bd781be3a9c4660642983aa92bc7a7484c4b0cb0c2afa0f9174c74061d5039061388590869089908b90615d4d565b60405180910390a35b5050613909565b60068101546001600160a01b0316156138c1576138ba6138b48561332a565b84613e53565b9150613909565b60405162461bcd60e51b815260206004820152601e60248201527f5769746e6574507269636546656564733a20756e6b6e6f776e206665656400006044820152606401610408565b34821015612fa357336108fc61391f843461569d565b6040518115909202916000818181858888f19350505050158015613947573d6000803e3d6000fd5b505092915050565b600180546001600160a01b0319169055612dd181613f10565b6060600061397583613f60565b6001600160401b0381111561398c5761398c61479c565b6040519080825280601f01601f1916602001820160405280156139b6576020820181803683370190505b50905060005b8151811015612fa3578381602081106139d7576139d7614efe565b1a60f81b8282815181106139ed576139ed614efe565b60200101906001600160f81b031916908160001a9053506001016139bc565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280836000015160ff168152602001603360ff16815260200183602001516001600160401b0316815260200183602001516064613a7d9190615d7c565b6001600160401b03168152602001836000015160ff168460200151613aa29190615d9f565b6001600160401b0316905292915050565b60606000613ac083613f99565b6001600160401b03811115613ad757613ad761479c565b6040519080825280601f01601f191660200182016040528015613b01576020820181803683370190505b50905060005b8151811015612fa357838160208110613b2257613b22614efe565b1a60f81b828281518110613b3857613b38614efe565b60200101906001600160f81b031916908160001a905350600101613b07565b3380613b61612cfe565b6001600160a01b031614613bc95760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610408565b612dd18161394f565b600080613bde83610d0b565b6005015414613c2e5781613bf183610d0b565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b81613c3883610d0b565b60080154604080516001600160e01b03199093166020840152820152606001613c11565b919050565b613c6961443a565b6000613c7483613fd2565b9050611a3381613ff7565b6000818060000151613cee5760405162461bcd60e51b815260206004820152603260248201527f5769746e65743a20747269656420746f206465636f64652076616c756520667260448201527137b69032b93937b932b2103932b9bab63a1760711b6064820152608401610408565b611a33836020015161402b565b60008115613d8c5760405163234fe6e360e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063234fe6e390602401602060405180830381865afa158015613d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d509190615c0d565b506002919050565b613d9c613217565b6001600160a01b038116613bc957604051631e4fbdf760e01b815260006004820152602401610408565b600080613dd96040840160208501615dc5565b6001600160401b0316118015613dfe57506000613df96020840184615de2565b60ff16115b8015613e1a5750607f613e146020840184615de2565b60ff1611155b8015610d5057506404a817c800613e376040840160208501615dc5565b613e42906064615d7c565b6001600160401b0316101592915050565b600080835134613e639190615906565b905060005b845181101561394757306001600160a01b031663abc86c6e83878481518110613e9357613e93614efe565b6020026020010151876040518463ffffffff1660e01b8152600401613eb9929190615dff565b60206040518083038185885af1158015613ed7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613efc91906158a5565b613f06908461506d565b9250600101613e68565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b6020811015613c5c57818160208110613f7e57613f7e614efe565b1a60f81b6001600160f81b03191615613c5c57600101613f63565b60005b6020811015613c5c57818160208110613fb757613fb7614efe565b1a60f81b6001600160f81b03191615613c5c57600101613f9c565b613fda614452565b6040805180820190915282815260006020820152611a338161408e565b613fff61443a565b5060a0810151604080518082019091526001600160401b03909116602714158152602081019190915290565b60008160008060ff16826040015160ff161461406b57604080830151905161800560e51b815260ff91821660048201529082166024820152604401610408565b61407d846000015185606001516141ae565b6001600160401b0316949350505050565b614096614452565b81515182906000036140bb576040516309036d4760e21b815260040160405180910390fd5b600060ff816001600160401b038160015b801561413e576140db8961426f565b9550816140e781615e33565b6007600589901c169650601f8816955092505060051985016141365760208901516141128a866141ae565b9350808a60200151614124919061569d565b61412e908461506d565b9250506140cc565b5060006140cc565b600760ff861611156141685760405163bd2ac87960e01b815260ff86166004820152602401610408565b506040805160c08101825298895260ff95861660208a015293851693880193909352921660608601526001600160401b0390811660808601521660a08401525090919050565b600060188260ff1610156141c6575060ff8116610d50565b8160ff166018036141e4576141da8361426f565b60ff169050610d50565b8160ff16601903614203576141f8836142d1565b61ffff169050610d50565b8160ff16601a03614224576142178361433d565b63ffffffff169050610d50565b8160ff16601b03614238576133238361439c565b8160ff16601f0361425157506001600160401b03610d50565b604051636d785b1360e01b815260ff83166004820152602401610408565b60008160200151826000015151808211156142a7576040516363a056dd60e01b81526004810183905260248101829052604401610408565b83516020850180518083016001015195509081906142c482615e33565b8152505050505050919050565b6000816020015160026142e4919061506d565b82515180821115614312576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600281840181015196509091614330828461506d565b9052509395945050505050565b600081602001516004614350919061506d565b8251518082111561437e576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600481840181015196509091614330828461506d565b6000816020015160086143af919061506d565b825151808211156143dd576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600881840181015196509091614330828461506d565b50805461440790614f14565b6000825580601f10614417575050565b601f016020900490600052602060002090810190612dd19190614499565b905290565b60405180604001604052806000151581526020016144355b604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b5b808211156124a5576000815560010161449a565b6001600160c01b031981358181169160088510156139475760089490940360031b84901b1690921692915050565b6001600160e01b031981168114612dd157600080fd5b60006020828403121561450457600080fd5b8135611a33816144dc565b60005b8381101561452a578181015183820152602001614512565b50506000910152565b6000815180845261454b81602086016020860161450f565b601f01601f19169290920160200192915050565b60008282518085526020808601955060208260051b8401016020860160005b848110156145ac57601f1986840301895261459a838351614533565b9884019892509083019060010161457e565b5090979650505050505050565b606080825284519082018190526000906020906080840190828801845b828110156145fc5781516001600160e01b031916845292840192908401906001016145d6565b50505083810382850152614610818761455f565b8481036040860152855180825283870192509083019060005b8181101561464557835183529284019291840191600101614629565b509098975050505050505050565b60008083601f84011261466557600080fd5b5081356001600160401b0381111561467c57600080fd5b60208301915083602082850101111561469457600080fd5b9250929050565b6001600160a01b0381168114612dd157600080fd5b60008083601f8401126146c257600080fd5b5081356001600160401b038111156146d957600080fd5b6020830191508360208260051b850101111561469457600080fd5b60008060008060006060868803121561470c57600080fd5b85356001600160401b038082111561472357600080fd5b61472f89838a01614653565b9097509550602088013591506147448261469b565b9093506040870135908082111561475a57600080fd5b50614767888289016146b0565b969995985093965092949392505050565b6001600160a01b03831681526040602082018190526000906131399083018461455f565b634e487b7160e01b600052604160045260246000fd5b604081018181106001600160401b03821117156147d1576147d161479c565b60405250565b60c081018181106001600160401b03821117156147d1576147d161479c565b60a081018181106001600160401b03821117156147d1576147d161479c565b601f8201601f191681016001600160401b038111828210171561483a5761483a61479c565b6040525050565b60405160e081016001600160401b03811182821017156148635761486361479c565b60405290565b60006001600160401b038211156148825761488261479c565b50601f01601f191660200190565b600061489b83614869565b6040516148a88282614815565b8092508481528585850111156148bd57600080fd5b8484602083013760006020868301015250509392505050565b6000602082840312156148e857600080fd5b81356001600160401b038111156148fe57600080fd5b8201601f8101841361490f57600080fd5b61313984823560208401614890565b634e487b7160e01b600052602160045260246000fd5b602081526000825160ff811061494c5761494c61491e565b8060208401525060208301516040808401526131396060840182614533565b602081526000611a336020830184614533565b6014811061498e5761498e61491e565b9052565b60208101610d50828461497e565b6000602082840312156149b257600080fd5b8135611a338161469b565b6005811061498e5761498e61491e565b600082825180855260208086019550808260051b8401018186016000805b85811015614a4557868403601f19018a5282518460408101845b6002811015614a30578782038352614a1e828551614533565b93890193928901929150600101614a05565b509b87019b95505050918401916001016149eb565b509198975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561464557603f19898403018552815160e060ff825116855288820151614aa88a8701826149bd565b5087820151614ab98987018261497e565b506060808301518282880152614ad183880182614533565b9250505060808083015186830382880152614aec8382614533565b9250505060a08083015186830382880152614b0783826149cd565b9250505060c08083015192508582038187015250614b258183614533565b968901969450505090860190600101614a7c565b600080600060408486031215614b4e57600080fd5b83356001600160401b03811115614b6457600080fd5b614b7086828701614653565b909790965060209590950135949350505050565b60008060208385031215614b9757600080fd5b82356001600160401b03811115614bad57600080fd5b614bb985828601614653565b90969095509350505050565b6020815260018060a01b03825116602082015262ffffff602083015116604082015268ffffffffffffffffff60408301511660608201526000606083015160e06080840152614c18610100840182614533565b9050608084015160a084015260a0840151614c4c60c0850182805160ff1682526020908101516001600160401b0316910152565b509392505050565b6001600160e01b031991909116815260200190565b60008060008060408587031215614c7f57600080fd5b84356001600160401b0380821115614c9657600080fd5b614ca288838901614653565b90965094506020870135915080821115614cbb57600080fd5b50614cc887828801614653565b95989497509550505050565b6000604082840312156129b657600080fd5b60008060608385031215614cf957600080fd5b8235614d04816144dc565b9150614d138460208501614cd4565b90509250929050565b600080600060408486031215614d3157600080fd5b83356001600160401b03811115614d4757600080fd5b614d5386828701614653565b9094509250506020840135614d678161469b565b809150509250925092565b600060208284031215614d8457600080fd5b813561ffff81168114611a3357600080fd5b600060208284031215614da857600080fd5b5035919050565b6006811061498e5761498e61491e565b80518252602081015160208301526040810151604083015260608101516126c16060840182614daf565b60808101610d508284614dbf565b6020815260018060a01b0382511660208201526001600160401b03602083015116604082015263ffffffff6040830151166060820152606082015160808201526000608083015160a08084015261313960c0840182614533565b60208101610d508284614daf565b60008060208385031215614e7257600080fd5b82356001600160401b03811115614e8857600080fd5b614bb9858286016146b0565b6020808252825182820181905260009190848201906040850190845b81811015614ed657614ec3838551614dbf565b9284019260809290920191600101614eb0565b50909695505050505050565b600060408284031215614ef457600080fd5b611a338383614cd4565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614f2857607f821691505b6020821081036129b657634e487b7160e01b600052602260045260246000fd5b601f8211156126c1576000816000526020600020601f850160051c81016020861015614f715750805b601f850160051c820191505b81811015614f9057828155600101614f7d565b505050505050565b6001600160401b03831115614faf57614faf61479c565b614fc383614fbd8354614f14565b83614f48565b6000601f841160018114614ff75760008515614fdf5750838201355b600019600387901b1c1916600186901b1783556130ab565b600083815260209020601f19861690835b828110156150285786850135825560209485019460019092019101615008565b50868210156150455760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d5057610d50615057565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e198436030181126150c057600080fd5b83016020810192503590506001600160401b038111156150df57600080fd5b80360382131561469457600080fd5b60006040820163ffffffff60e01b861683526020604060208501528185835260608501905060608660051b86010192508660005b8781101561515c57868503605f1901835261513d828a6150a9565b615148878284615080565b965050509183019190830190600101615122565b509298975050505050505050565b6000825161517c81846020870161450f565b9190910192915050565b600082601f83011261519757600080fd5b81516151a281614869565b6040516151af8282614815565b8281528560208487010111156151c457600080fd5b6151d583602083016020880161450f565b95945050505050565b6000602082840312156151f057600080fd5b81516001600160401b0381111561520657600080fd5b61313984828501615186565b7f5769746e657450726963654665656455706772616461626c653a20736f6c7665815274039103b30b634b230ba34b7b7103330b4b632b21d1605d1b60208201526000825161526881603585016020870161450f565b9190910160350192915050565b7f5769746e6574507269636546656564733a20736d6f6b652d746573742066616981526403632b21d160dd1b6020820152600082516152bb81602585016020870161450f565b9190910160250192915050565b6000602082840312156152da57600080fd5b8151611a338161469b565b6000602082840312156152f757600080fd5b8151611a33816144dc565b60006020828403121561531457600080fd5b81516001600160401b038082111561532b57600080fd5b908301906040828603121561533f57600080fd5b60405161534b816147b2565b825160ff811061535a57600080fd5b815260208301518281111561536e57600080fd5b61537a87828601615186565b60208301525095945050505050565b60006001600160401b038211156153a2576153a261479c565b5060051b60200190565b600060208083850312156153bf57600080fd5b82516001600160401b038111156153d557600080fd5b8301601f810185136153e657600080fd5b80516153f181615389565b6040516153fe8282614815565b82815260059290921b830184019184810191508783111561541e57600080fd5b928401925b8284101561543c57835182529284019290840190615423565b979650505050505050565b60ff81168114612dd157600080fd5b8051613c5c81615447565b805160058110613c5c57600080fd5b805160148110613c5c57600080fd5b600082601f83011261549057600080fd5b8151602061549d82615389565b6040516154aa8282614815565b83815260059390931b85018201928281019150868411156154ca57600080fd5b8286015b8481101561556c5780516001600160401b03808211156154ee5760008081fd5b818901915089603f8301126155035760008081fd5b60405161550f816147b2565b80606084018c8111156155225760008081fd5b8885015b8181101561555a5780518581111561553e5760008081fd5b61554c8f8c838a0101615186565b845250918901918901615526565b505050855250509183019183016154ce565b509695505050505050565b60006020828403121561558957600080fd5b81516001600160401b03808211156155a057600080fd5b9083019060e082860312156155b457600080fd5b6155bc614841565b6155c583615456565b81526155d360208401615461565b60208201526155e460408401615470565b60408201526060830151828111156155fb57600080fd5b61560787828601615186565b60608301525060808301518281111561561f57600080fd5b61562b87828601615186565b60808301525060a08301518281111561564357600080fd5b61564f8782860161547f565b60a08301525060c08301518281111561566757600080fd5b61567387828601615186565b60c08301525095945050505050565b60006020828403121561569457600080fd5b611a3382615470565b81810381811115610d5057610d50615057565b634e487b7160e01b600052603160045260246000fd5b805162ffffff81168114613c5c57600080fd5b805168ffffffffffffffffff81168114613c5c57600080fd5b6001600160401b0381168114612dd157600080fd5b60006040828403121561571957600080fd5b604051615725816147b2565b809150825161573381615447565b81526020830151615743816156f2565b6020919091015292915050565b60006020828403121561576257600080fd5b81516001600160401b038082111561577957600080fd5b9083019060e0828603121561578d57600080fd5b604051615799816147d7565b82516157a48161469b565b81526157b2602084016156c6565b60208201526157c3604084016156d9565b60408201526060830151828111156157da57600080fd5b6157e687828601615186565b606083015250608083015160808201526158038660a08501615707565b60a082015295945050505050565b604081526000615825604083018688615080565b828103602084015261543c818587615080565b60018060a01b0385168152836020820152606060408201526000612966606083018486615080565b60006040828403121561587257600080fd5b60405161587e816147b2565b823561588981615447565b81526020830135615899816156f2565b60208201529392505050565b6000602082840312156158b757600080fd5b5051919050565b61ffff818116838216019080821115612fa357612fa3615057565b8082028115828204841417610d5057610d50615057565b634e487b7160e01b600052601260045260246000fd5b600082615915576159156158f0565b500490565b7102bb4ba3732ba283934b1b2a332b2b2399d160751b81526000825161594781601285016020870161450f565b9190910160120192915050565b805160068110613c5c57600080fd5b60006080828403121561597557600080fd5b604051608081018181106001600160401b03821117156159975761599761479c565b80604052508251815260208301516020820152604083015160408201526159c060608401615954565b60608201529392505050565b6000602082840312156159de57600080fd5b81516001600160401b03808211156159f557600080fd5b9083019060a08286031215615a0957600080fd5b604051615a15816147f6565b8251615a208161469b565b81526020830151615a30816156f2565b6020820152604083015163ffffffff81168114615a4c57600080fd5b604082015260608381015190820152608083015182811115615a6d57600080fd5b615a7987828601615186565b60808301525095945050505050565b600081615a9757615a97615057565b506000190190565b8135615aaa81615447565b60ff8116905081548160ff1982161783556020840135615ac9816156f2565b68ffffffffffffffff008160081b168368ffffffffffffffffff198416171784555050505050565b604081018235615b0081615447565b60ff1682526020830135615b13816156f2565b6001600160401b03811660208401525092915050565b6000838385526020808601955060208560051b8301018460005b878110156145ac57848303601f19018952615b5e82886150a9565b615b69858284615080565b9a86019a9450505090830190600101615b43565b6020808252818101839052600090600560408085019086831b86010187855b8881101561464557878303603f190184528135368b9003601e19018112615bc257600080fd5b8a0186810190356001600160401b03811115615bdd57600080fd5b80871b3603821315615bee57600080fd5b615bf9858284615b29565b958801959450505090850190600101615b9c565b600060208284031215615c1f57600080fd5b611a3382615954565b838152604060208201526000613136604083018486615080565b600060208284031215615c5457600080fd5b8151611a3381615447565b600060033d11156124a75760046000803e5060005160e01c90565b600060443d1015615c885790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615cb757505050505090565b8285019150815181811115615ccf5750505050505090565b843d8701016020828501011115615ce95750505050505090565b615cf860208286010187614815565b509095945050505050565b8181036000831280158383131683831282161715612fa357612fa3615057565b82815260608101611a336020830184805160ff1682526020908101516001600160401b0316910152565b8381526020808201849052825160ff1660408301528201516001600160401b0316606082015260808101613139565b6001600160401b0381811683821602808216919082811461394757613947615057565b60006001600160401b0380841680615db957615db96158f0565b92169190910492915050565b600060208284031215615dd757600080fd5b8135611a33816156f2565b600060208284031215615df457600080fd5b8135611a3381615447565b6001600160e01b03198316815260608101611a336020830184805160ff1682526020908101516001600160401b0316910152565b600060018201615e4557615e45615057565b506001019056fee36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ffe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200a26469706673582212200323fb8b972d3201c0ca285eb7b2dff0273fc4ebf93ab2c4f7a0b21304a964f964736f6c6343000819003300000000000000000000000077703ae126b971c9946d562f41dd47071da007770000000000000000000000000000000000000000000000000000000000000001322e302e31342d34386336646436000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106103505760003560e01c80638da5cb5b116101c6578063d5f39488116100f7578063f2fde38b11610095578063f9f34bb61161006f578063f9f34bb614610c7e578063fae91a5114610cab578063ff24fb4f14610ccb578063ff75890f14610ceb57610350565b8063f2fde38b14610c03578063f78eea8314610c23578063f9b4a27f14610c5e57610350565b8063e30c3978116100d1578063e30c397814610b7e578063eb92b29b14610b93578063ef1dff2b14610bb6578063f14cb81214610bd657610350565b8063d5f3948814610b13578063d6a3614f14610b47578063e1c9e3c014610b6957610350565b8063b411ee9411610164578063c064d3721161013e578063c064d37214610a79578063c3d98ea814610a99578063c5010d1714610ac6578063d3471e3414610ae657610350565b8063b411ee94146109ed578063b8d38c9614610a13578063bff852fa14610a3357610350565b8063a9e954b9116101a0578063a9e954b914610952578063abc86c6e14610986578063ac82c60814610999578063adb7c3f7146109b957610350565b80638da5cb5b146108f45780638df3fdfd14610912578063a55b471c1461093257610350565b80635be93984116102a057806379ba50971161023e57806384292f071161021857806384292f071461086557806386ac03e01461088557806389a87b16146108a55780638a416ea9146108d257610350565b806379ba50971461080e5780637b10399914610823578063806d7e8f1461083857610350565b80636b58960a1161027a5780636b58960a146107565780636d1178e514610776578063715018a6146107e457806375dadb32146107f957610350565b80635be93984146106c35780636175ff00146106e35780636ab221f81461072457610350565b806346d1d21a1161030d5780635001f3b5116102e75780635001f3b51461060857806352d1902d1461063b5780635479d9401461066f57806354fd4d50146106ae57610350565b806346d1d21a1461056257806349492ef1146105ae5780634efef9c0146105db57610350565b8063029db9581461048a5780630306732e146104bd57806303f3813d146104e1578063384ac938146105015780633e088e121461052f578063439fab9114610542575b34801561035c57600080fd5b506000356001600160e01b03191663e0d20f7360e01b14801561037e57503330145b156104365760006103a5602061039436846144ae565b6001600160c01b031916901b610d0b565b600601546001600160a01b03169050806104115760405162461bcd60e51b815260206004820152602260248201527f5769746e6574507269636546656564733a20756e736574746c656420736f6c7660448201526132b960f11b60648201526084015b60405180910390fd5b60405136600082376000803683855af43d806000843e818015610432578184f35b8184fd5b60405162461bcd60e51b815260206004820152602160248201527f5769746e6574507269636546656564733a206e6f7420696d706c656d656e74656044820152601960fa1b6064820152608401610408565b005b34801561049657600080fd5b506104aa6104a53660046144f2565b610d45565b6040519081526020015b60405180910390f35b3480156104c957600080fd5b506104d2610d56565b6040516104b4939291906145b9565b3480156104ed57600080fd5b506104886104fc3660046146f4565b610fb5565b34801561050d57600080fd5b5061052161051c3660046144f2565b6113ab565b6040516104b4929190614778565b6104aa61053d3660046144f2565b61147d565b34801561054e57600080fd5b5061048861055d3660046148d6565b6114b1565b34801561056e57600080fd5b506105967f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077781565b6040516001600160a01b0390911681526020016104b4565b3480156105ba57600080fd5b506105ce6105c93660046144f2565b6118a1565b6040516104b49190614934565b3480156105e757600080fd5b506105fb6105f63660046144f2565b611951565b6040516104b4919061496b565b34801561061457600080fd5b507f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef11610596565b34801561064757600080fd5b506104aa7f688a557b3c9b52d2ba2301577897f3d892372d2d9be386db46c3ca9048c47f0b81565b34801561067b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000015b60405190151581526020016104b4565b3480156106ba57600080fd5b506105fb611a3a565b3480156106cf57600080fd5b506104aa6106de3660046144f2565b611a6a565b3480156106ef57600080fd5b506107177f000000000000000000000000000000000000000000000000000000000000000481565b6040516104b49190614992565b34801561073057600080fd5b5061074461073f3660046144f2565b611a7f565b60405160ff90911681526020016104b4565b34801561076257600080fd5b5061069e6107713660046149a0565b611a97565b34801561078257600080fd5b5061078b611af2565b6040516104b49190600060a08201905060ff835116825260ff602084015116602083015260408301516001600160401b038082166040850152806060860151166060850152806080860151166080850152505092915050565b3480156107f057600080fd5b50610488611b4c565b34801561080557600080fd5b506105fb611b60565b34801561081a57600080fd5b50610488611b8b565b34801561082f57600080fd5b50610596611b93565b34801561084457600080fd5b506108586108533660046144f2565b611c17565b6040516104b49190614a53565b34801561087157600080fd5b50610488610880366004614b39565b611df8565b34801561089157600080fd5b506104886108a0366004614b84565b6120a6565b3480156108b157600080fd5b506108c56108c03660046144f2565b612311565b6040516104b49190614bc5565b3480156108de57600080fd5b506108e76123f0565b6040516104b49190614c54565b34801561090057600080fd5b506000546001600160a01b0316610596565b34801561091e57600080fd5b506104aa61092d3660046144f2565b6124aa565b34801561093e57600080fd5b5061059661094d366004614c69565b6124bf565b34801561095e57600080fd5b507f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef113f6104aa565b6104aa610994366004614ce6565b612598565b3480156109a557600080fd5b506104886109b4366004614d1c565b612652565b3480156109c557600080fd5b506108e77f68d22dde0000000000000000000000000000000000000000000000000000000081565b3480156109f957600080fd5b506108e7610a083660046148d6565b805160209091012090565b348015610a1f57600080fd5b50610488610a2e366004614d72565b6126c6565b348015610a3f57600080fd5b5060408051808201909152601781527f5769746e65745072696365466565647344656661756c7400000000000000000060208201526105fb565b348015610a8557600080fd5b506104aa610a94366004614d96565b6126e6565b348015610aa557600080fd5b50610ab9610ab43660046144f2565b6127a9565b6040516104b49190614de9565b348015610ad257600080fd5b5061069e610ae1366004614b84565b6129bc565b348015610af257600080fd5b50610b06610b013660046144f2565b612abe565b6040516104b49190614df7565b348015610b1f57600080fd5b506105967f00000000000000000000000003232abe800d1638b30432feef300581de323a4e81565b348015610b5357600080fd5b50600080516020615e6d833981519152546104aa565b348015610b7557600080fd5b50610488612b86565b348015610b8a57600080fd5b50610596612cfe565b348015610b9f57600080fd5b5060045460405161ffff90911681526020016104b4565b348015610bc257600080fd5b506105fb610bd13660046144f2565b612d12565b348015610be257600080fd5b50610bf6610bf13660046144f2565b612dad565b6040516104b49190614e51565b348015610c0f57600080fd5b50610488610c1e3660046149a0565b612dc0565b348015610c2f57600080fd5b50610c43610c3e366004614d96565b612dd4565b604080519384526020840192909252908201526060016104b4565b348015610c6a57600080fd5b50610b06610c793660046144f2565b612e6e565b348015610c8a57600080fd5b50610c9e610c99366004614e5f565b612ed3565b6040516104b49190614e94565b348015610cb757600080fd5b50610488610cc6366004614ee2565b612faa565b348015610cd757600080fd5b50610488610ce63660046146f4565b613051565b348015610cf757600080fd5b50610596610d06366004614c69565b6130b2565b6001600160e01b03191660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b6000610d5082613141565b92915050565b600080516020615e6d83398151915280546040805160208084028201810190925282815260609384938493830182828015610ddd57602002820191906000526020600020906000905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610d9f5790505b5050505050925082516001600160401b03811115610dfd57610dfd61479c565b604051908082528060200260200182016040528015610e3057816020015b6060815260200190600190039081610e1b5790505b50915082516001600160401b03811115610e4c57610e4c61479c565b604051908082528060200260200182016040528015610e75578160200160208202803683370190505b50905060005b8351811015610faf576000610ea8858381518110610e9b57610e9b614efe565b6020026020010151610d0b565b9050806000018054610eb990614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee590614f14565b8015610f325780601f10610f0757610100808354040283529160200191610f32565b820191906000526020600020905b815481529060010190602001808311610f1557829003601f168201915b5050505050848381518110610f4957610f49614efe565b602090810291909101015260068101546001600160a01b031615610f8357600681015460601b6bffffffffffffffffffffffff1916610f89565b80600501545b838381518110610f9b57610f9b614efe565b602090810291909101015250600101610e7b565b50909192565b610fbd613217565b6001600160a01b03831661101f5760405162461bcd60e51b815260206004820152602360248201527f5769746e6574507269636546656564733a206e6f20736f6c766572206164647260448201526265737360e81b6064820152608401610408565b600061106086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b9050600061106d82610d0b565b9050806002015460000361113d5780611087878983614f98565b506110928787613244565b60018201805460ff191660ff92909216919091179055600080516020615e4d8339815191526001908101546110c69161506d565b60028201556006810180546001600160a01b0319166001600160a01b038716179055600080516020615e4d8339815191526001908101805491820181556000908152602090206008820401805463ffffffff60079093166004026101000a928302191660e085901c92909202919091179055611179565b60068101546001600160a01b0386811691161461117957600060058201556006810180546001600160a01b0319166001600160a01b0387161790555b600080866001600160a01b031663e6f8715860e01b8588886040516024016111a3939291906150ee565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111e1919061516a565b600060405180830381855af49150503d806000811461121c576040519150601f19603f3d011682016040523d82523d6000602084013e611221565b606091505b50915091508161127b576004810190508080602001905181019061124591906151de565b6040516020016112559190615212565b60408051601f198184030181529082905262461bcd60e51b82526104089160040161496b565b5050600080306001600160a01b031663e0d20f7360e01b856040516024016112a39190614c54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112e1919061516a565b600060405180830381855afa9150503d806000811461131c576040519150601f19603f3d011682016040523d82523d6000602084013e611321565b606091505b509150915081611355576004810190508080602001905181019061134591906151de565b6040516020016112559190615275565b5050604080516001600160e01b0319841681526001600160a01b03871660208201527f850802cc670161a9f185e45414c2fe7efb5e71b23a8e32a53caffb7dd000aca3910160405180910390a150505050505050565b600060606113b883610d0b565b600601546001600160a01b0316915060006113d28461332a565b905080516001600160401b038111156113ed576113ed61479c565b60405190808252806020026020018201604052801561142057816020015b606081526020019060019003908161140b5790505b50915060005b81518110156114765761145182828151811061144457611444614efe565b6020026020010151612d12565b83828151811061146357611463614efe565b6020908102919091010152600101611426565b5050915091565b6040805180820190915260035460ff8116825261010090046001600160401b03166020820152600090610d50908390613414565b6000546001600160a01b03168061152a57818060200190518101906114d691906152c8565b90506114e18161394f565b60408051808201909152600a808252630bebc2006020909201919091526003805468ffffffffffffffffff1916640bebc2000a1790556004805461ffff19169091179055611582565b336001600160a01b038216146115825760405162461bcd60e51b815260206004820152601f60248201527f5769746e6574507269636546656564733a206e6f7420746865206f776e6572006044820152606401610408565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54158015906115f357507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef113f145b1561164b5760405162461bcd60e51b815260206004820152602260248201527f5769746e6574507269636546656564733a20616c726561647920757067726164604482015261195960f21b6064820152608401610408565b7f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef113f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe557f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03163b6117125760405162461bcd60e51b815260206004820152602360248201527f5769746e6574507269636546656564733a20696e6578697374656e74206f7261604482015262636c6560e81b6064820152608401610408565b63baeca88b60e01b6001600160e01b0319167f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015611782573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a691906152e5565b6001600160e01b031916146118095760405162461bcd60e51b8152602060048201526024808201527f5769746e6574507269636546656564733a20756e636f6d706c69616e74206f7260448201526361636c6560e01b6064820152608401610408565b7f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef113f7f0000000000000000000000008280929b7f6adce1cfa15b63cbec1a7fd8caef116001600160a01b0316826001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f6611888611a3a565b604051611895919061496b565b60405180910390a45050565b6040805180820190915260008152606060208201527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663a77fc1a46118ee84611a6a565b6040518263ffffffff1660e01b815260040161190c91815260200190565b600060405180830381865afa158015611929573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d509190810190615302565b6060600061195e83610d0b565b60058101549091506000036119b55760405162461bcd60e51b815260206004820152601d60248201527f5769746e6574507269636546656564733a206e6f2052414420686173680000006044820152606401610408565b6119bd611b93565b6001600160a01b0316632ebf5d5c82600501546040518263ffffffff1660e01b81526004016119ee91815260200190565b600060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a3391908101906151de565b9392505050565b6060611a657f322e302e31342d34386336646436000000000000000000000000000000000000613968565b905090565b6000611a7582610d0b565b6004015492915050565b6000611a8a82610d0b565b6001015460ff1692915050565b600080611aac6000546001600160a01b031690565b90507f00000000000000000000000000000000000000000000000000000000000000018015611a335750826001600160a01b0316816001600160a01b0316149392505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805180820190915260035460ff8116825261010090046001600160401b03166020820152611a6590613a0c565b611b54613217565b611b5e600061394f565b565b6060611a657f50726963652d0000000000000000000000000000000000000000000000000000613ab3565b611b5e613b57565b60007f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6591906152c8565b60606000611c23611b93565b6001600160a01b031663a83e942c611c3a856124aa565b6040518263ffffffff1660e01b8152600401611c5891815260200190565b600060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c9d91908101906153ac565b905080516001600160401b03811115611cb857611cb861479c565b604051908082528060200260200182016040528015611d2a57816020015b611d176040805160e0810190915260008082526020820190815260200160008152602001606081526020016060815260200160608152602001606081525090565b815260200190600190039081611cd65790505b50915060005b8251811015611df157611d41611b93565b6001600160a01b0316639dd48757838381518110611d6157611d61614efe565b60200260200101516040518263ffffffff1660e01b8152600401611d8791815260200190565b600060405180830381865afa158015611da4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611dcc9190810190615577565b838281518110611dde57611dde614efe565b6020908102919091010152600101611d30565b5050919050565b611e00613217565b7f00000000000000000000000000000000000000000000000000000000000000046013811115611e3257611e3261491e565b611e3a611b93565b6001600160a01b0316634c729104836040518263ffffffff1660e01b8152600401611e6791815260200190565b602060405180830381865afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea89190615682565b6013811115611eb957611eb961491e565b14611f155760405162461bcd60e51b815260206004820152602660248201527f5769746e6574507269636546656564733a2062616420726573756c742064617460448201526561207479706560d01b6064820152608401610408565b6000611f5684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b90506000611f6382610d0b565b905080600201546000036120375780611f7d858783614f98565b50611f888585613244565b60018201805460ff191660ff92909216919091179055600080516020615e4d833981519152600190810154611fbc9161506d565b600282015560058101839055600080516020615e6d83398151915280546001810182556000919091527fb7ef506da7909f25321b247725840c95fced7275a59588a4236c0671ab1d82216008820401805463ffffffff60079093166004026101000a928302191660e085901c9290920291909117905561205c565b8281600501541461205c57600581018390556006810180546001600160a01b03191690555b604080516001600160e01b031984168152602081018590527f37206f9df7db3fe5c4edfea9c5ce9ea406912fc4133f5c67200273da0c09e7b1910160405180910390a15050505050565b6120ae613217565b60006120ef83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b9050600080516020615e6d833981519152600061210b83610d0b565b600281015490915060008190036121645760405162461bcd60e51b815260206004820152601e60248201527f5769746e6574507269636546656564733a20756e6b6e6f776e206665656400006044820152606401610408565b825460009084906121779060019061569d565b8154811061218757612187614efe565b6000918252602090912060088204015460079091166004026101000a900460e01b905080846121b760018561569d565b815481106121c7576121c7614efe565b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555083805480612207576122076156b0565b600082815260209020600860001990920191820401805463ffffffff600460078516026101000a021916905590558161223f82610d0b565b600201556001600160e01b0319851660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602052604081209061228682826143fb565b5060018101805460ff191690556000600282018190556003820181905560048201819055600582018190556006820180546001600160a01b031916905560078201819055600890910155506040517f5296cc0e8dad8eeece6ce7d0928746294283b850d6261e03e7028a84de61f0b690612301908690614c54565b60405180910390a1505050505050565b6123556040805160c081018252600080825260208083018290528284018290526060808401526080830182905283518085019094528184528301529060a082015290565b7f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316630aa4112a61238d84611a6a565b6040518263ffffffff1660e01b81526004016123ab91815260200190565b600060405180830381865afa1580156123c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d509190810190615750565b600080516020615e6d83398151915254600090156124a757612457600080516020615e4d83398151915260010160008154811061242f5761242f614efe565b90600052602060002090600891828204019190066004029054906101000a900460e01b613bd2565b905060015b600080516020615e6d833981519152548110156124a557612499600080516020615e4d833981519152600101828154811061242f5761242f614efe565b9091189060010161245c565b505b90565b60006124b582610d0b565b6005015492915050565b60006124c9613217565b604051632956d1c760e21b815273579b4ad5e67e5b491a33a033a02a70769d7af8379063a55b471c90612506908890889088908890600401615811565b602060405180830381865af4158015612523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254791906152c8565b90507f3c07c0cbdabca8310d65b09f79c58655b46c3035d57c452177e3d49972ff5cec81826001600160a01b03163f85856040516125889493929190615838565b60405180910390a1949350505050565b6040805180820190915260035460ff8116825261010090046001600160401b031660208201526000906125e4906125d436859003850185615860565b9051905160ff9182169116101590565b61263a5760405162461bcd60e51b815260206004820152602160248201527f5769746e6574507269636546656564733a20756e7365637572652075706461746044820152606560f81b6064820152608401610408565b611a338361264d36859003850185615860565b613414565b61265a613217565b6126c18383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa15801561269d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088091906158a5565b505050565b6126ce613217565b6004805461ffff191661ffff92909216919091179055565b6004546000906064906126fd9061ffff16826158be565b604051630f7b104360e31b8152600481018590526020602482015261ffff91909116906001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771690637bd8821890604401602060405180830381865afa158015612771573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279591906158a5565b61279f91906158d9565b610d509190615906565b6127d16040805160808101825260008082526020820181905291810182905290606082015290565b60006127dc83613141565b9050801561285a5760006127ef84612e6e565b905060006128008260800151613c61565b9050604051806080016040528061281683613c7f565b8152602001836040015163ffffffff1681526020018360600151815260200161283e87612dad565b600581111561284f5761284f61491e565b905295945050505050565b600061286584610d0b565b600601546001600160a01b03169050801561297057600080306001600160a01b031663e0d20f7360e01b876040516024016128a09190614c54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516128de919061516a565b600060405180830381855afa9150503d8060008114612919576040519150601f19603f3d011682016040523d82523d6000602084013e61291e565b606091505b509150915081612952576004810190508080602001905181019061294291906151de565b604051602001611255919061591a565b808060200190518101906129669190615963565b9695505050505050565b604051806080016040528060008152602001600081526020016000801b815260200161299b86612dad565b60058111156129ac576129ac61491e565b9052949350505050565b50919050565b6000806129fe84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a0892505050565b90506001600160e01b03198116612aab612a1783610d0b565b8054612a2290614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054612a4e90614f14565b8015612a9b5780601f10612a7057610100808354040283529160200191612a9b565b820191906000526020600020905b815481529060010190602001808311612a7e57829003601f168201915b5050505050805160209091012090565b6001600160e01b03191614949350505050565b6040805160a08101825260008082526020820181905291810182905260608082019290925260808101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663f61921b2612b2384611a6a565b6040518263ffffffff1660e01b8152600401612b4191815260200190565b600060405180830381865afa158015612b5e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5091908101906159cc565b612b8e613217565b600080516020615e6d83398151915280545b8015612cfa57600082612bb460018461569d565b81548110612bc457612bc4614efe565b90600052602060002090600891828204019190066004029054906101000a900460e01b9050612bfe600080516020615e4d83398151915290565b6001600160e01b0319821660009081526002919091016020526040812090612c2682826143fb565b5060018101805460ff191690556000600282018190556003820181905560048201819055600582018190556006820180546001600160a01b0319169055600782018190556008909101558254839080612c8157612c816156b0565b600082815260209020600860001990920191820401805463ffffffff600460078516026101000a021916905590556040517f5296cc0e8dad8eeece6ce7d0928746294283b850d6261e03e7028a84de61f0b690612cdf908390614c54565b60405180910390a15080612cf281615a88565b915050612ba0565b5050565b6000611a656001546001600160a01b031690565b6060612d1d82610d0b565b8054612d2890614f14565b80601f0160208091040260200160405190810160405280929190818152602001828054612d5490614f14565b8015612da15780601f10612d7657610100808354040283529160200191612da1565b820191906000526020600020905b815481529060010190602001808311612d8457829003601f168201915b50505050509050919050565b6000610d50612dbb83611a6a565b613cfb565b612dc8613217565b612dd181613d94565b50565b600080600080612de3856127a9565b8051602082015191925090600283606001516005811115612e0657612e0661491e565b14612e5857600183606001516005811115612e2357612e2361491e565b1480612e445750600483606001516005811115612e4257612e4261491e565b145b612e5057610190612e5b565b610194612e5b565b60c85b919550935061ffff169150509193909250565b6040805160a08101825260008082526020820181905291810182905260608082019290925260808101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663f61921b2612b2384613141565b6060816001600160401b03811115612eed57612eed61479c565b604051908082528060200260200182016040528015612f4657816020015b612f336040805160808101825260008082526020820181905291810182905290606082015290565b815260200190600190039081612f0b5790505b50905060005b82811015612fa357612f7e848483818110612f6957612f69614efe565b9050602002016020810190610ab491906144f2565b828281518110612f9057612f90614efe565b6020908102919091010152600101612f4c565b5092915050565b612fb2613217565b612fbb81613dc6565b6130075760405162461bcd60e51b815260206004820152601d60248201527f5769746e6574507269636546656564733a20696e76616c696420534c410000006044820152606401610408565b8060036130148282615a9f565b9050507f084efe053ac15af09a2db38bb176035f1d94cbc8a775c7761e662f7f11ae6940816040516130469190615af1565b60405180910390a150565b613059613217565b6130ab8585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161308c929190615b7d565b6020604051808303816000875af115801561269d573d6000803e3d6000fd5b5050505050565b6040516001628a76f160e01b0319815260009073579b4ad5e67e5b491a33a033a02a70769d7af8379063ff75890f906130f5908890889088908890600401615811565b602060405180830381865af4158015613112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313691906152c8565b90505b949350505050565b60008061314d83611a6a565b90506000811180156131f85750600260405163234fe6e360e01b8152600481018390527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063234fe6e390602401602060405180830381865afa1580156131c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e59190615c0d565b60058111156131f6576131f661491e565b145b156132035792915050565b61320c83610d0b565b600301549392505050565b6000546001600160a01b03163314611b5e5760405163118cdaa760e01b8152336004820152602401610408565b60405163e78d44d960e01b815260009073579b4ad5e67e5b491a33a033a02a70769d7af8379063e78d44d9906132a2907f50726963652d00000000000000000000000000000000000000000000000000009087908790600401615c28565b602060405180830381865af49250505080156132db575060408051601f3d908101601f191682019092526132d891810190615c42565b60015b613323576132e7615c5f565b806308c379a00361331757506132fb615c7a565b806133065750613319565b80604051602001611255919061591a565b505b3d6000803e3d6000fd5b9050610d50565b6001600160e01b0319811660009081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d201602090815260409182902060089081015483518281526101208101909452606093909290919082016101008036833701905050915060005b600881101561340c57818382815181106133af576133af614efe565b60200260200101906001600160e01b03191690816001600160e01b031916815250508281815181106133e3576133e3614efe565b60209081029190910101516001600160e01b0319161561340c57602082901b9150600101613393565b825250919050565b60008061342084610d0b565b600581015490915015613895576134363a6126e6565b9150813410156134965760405162461bcd60e51b815260206004820152602560248201527f5769746e6574507269636546656564733a20696e73756666696369656e742072604482015264195dd85c9960da1b6064820152608401610408565b600481015460006134a682613cfb565b905060018160058111156134bc576134bc61491e565b0361364f57604051630552089560e11b8152600481018390526000907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031690630aa4112a90602401600060405180830381865afa158015613529573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135519190810190615750565b9050600085826040015160080b6135689190615d03565b90506000811315613643578095507f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663ec5946db87866040518363ffffffff1660e01b81526004016135c591815260200190565b6000604051808303818588803b1580156135de57600080fd5b505af11580156135f2573d6000803e3d6000fd5b505060408051888152602081018b90526001600160e01b03198d1694503293507fc75bbe35e1d3486439c776ccf0fb47aede3d28e1bf548e01357b57132974cd9692500160405180910390a3613648565b600095505b505061388e565b60028160058111156136635761366361491e565b036137155760038301541561370957600383015460405163045bf42f60e11b815260048101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316906308b7e85e906024016000604051808303816000875af11580156136df573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261370791908101906159cc565b505b600383018290556137a4565b60405163045bf42f60e11b8152600481018390527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316906308b7e85e906024016000604051808303816000875af192505050801561379d57506040513d6000823e601f3d908101601f1916820160405261379a91908101906159cc565b60015b156137a457505b6005830154604051631ee15bd160e11b81526001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771691633dc2b7a29187916137f7918a90600401615d23565b60206040518083038185885af1158015613815573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061383a91906158a5565b600484018190556040519092506001600160e01b031987169032907e9bd781be3a9c4660642983aa92bc7a7484c4b0cb0c2afa0f9174c74061d5039061388590869089908b90615d4d565b60405180910390a35b5050613909565b60068101546001600160a01b0316156138c1576138ba6138b48561332a565b84613e53565b9150613909565b60405162461bcd60e51b815260206004820152601e60248201527f5769746e6574507269636546656564733a20756e6b6e6f776e206665656400006044820152606401610408565b34821015612fa357336108fc61391f843461569d565b6040518115909202916000818181858888f19350505050158015613947573d6000803e3d6000fd5b505092915050565b600180546001600160a01b0319169055612dd181613f10565b6060600061397583613f60565b6001600160401b0381111561398c5761398c61479c565b6040519080825280601f01601f1916602001820160405280156139b6576020820181803683370190505b50905060005b8151811015612fa3578381602081106139d7576139d7614efe565b1a60f81b8282815181106139ed576139ed614efe565b60200101906001600160f81b031916908160001a9053506001016139bc565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040518060a00160405280836000015160ff168152602001603360ff16815260200183602001516001600160401b0316815260200183602001516064613a7d9190615d7c565b6001600160401b03168152602001836000015160ff168460200151613aa29190615d9f565b6001600160401b0316905292915050565b60606000613ac083613f99565b6001600160401b03811115613ad757613ad761479c565b6040519080825280601f01601f191660200182016040528015613b01576020820181803683370190505b50905060005b8151811015612fa357838160208110613b2257613b22614efe565b1a60f81b828281518110613b3857613b38614efe565b60200101906001600160f81b031916908160001a905350600101613b07565b3380613b61612cfe565b6001600160a01b031614613bc95760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610408565b612dd18161394f565b600080613bde83610d0b565b6005015414613c2e5781613bf183610d0b565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b81613c3883610d0b565b60080154604080516001600160e01b03199093166020840152820152606001613c11565b919050565b613c6961443a565b6000613c7483613fd2565b9050611a3381613ff7565b6000818060000151613cee5760405162461bcd60e51b815260206004820152603260248201527f5769746e65743a20747269656420746f206465636f64652076616c756520667260448201527137b69032b93937b932b2103932b9bab63a1760711b6064820152608401610408565b611a33836020015161402b565b60008115613d8c5760405163234fe6e360e01b8152600481018390527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063234fe6e390602401602060405180830381865afa158015613d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d509190615c0d565b506002919050565b613d9c613217565b6001600160a01b038116613bc957604051631e4fbdf760e01b815260006004820152602401610408565b600080613dd96040840160208501615dc5565b6001600160401b0316118015613dfe57506000613df96020840184615de2565b60ff16115b8015613e1a5750607f613e146020840184615de2565b60ff1611155b8015610d5057506404a817c800613e376040840160208501615dc5565b613e42906064615d7c565b6001600160401b0316101592915050565b600080835134613e639190615906565b905060005b845181101561394757306001600160a01b031663abc86c6e83878481518110613e9357613e93614efe565b6020026020010151876040518463ffffffff1660e01b8152600401613eb9929190615dff565b60206040518083038185885af1158015613ed7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613efc91906158a5565b613f06908461506d565b9250600101613e68565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b6020811015613c5c57818160208110613f7e57613f7e614efe565b1a60f81b6001600160f81b03191615613c5c57600101613f63565b60005b6020811015613c5c57818160208110613fb757613fb7614efe565b1a60f81b6001600160f81b03191615613c5c57600101613f9c565b613fda614452565b6040805180820190915282815260006020820152611a338161408e565b613fff61443a565b5060a0810151604080518082019091526001600160401b03909116602714158152602081019190915290565b60008160008060ff16826040015160ff161461406b57604080830151905161800560e51b815260ff91821660048201529082166024820152604401610408565b61407d846000015185606001516141ae565b6001600160401b0316949350505050565b614096614452565b81515182906000036140bb576040516309036d4760e21b815260040160405180910390fd5b600060ff816001600160401b038160015b801561413e576140db8961426f565b9550816140e781615e33565b6007600589901c169650601f8816955092505060051985016141365760208901516141128a866141ae565b9350808a60200151614124919061569d565b61412e908461506d565b9250506140cc565b5060006140cc565b600760ff861611156141685760405163bd2ac87960e01b815260ff86166004820152602401610408565b506040805160c08101825298895260ff95861660208a015293851693880193909352921660608601526001600160401b0390811660808601521660a08401525090919050565b600060188260ff1610156141c6575060ff8116610d50565b8160ff166018036141e4576141da8361426f565b60ff169050610d50565b8160ff16601903614203576141f8836142d1565b61ffff169050610d50565b8160ff16601a03614224576142178361433d565b63ffffffff169050610d50565b8160ff16601b03614238576133238361439c565b8160ff16601f0361425157506001600160401b03610d50565b604051636d785b1360e01b815260ff83166004820152602401610408565b60008160200151826000015151808211156142a7576040516363a056dd60e01b81526004810183905260248101829052604401610408565b83516020850180518083016001015195509081906142c482615e33565b8152505050505050919050565b6000816020015160026142e4919061506d565b82515180821115614312576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600281840181015196509091614330828461506d565b9052509395945050505050565b600081602001516004614350919061506d565b8251518082111561437e576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600481840181015196509091614330828461506d565b6000816020015160086143af919061506d565b825151808211156143dd576040516363a056dd60e01b81526004810183905260248101829052604401610408565b8351602085018051600881840181015196509091614330828461506d565b50805461440790614f14565b6000825580601f10614417575050565b601f016020900490600052602060002090810190612dd19190614499565b905290565b60405180604001604052806000151581526020016144355b604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b5b808211156124a5576000815560010161449a565b6001600160c01b031981358181169160088510156139475760089490940360031b84901b1690921692915050565b6001600160e01b031981168114612dd157600080fd5b60006020828403121561450457600080fd5b8135611a33816144dc565b60005b8381101561452a578181015183820152602001614512565b50506000910152565b6000815180845261454b81602086016020860161450f565b601f01601f19169290920160200192915050565b60008282518085526020808601955060208260051b8401016020860160005b848110156145ac57601f1986840301895261459a838351614533565b9884019892509083019060010161457e565b5090979650505050505050565b606080825284519082018190526000906020906080840190828801845b828110156145fc5781516001600160e01b031916845292840192908401906001016145d6565b50505083810382850152614610818761455f565b8481036040860152855180825283870192509083019060005b8181101561464557835183529284019291840191600101614629565b509098975050505050505050565b60008083601f84011261466557600080fd5b5081356001600160401b0381111561467c57600080fd5b60208301915083602082850101111561469457600080fd5b9250929050565b6001600160a01b0381168114612dd157600080fd5b60008083601f8401126146c257600080fd5b5081356001600160401b038111156146d957600080fd5b6020830191508360208260051b850101111561469457600080fd5b60008060008060006060868803121561470c57600080fd5b85356001600160401b038082111561472357600080fd5b61472f89838a01614653565b9097509550602088013591506147448261469b565b9093506040870135908082111561475a57600080fd5b50614767888289016146b0565b969995985093965092949392505050565b6001600160a01b03831681526040602082018190526000906131399083018461455f565b634e487b7160e01b600052604160045260246000fd5b604081018181106001600160401b03821117156147d1576147d161479c565b60405250565b60c081018181106001600160401b03821117156147d1576147d161479c565b60a081018181106001600160401b03821117156147d1576147d161479c565b601f8201601f191681016001600160401b038111828210171561483a5761483a61479c565b6040525050565b60405160e081016001600160401b03811182821017156148635761486361479c565b60405290565b60006001600160401b038211156148825761488261479c565b50601f01601f191660200190565b600061489b83614869565b6040516148a88282614815565b8092508481528585850111156148bd57600080fd5b8484602083013760006020868301015250509392505050565b6000602082840312156148e857600080fd5b81356001600160401b038111156148fe57600080fd5b8201601f8101841361490f57600080fd5b61313984823560208401614890565b634e487b7160e01b600052602160045260246000fd5b602081526000825160ff811061494c5761494c61491e565b8060208401525060208301516040808401526131396060840182614533565b602081526000611a336020830184614533565b6014811061498e5761498e61491e565b9052565b60208101610d50828461497e565b6000602082840312156149b257600080fd5b8135611a338161469b565b6005811061498e5761498e61491e565b600082825180855260208086019550808260051b8401018186016000805b85811015614a4557868403601f19018a5282518460408101845b6002811015614a30578782038352614a1e828551614533565b93890193928901929150600101614a05565b509b87019b95505050918401916001016149eb565b509198975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b8381101561464557603f19898403018552815160e060ff825116855288820151614aa88a8701826149bd565b5087820151614ab98987018261497e565b506060808301518282880152614ad183880182614533565b9250505060808083015186830382880152614aec8382614533565b9250505060a08083015186830382880152614b0783826149cd565b9250505060c08083015192508582038187015250614b258183614533565b968901969450505090860190600101614a7c565b600080600060408486031215614b4e57600080fd5b83356001600160401b03811115614b6457600080fd5b614b7086828701614653565b909790965060209590950135949350505050565b60008060208385031215614b9757600080fd5b82356001600160401b03811115614bad57600080fd5b614bb985828601614653565b90969095509350505050565b6020815260018060a01b03825116602082015262ffffff602083015116604082015268ffffffffffffffffff60408301511660608201526000606083015160e06080840152614c18610100840182614533565b9050608084015160a084015260a0840151614c4c60c0850182805160ff1682526020908101516001600160401b0316910152565b509392505050565b6001600160e01b031991909116815260200190565b60008060008060408587031215614c7f57600080fd5b84356001600160401b0380821115614c9657600080fd5b614ca288838901614653565b90965094506020870135915080821115614cbb57600080fd5b50614cc887828801614653565b95989497509550505050565b6000604082840312156129b657600080fd5b60008060608385031215614cf957600080fd5b8235614d04816144dc565b9150614d138460208501614cd4565b90509250929050565b600080600060408486031215614d3157600080fd5b83356001600160401b03811115614d4757600080fd5b614d5386828701614653565b9094509250506020840135614d678161469b565b809150509250925092565b600060208284031215614d8457600080fd5b813561ffff81168114611a3357600080fd5b600060208284031215614da857600080fd5b5035919050565b6006811061498e5761498e61491e565b80518252602081015160208301526040810151604083015260608101516126c16060840182614daf565b60808101610d508284614dbf565b6020815260018060a01b0382511660208201526001600160401b03602083015116604082015263ffffffff6040830151166060820152606082015160808201526000608083015160a08084015261313960c0840182614533565b60208101610d508284614daf565b60008060208385031215614e7257600080fd5b82356001600160401b03811115614e8857600080fd5b614bb9858286016146b0565b6020808252825182820181905260009190848201906040850190845b81811015614ed657614ec3838551614dbf565b9284019260809290920191600101614eb0565b50909695505050505050565b600060408284031215614ef457600080fd5b611a338383614cd4565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614f2857607f821691505b6020821081036129b657634e487b7160e01b600052602260045260246000fd5b601f8211156126c1576000816000526020600020601f850160051c81016020861015614f715750805b601f850160051c820191505b81811015614f9057828155600101614f7d565b505050505050565b6001600160401b03831115614faf57614faf61479c565b614fc383614fbd8354614f14565b83614f48565b6000601f841160018114614ff75760008515614fdf5750838201355b600019600387901b1c1916600186901b1783556130ab565b600083815260209020601f19861690835b828110156150285786850135825560209485019460019092019101615008565b50868210156150455760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d5057610d50615057565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e198436030181126150c057600080fd5b83016020810192503590506001600160401b038111156150df57600080fd5b80360382131561469457600080fd5b60006040820163ffffffff60e01b861683526020604060208501528185835260608501905060608660051b86010192508660005b8781101561515c57868503605f1901835261513d828a6150a9565b615148878284615080565b965050509183019190830190600101615122565b509298975050505050505050565b6000825161517c81846020870161450f565b9190910192915050565b600082601f83011261519757600080fd5b81516151a281614869565b6040516151af8282614815565b8281528560208487010111156151c457600080fd5b6151d583602083016020880161450f565b95945050505050565b6000602082840312156151f057600080fd5b81516001600160401b0381111561520657600080fd5b61313984828501615186565b7f5769746e657450726963654665656455706772616461626c653a20736f6c7665815274039103b30b634b230ba34b7b7103330b4b632b21d1605d1b60208201526000825161526881603585016020870161450f565b9190910160350192915050565b7f5769746e6574507269636546656564733a20736d6f6b652d746573742066616981526403632b21d160dd1b6020820152600082516152bb81602585016020870161450f565b9190910160250192915050565b6000602082840312156152da57600080fd5b8151611a338161469b565b6000602082840312156152f757600080fd5b8151611a33816144dc565b60006020828403121561531457600080fd5b81516001600160401b038082111561532b57600080fd5b908301906040828603121561533f57600080fd5b60405161534b816147b2565b825160ff811061535a57600080fd5b815260208301518281111561536e57600080fd5b61537a87828601615186565b60208301525095945050505050565b60006001600160401b038211156153a2576153a261479c565b5060051b60200190565b600060208083850312156153bf57600080fd5b82516001600160401b038111156153d557600080fd5b8301601f810185136153e657600080fd5b80516153f181615389565b6040516153fe8282614815565b82815260059290921b830184019184810191508783111561541e57600080fd5b928401925b8284101561543c57835182529284019290840190615423565b979650505050505050565b60ff81168114612dd157600080fd5b8051613c5c81615447565b805160058110613c5c57600080fd5b805160148110613c5c57600080fd5b600082601f83011261549057600080fd5b8151602061549d82615389565b6040516154aa8282614815565b83815260059390931b85018201928281019150868411156154ca57600080fd5b8286015b8481101561556c5780516001600160401b03808211156154ee5760008081fd5b818901915089603f8301126155035760008081fd5b60405161550f816147b2565b80606084018c8111156155225760008081fd5b8885015b8181101561555a5780518581111561553e5760008081fd5b61554c8f8c838a0101615186565b845250918901918901615526565b505050855250509183019183016154ce565b509695505050505050565b60006020828403121561558957600080fd5b81516001600160401b03808211156155a057600080fd5b9083019060e082860312156155b457600080fd5b6155bc614841565b6155c583615456565b81526155d360208401615461565b60208201526155e460408401615470565b60408201526060830151828111156155fb57600080fd5b61560787828601615186565b60608301525060808301518281111561561f57600080fd5b61562b87828601615186565b60808301525060a08301518281111561564357600080fd5b61564f8782860161547f565b60a08301525060c08301518281111561566757600080fd5b61567387828601615186565b60c08301525095945050505050565b60006020828403121561569457600080fd5b611a3382615470565b81810381811115610d5057610d50615057565b634e487b7160e01b600052603160045260246000fd5b805162ffffff81168114613c5c57600080fd5b805168ffffffffffffffffff81168114613c5c57600080fd5b6001600160401b0381168114612dd157600080fd5b60006040828403121561571957600080fd5b604051615725816147b2565b809150825161573381615447565b81526020830151615743816156f2565b6020919091015292915050565b60006020828403121561576257600080fd5b81516001600160401b038082111561577957600080fd5b9083019060e0828603121561578d57600080fd5b604051615799816147d7565b82516157a48161469b565b81526157b2602084016156c6565b60208201526157c3604084016156d9565b60408201526060830151828111156157da57600080fd5b6157e687828601615186565b606083015250608083015160808201526158038660a08501615707565b60a082015295945050505050565b604081526000615825604083018688615080565b828103602084015261543c818587615080565b60018060a01b0385168152836020820152606060408201526000612966606083018486615080565b60006040828403121561587257600080fd5b60405161587e816147b2565b823561588981615447565b81526020830135615899816156f2565b60208201529392505050565b6000602082840312156158b757600080fd5b5051919050565b61ffff818116838216019080821115612fa357612fa3615057565b8082028115828204841417610d5057610d50615057565b634e487b7160e01b600052601260045260246000fd5b600082615915576159156158f0565b500490565b7102bb4ba3732ba283934b1b2a332b2b2399d160751b81526000825161594781601285016020870161450f565b9190910160120192915050565b805160068110613c5c57600080fd5b60006080828403121561597557600080fd5b604051608081018181106001600160401b03821117156159975761599761479c565b80604052508251815260208301516020820152604083015160408201526159c060608401615954565b60608201529392505050565b6000602082840312156159de57600080fd5b81516001600160401b03808211156159f557600080fd5b9083019060a08286031215615a0957600080fd5b604051615a15816147f6565b8251615a208161469b565b81526020830151615a30816156f2565b6020820152604083015163ffffffff81168114615a4c57600080fd5b604082015260608381015190820152608083015182811115615a6d57600080fd5b615a7987828601615186565b60808301525095945050505050565b600081615a9757615a97615057565b506000190190565b8135615aaa81615447565b60ff8116905081548160ff1982161783556020840135615ac9816156f2565b68ffffffffffffffff008160081b168368ffffffffffffffffff198416171784555050505050565b604081018235615b0081615447565b60ff1682526020830135615b13816156f2565b6001600160401b03811660208401525092915050565b6000838385526020808601955060208560051b8301018460005b878110156145ac57848303601f19018952615b5e82886150a9565b615b69858284615080565b9a86019a9450505090830190600101615b43565b6020808252818101839052600090600560408085019086831b86010187855b8881101561464557878303603f190184528135368b9003601e19018112615bc257600080fd5b8a0186810190356001600160401b03811115615bdd57600080fd5b80871b3603821315615bee57600080fd5b615bf9858284615b29565b958801959450505090850190600101615b9c565b600060208284031215615c1f57600080fd5b611a3382615954565b838152604060208201526000613136604083018486615080565b600060208284031215615c5457600080fd5b8151611a3381615447565b600060033d11156124a75760046000803e5060005160e01c90565b600060443d1015615c885790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615cb757505050505090565b8285019150815181811115615ccf5750505050505090565b843d8701016020828501011115615ce95750505050505090565b615cf860208286010187614815565b509095945050505050565b8181036000831280158383131683831282161715612fa357612fa3615057565b82815260608101611a336020830184805160ff1682526020908101516001600160401b0316910152565b8381526020808201849052825160ff1660408301528201516001600160401b0316606082015260808101613139565b6001600160401b0381811683821602808216919082811461394757613947615057565b60006001600160401b0380841680615db957615db96158f0565b92169190910492915050565b600060208284031215615dd757600080fd5b8135611a33816156f2565b600060208284031215615df457600080fd5b8135611a3381615447565b6001600160e01b03198316815260608101611a336020830184805160ff1682526020908101516001600160401b0316910152565b600060018201615e4557615e45615057565b506001019056fee36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ffe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200a26469706673582212200323fb8b972d3201c0ca285eb7b2dff0273fc4ebf93ab2c4f7a0b21304a964f964736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000077703ae126b971c9946d562f41dd47071da007770000000000000000000000000000000000000000000000000000000000000001322e302e31342d34386336646436000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _wrb (address): 0x77703aE126B971c9946d562F41Dd47071dA00777
Arg [1] : _upgradable (bool): True
Arg [2] : _versionTag (bytes32): 0x322e302e31342d34386336646436000000000000000000000000000000000000
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000077703ae126b971c9946d562f41dd47071da00777
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [2] : 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.