Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | Amount | ||
|---|---|---|---|---|---|---|
| 21249195 | 43 secs ago | 0.00000015 ETH | ||||
| 21249173 | 1 min ago | 0.00000015 ETH | ||||
| 21249083 | 4 mins ago | 0.00000015 ETH | ||||
| 21249061 | 5 mins ago | 0.00000015 ETH | ||||
| 21248970 | 8 mins ago | 0.00000015 ETH | ||||
| 21248858 | 11 mins ago | 0.00000015 ETH | ||||
| 21248767 | 14 mins ago | 0.00000015 ETH | ||||
| 21248678 | 17 mins ago | 0.00000015 ETH | ||||
| 21248587 | 20 mins ago | 0.00000015 ETH | ||||
| 21248498 | 23 mins ago | 0.00000015 ETH | ||||
| 21248385 | 27 mins ago | 0.00000015 ETH | ||||
| 21248272 | 31 mins ago | 0.00000015 ETH | ||||
| 21248182 | 34 mins ago | 0.00000015 ETH | ||||
| 21248092 | 37 mins ago | 0.00000015 ETH | ||||
| 21248002 | 40 mins ago | 0.00000015 ETH | ||||
| 21247912 | 43 mins ago | 0.00000015 ETH | ||||
| 21247821 | 46 mins ago | 0.00000015 ETH | ||||
| 21247732 | 49 mins ago | 0.00000015 ETH | ||||
| 21247641 | 52 mins ago | 0.00000015 ETH | ||||
| 21247551 | 55 mins ago | 0.00000015 ETH | ||||
| 21247461 | 58 mins ago | 0.00000015 ETH | ||||
| 21247349 | 1 hr ago | 0.00000015 ETH | ||||
| 21247237 | 1 hr ago | 0.00000015 ETH | ||||
| 21247102 | 1 hr ago | 0.00000015 ETH | ||||
| 21246989 | 1 hr ago | 0.00000015 ETH |
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:
WitPriceFeedsLegacyUpgradable
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 200 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "../WitPriceFeedsLegacy.sol"; import "../core/WitnetUpgradableBase.sol"; import "../data/WitPriceFeedsLegacyDataLib.sol"; import "../interfaces/legacy/IWitOracleLegacy.sol"; import "../patterns/Ownable2Step.sol"; /// @title WitPriceFeeds: Price Feeds upgradable repository reliant on the Wit/Oracle blockchain. /// @author Guillermo Díaz <[email protected]> contract WitPriceFeedsLegacyUpgradable is WitPriceFeedsLegacy, Ownable2Step, WitnetUpgradableBase { using Witnet for bytes; using Witnet for Witnet.DataResult; using Witnet for Witnet.QueryResponse; using Witnet for Witnet.QuerySLA; using Witnet for Witnet.ResultStatus; function class() virtual override public view returns (string memory) { return type(WitPriceFeedsLegacyUpgradable).name; } address immutable public override witOracle; IWitOracleRadonRegistry immutable internal __registry; Witnet.QuerySLA private __defaultQuerySLA; uint16 private __baseFeeOverheadPercentage; constructor( WitOracle _witOracle, bytes32 _versionTag, bool _upgradable ) Ownable(address(msg.sender)) WitnetUpgradableBase( _upgradable, _versionTag, "io.witnet.proxiable.feeds.price" ) { _require( address(_witOracle).code.length > 0, "inexistent oracle" ); _require( _witOracle.specs() == ( type(IWitOracle).interfaceId ^ type(IWitOracleQueriable).interfaceId ), "uncompliant oracle" ); witOracle = address(_witOracle); } function _registry() virtual internal view returns (IWitOracleRadonRegistry) { return IWitOracle(witOracle).registry(); } // solhint-disable-next-line payable-fallback fallback() override external { if ( msg.sig == IWitPriceFeedsLegacySolver.solve.selector && msg.sender == address(this) ) { address _solver = WitPriceFeedsLegacyDataLib.seekRecord(bytes4(bytes8(msg.data) << 32)).solver; _require( _solver != address(0), "unsettled solver" ); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), _solver, ptr, calldatasize(), 0, 0) let size := returndatasize() returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } else { _revert("not implemented"); } } // ================================================================================================================ // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------ /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. function __initializeUpgradableData(bytes memory _initData) virtual override internal { if (__proxiable().codehash == bytes32(0)) { __defaultQuerySLA = Witnet.QuerySLA({ witCommitteeSize: 3, witUnitaryReward: 200_000_000, witResultMaxSize: 16 }); // settle default base fee overhead percentage __baseFeeOverheadPercentage = 10; } else { // otherwise, store beacon read from _initData, if any if (_initData.length > 0) { (uint16 _baseFeeOverheadPercentage, Witnet.QuerySLA memory _defaultQuerySLA) = abi.decode( _initData, (uint16, Witnet.QuerySLA) ); __baseFeeOverheadPercentage = _baseFeeOverheadPercentage; __defaultQuerySLA = _defaultQuerySLA; } else if (!__defaultQuerySLA.isValid()) { // possibly, an upgrade from a previous branch took place: __defaultQuerySLA = Witnet.QuerySLA({ witCommitteeSize: 3, witUnitaryReward: 200_000_000, witResultMaxSize: 16 }); } } } /// Tells whether provided address could eventually upgrade the contract. function isUpgradableFrom(address _from) external view override returns (bool) { address _owner = owner(); return ( // false if the WRB is intrinsically not upgradable, or `_from` is no owner isUpgradable() && _owner == _from ); } // ================================================================================================================ // --- Implements 'IWitFeeds' ------------------------------------------------------------------------------------- function estimateUpdateBaseFee(uint256 _evmGasPrice) virtual override public view returns (uint256) { return _estimateUpdateRequestFee(_evmGasPrice); } function _estimateUpdateRequestFee(uint256 _evmGasPrice) internal view returns (uint) { return ( IWitOracleQueriable(witOracle).estimateBaseFee(_evmGasPrice) * (100 + __baseFeeOverheadPercentage) ) / 100; } /// @notice Returns unique hash determined by the combination of data sources being used /// @notice on non-routed price feeds, and dependencies of routed price feeds. /// @dev Ergo, `footprint()` changes if any data source is modified, or the dependecy tree /// @dev on any routed price feed is altered. function footprint() virtual override public view returns (bytes4 _footprint) { if (__storage().ids.length > 0) { _footprint = _footprintOf(__storage().ids[0]); for (uint _ix = 1; _ix < __storage().ids.length; _ix ++) { _footprint ^= _footprintOf(__storage().ids[_ix]); } } } function hash(string memory caption) virtual override public pure returns (bytes4) { return WitPriceFeedsLegacyDataLib.hash(caption); } function lookupCaption(bytes4 feedId) override public view returns (string memory) { return WitPriceFeedsLegacyDataLib.seekRecord(feedId).caption; } function supportedFeeds() virtual override external view returns (bytes4[] memory _ids, string[] memory _captions, bytes32[] memory _solvers) { return WitPriceFeedsLegacyDataLib.supportedFeeds(); } function supportsCaption(string calldata caption) virtual override external view returns (bool) { bytes4 feedId = hash(caption); return hash(WitPriceFeedsLegacyDataLib.seekRecord(feedId).caption) == feedId; } function totalFeeds() override external view returns (uint256) { return __storage().ids.length; } function lastValidQueryId(bytes4 feedId) override public view returns (uint256) { return WitPriceFeedsLegacyDataLib.lastValidQueryId(IWitOracleQueriable(witOracle), feedId); } function lastValidQueryResponse(bytes4 feedId) override public view returns (Witnet.QueryResponse memory) { return IWitOracleQueriable(witOracle).getQueryResponse(Witnet.QueryId.wrap(uint64( WitPriceFeedsLegacyDataLib.lastValidQueryId(IWitOracleQueriable(witOracle), feedId) ))); } function latestUpdateQueryId(bytes4 feedId) override public view returns (uint256) { return WitPriceFeedsLegacyDataLib.seekRecord(feedId).latestUpdateQueryId; } function latestUpdateQueryRequest(bytes4 feedId) override external view returns (Witnet.QueryRequest memory) { return IWitOracleQueriable(witOracle).getQueryRequest(Witnet.QueryId.wrap(uint64( latestUpdateQueryId(feedId) ))); } function lookupWitnetBytecode(bytes4 feedId) override public view returns (bytes memory) { WitPriceFeedsLegacyDataLib.Record storage __record = WitPriceFeedsLegacyDataLib.seekRecord(feedId); _require( __record.radHash != 0, "no RAD hash" ); return _registry().lookupRadonRequestBytecode(Witnet.RadonHash.wrap(__record.radHash)); } function lookupWitnetRadHash(bytes4 feedId) override public view returns (bytes32) { return WitPriceFeedsLegacyDataLib.seekRecord(feedId).radHash; } function lookupWitnetRetrievals(bytes4 feedId) override external view returns (Witnet.RadonRetrieval[] memory _retrievals) { return _registry().lookupRadonRequestRetrievals( Witnet.RadonHash.wrap(lookupWitnetRadHash(feedId)) ); } function requestUpdate(bytes4 feedId) external payable virtual override returns (uint256) { return __requestUpdate(feedId, __defaultQuerySLA); } /// =============================================================================================================== /// --- IWitFeedsLegacy ------------------------------------------------------------------------------------------- function defaultRadonSLA() override external view returns (IWitPriceFeedsLegacy.RadonSLAv1 memory) { uint8 _numWitnesses = uint8(__defaultQuerySLA.witCommitteeSize); uint64 _unitaryReward = __defaultQuerySLA.witUnitaryReward; return IWitPriceFeedsLegacy.RadonSLAv1({ numWitnesses: _numWitnesses, minConsensusPercentage: 51, witnessReward: _unitaryReward, witnessCollateral: _unitaryReward * _numWitnesses, minerCommitRevealFee: _unitaryReward / _numWitnesses }); } function latestUpdateResponse(bytes4 feedId) override external view returns (Witnet.QueryResponse memory) { return IWitOracleQueriable(witOracle).getQueryResponse(Witnet.QueryId.wrap(uint64( latestUpdateQueryId(feedId) ))); } function latestUpdateResponseStatus(bytes4 feedId) override public view returns (IWitOracleLegacy.QueryResponseStatus) { return IWitOracleLegacy(witOracle).getQueryResponseStatus(latestUpdateQueryId(feedId)); } function latestUpdateResultError(bytes4 feedId) override external view returns (IWitOracleLegacy.ResultError memory) { return IWitOracleLegacy(witOracle).getQueryResultError(latestUpdateQueryId(feedId)); } function requestUpdate(bytes4 feedId, IWitPriceFeedsLegacy.RadonSLAv2 calldata legacySLA) external payable virtual override returns (uint256) { return __requestUpdate(feedId, _intoQuerySLA(legacySLA)); } function witnet() virtual override external view returns (address) { return address(witOracle); } // ================================================================================================================ // --- Implements 'IWitPriceFeedsLegacyAdmin' ----------------------------------------------------------------------------- function owner() virtual override (IWitPriceFeedsLegacyAdmin, Ownable) public view returns (address) { return Ownable.owner(); } function acceptOwnership() virtual override (IWitPriceFeedsLegacyAdmin, Ownable2Step) public { Ownable2Step.acceptOwnership(); } function baseFeeOverheadPercentage() virtual override external view returns (uint16) { return __baseFeeOverheadPercentage; } function pendingOwner() virtual override (IWitPriceFeedsLegacyAdmin, Ownable2Step) public view returns (address) { return Ownable2Step.pendingOwner(); } function transferOwnership(address _newOwner) virtual override (IWitPriceFeedsLegacyAdmin, Ownable2Step) public onlyOwner { Ownable.transferOwnership(_newOwner); } function deleteFeed(string calldata caption) virtual override external onlyOwner { try WitPriceFeedsLegacyDataLib.deleteFeed(caption) { } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function deleteFeeds() virtual override external onlyOwner { try WitPriceFeedsLegacyDataLib.deleteFeeds() { } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function settleBaseFeeOverheadPercentage(uint16 _baseFeeOverheadPercentage) virtual override external onlyOwner { __baseFeeOverheadPercentage = _baseFeeOverheadPercentage; } function settleDefaultRadonSLA(RadonSLAv2 calldata radonSLAv2) override public onlyOwner { __defaultQuerySLA.witCommitteeSize = radonSLAv2.numWitnesses; __defaultQuerySLA.witUnitaryReward = radonSLAv2.unitaryReward; _require( __defaultQuerySLA.isValid(), "invalid update SLA" ); } function settleFeedRequest(string calldata caption, bytes32 radHash) override public onlyOwner { _require( _registry().lookupRadonRequestResultDataType(Witnet.RadonHash.wrap(radHash)) == dataType, "bad result data type" ); try WitPriceFeedsLegacyDataLib.settleFeedRequest(caption, radHash) { } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function settleFeedRequest(string calldata caption, IWitOracleRequest request) override external onlyOwner { settleFeedRequest(caption, Witnet.RadonHash.unwrap(request.radHash())); } function settleFeedRequest( string calldata caption, IWitOracleRequestTemplate template, string[][] calldata args ) override external onlyOwner { settleFeedRequest(caption, Witnet.RadonHash.unwrap(template.verifyRadonRequest(args))); } function settleFeedSolver( string calldata caption, address solver, string[] calldata deps ) override external onlyOwner { _require( bytes6(bytes(caption)) == bytes6(__prefix), "bad caption prefix" ); _require( solver != address(0), "no solver address" ); try WitPriceFeedsLegacyDataLib.settleFeedSolver(caption, solver, deps) { } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } // ================================================================================================================ // --- Implements 'IWitPriceFeeds' ----------------------------------------------------------------------------- function lookupDecimals(bytes4 feedId) override external view returns (uint8) { return WitPriceFeedsLegacyDataLib.seekRecord(feedId).decimals; } function lookupPriceSolver(bytes4 feedId) override external view returns (address _solverAddress, string[] memory _solverDeps) { return WitPriceFeedsLegacyDataLib.seekPriceSolver(feedId); } function latestPrice(bytes4 feedId) virtual override public view returns (IWitPriceFeedsLegacySolver.Price memory) { try WitPriceFeedsLegacyDataLib.latestPrice( IWitOracleQueriable(witOracle), feedId ) returns (IWitPriceFeedsLegacySolver.Price memory _latestPrice) { return _latestPrice; } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function latestPrices(bytes4[] calldata feedIds) virtual override external view returns (IWitPriceFeedsLegacySolver.Price[] memory _prices) { _prices = new IWitPriceFeedsLegacySolver.Price[](feedIds.length); for (uint _ix = 0; _ix < feedIds.length; _ix ++) { _prices[_ix] = latestPrice(feedIds[_ix]); } } // ================================================================================================================ // --- Implements 'IWitPriceFeedsLegacySolverFactory' --------------------------------------------------------------------- function deployPriceSolver(bytes calldata initcode, bytes calldata constructorParams) virtual override external onlyOwner returns (address) { try WitPriceFeedsLegacyDataLib.deployPriceSolver( initcode, constructorParams ) returns ( address _solver ) { emit NewPriceFeedsSolver( _solver, _solver.codehash, constructorParams ); return _solver; } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function determinePriceSolverAddress(bytes calldata initcode, bytes calldata constructorParams) virtual override public view returns (address _address) { return WitPriceFeedsLegacyDataLib.determinePriceSolverAddress(initcode, constructorParams); } // ================================================================================================================ // --- Implements 'IERC2362' -------------------------------------------------------------------------------------- function valueFor(bytes32 feedId) virtual override external view returns (int256 _value, uint256 _timestamp, uint256 _status) { IWitPriceFeedsLegacySolver.Price memory _latestPrice = latestPrice(bytes4(feedId)); return ( int(uint(_latestPrice.value)), Witnet.Timestamp.unwrap(_latestPrice.timestamp), (_latestPrice.latestStatus == IWitPriceFeedsLegacySolver.LatestUpdateStatus.Ready ? 200 : (_latestPrice.latestStatus == IWitPriceFeedsLegacySolver.LatestUpdateStatus.Awaiting ? 404 : 400 ) ) ); } // ================================================================================================================ // --- Internal methods ------------------------------------------------------------------------------------------- function _footprintOf(bytes4 _id4) virtual internal view returns (bytes4) { if (WitPriceFeedsLegacyDataLib.seekRecord(_id4).radHash != bytes32(0)) { return bytes4(keccak256(abi.encode(_id4, WitPriceFeedsLegacyDataLib.seekRecord(_id4).radHash))); } else { return bytes4(keccak256(abi.encode(_id4, WitPriceFeedsLegacyDataLib.seekRecord(_id4).solverDepsFlag))); } } function _intoQuerySLA(IWitPriceFeedsLegacy.RadonSLAv2 memory _updateSLA) internal view returns (Witnet.QuerySLA memory) { if ( _updateSLA.numWitnesses >= __defaultQuerySLA.witCommitteeSize && _updateSLA.unitaryReward >= __defaultQuerySLA.witUnitaryReward ) { return Witnet.QuerySLA({ witCommitteeSize: _updateSLA.numWitnesses, witUnitaryReward: _updateSLA.unitaryReward, witResultMaxSize: __defaultQuerySLA.witResultMaxSize }); } else { _revert("unsecure update request"); } } function _validateCaption(string calldata caption) internal view returns (uint8) { _require( bytes6(bytes(caption)) == bytes6(__prefix), "bad caption prefix" ); try WitPriceFeedsLegacyDataLib.validateCaption(caption) returns (uint8 _decimals) { return _decimals; } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } function _revertWitPriceFeedsLegacyDataLibUnhandledException() internal view { _revert(_revertWitPriceFeedsLegacyDataLibUnhandledExceptionReason()); } function _revertWitPriceFeedsLegacyDataLibUnhandledExceptionReason() internal pure returns (string memory) { return string(abi.encodePacked( type(WitPriceFeedsLegacyDataLib).name, ": unhandled assertion" )); } function __requestUpdate(bytes4[] memory _deps, IWitPriceFeedsLegacy.RadonSLAv2 memory sla) virtual internal returns (uint256 _evmUsedFunds) { uint _evmUnitaryUpdateRequestFee = msg.value / _deps.length; for (uint _ix = 0; _ix < _deps.length; _ix ++) { _evmUsedFunds += this.requestUpdate{ value: _evmUnitaryUpdateRequestFee }( _deps[_ix], sla ); } } function __requestUpdate( bytes4 feedId, Witnet.QuerySLA memory querySLA ) virtual internal returns (uint256) { if (WitPriceFeedsLegacyDataLib.seekRecord(feedId).radHash != 0) { uint256 _evmUpdateRequestFee = msg.value; try WitPriceFeedsLegacyDataLib.requestUpdate( IWitOracleQueriable(witOracle), feedId, querySLA, _evmUpdateRequestFee ) returns ( uint256 _latestQueryId, uint256 _evmUsedFunds ) { if (_evmUsedFunds < msg.value) { // transfer back unused funds: payable(msg.sender).transfer(msg.value - _evmUsedFunds); } // solhint-disable avoid-tx-origin: emit PullingUpdate(tx.origin, _msgSender(), feedId, _latestQueryId); return _evmUsedFunds; } catch Error(string memory _reason) { _revert(_reason); } catch (bytes memory) { _revertWitPriceFeedsLegacyDataLibUnhandledException(); } } else if (WitPriceFeedsLegacyDataLib.seekRecord(feedId).solver != address(0)) { return __requestUpdate( WitPriceFeedsLegacyDataLib.depsOf(feedId), IWitPriceFeedsLegacy.RadonSLAv2({ numWitnesses: uint8(querySLA.witCommitteeSize), unitaryReward: querySLA.witUnitaryReward }) ); } else { _revert("unknown feed"); } } function __storage() internal pure returns (WitPriceFeedsLegacyDataLib.Storage storage) { return WitPriceFeedsLegacyDataLib.data(); } }
// SPDX-License-Identifier: MIT
/* solhint-disable var-name-mixedcase */
pragma solidity >=0.6.0 <0.9.0;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "./Initializable.sol";
import "./Proxiable.sol";
abstract contract Upgradeable is Initializable, Proxiable {
address internal immutable _BASE;
bytes32 internal immutable _CODEHASH;
bool internal immutable _UPGRADABLE;
modifier onlyDelegateCalls virtual {
require(
address(this) != _BASE,
"Upgradeable: not a delegate call"
);
_;
}
/// Emitted every time the contract gets upgraded.
/// @param from The address who ordered the upgrading. Namely, the WRB operator in "trustable" implementations.
/// @param baseAddr The address of the new implementation contract.
/// @param baseCodehash The EVM-codehash of the new implementation contract.
/// @param versionTag Ascii-encoded version literal with which the implementation deployer decided to tag it.
event Upgraded(
address indexed from,
address indexed baseAddr,
bytes32 indexed baseCodehash,
string versionTag
);
constructor (bool _isUpgradable) {
address _base = address(this);
_BASE = _base;
_UPGRADABLE = _isUpgradable;
}
/// @dev Retrieves base contract. Differs from address(this) when called via delegate-proxy pattern.
function base() virtual public view returns (address) {
return _BASE;
}
/// @dev Retrieves the immutable codehash of this contract, even if invoked as delegatecall.
function codehash() public view returns (bytes32 _codehash) {
address _base = _BASE;
assembly {
_codehash := extcodehash(_base)
}
}
/// @dev Determines whether the logic of this contract is potentially upgradable.
function isUpgradable() public view returns (bool) {
return _UPGRADABLE;
}
/// @dev Tells whether provided address could eventually upgrade the contract.
function isUpgradableFrom(address from) virtual external view returns (bool);
/// @notice Re-initialize contract's storage context upon a new upgrade from a proxy.
/// @dev Must fail when trying to upgrade to same logic contract more than once.
function initialize(bytes memory) virtual external;
function __initializeUpgradableData(bytes memory _initData) virtual internal;
/// @dev Retrieves human-redable named version of current implementation.
function version() virtual public view returns (string memory);
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
abstract contract Proxiable {
/// @dev Complying with EIP-1822: Universal Upgradeable Proxy Standard (UUPS)
/// @dev See https://eips.ethereum.org/EIPS/eip-1822.
function proxiableUUID() virtual external view returns (bytes32);
struct ProxiableSlot {
address implementation;
address proxy;
bytes32 codehash;
}
function __implementation() internal view returns (address) {
return __proxiable().implementation;
}
function __proxy() internal view returns (address) {
return __proxiable().proxy;
}
function __proxiable() internal pure returns (ProxiableSlot storage proxiable) {
assembly {
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
proxiable.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert("Ownable2Step: caller is not the new owner");
}
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/Ownable.sol";
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./WitnetBuffer.sol";
/// @title A minimalistic implementation of “RFC 7049 Concise Binary Object Representation”
/// @notice This library leverages a buffer-like structure for step-by-step decoding of bytes so as to minimize
/// the gas cost of decoding them into a useful native type.
/// @dev Most of the logic has been borrowed from Patrick Gansterer’s cbor.js library: https://github.com/paroga/cbor-js
/// @author The Witnet Foundation.
library WitnetCBOR {
using WitnetBuffer for WitnetBuffer.Buffer;
using WitnetCBOR for WitnetCBOR.CBOR;
/// Data struct following the RFC-7049 standard: Concise Binary Object Representation.
struct CBOR {
WitnetBuffer.Buffer buffer;
uint8 initialByte;
uint8 majorType;
uint8 additionalInformation;
uint64 len;
uint64 tag;
}
uint8 internal constant MAJOR_TYPE_INT = 0;
uint8 internal constant MAJOR_TYPE_NEGATIVE_INT = 1;
uint8 internal constant MAJOR_TYPE_BYTES = 2;
uint8 internal constant MAJOR_TYPE_STRING = 3;
uint8 internal constant MAJOR_TYPE_ARRAY = 4;
uint8 internal constant MAJOR_TYPE_MAP = 5;
uint8 internal constant MAJOR_TYPE_TAG = 6;
uint8 internal constant MAJOR_TYPE_CONTENT_FREE = 7;
uint32 internal constant UINT32_MAX = type(uint32).max;
uint64 internal constant UINT64_MAX = type(uint64).max;
error EmptyArray();
error InvalidLengthEncoding(uint length);
error UnexpectedMajorType(uint read, uint expected);
error UnsupportedPrimitive(uint primitive);
error UnsupportedMajorType(uint unexpected);
modifier isMajorType(
WitnetCBOR.CBOR memory cbor,
uint8 expected
) {
if (cbor.majorType != expected) {
revert UnexpectedMajorType(cbor.majorType, expected);
}
_;
}
modifier notEmpty(WitnetBuffer.Buffer memory buffer) {
if (buffer.data.length == 0) {
revert WitnetBuffer.EmptyBuffer();
}
_;
}
function eof(CBOR memory cbor)
internal pure
returns (bool)
{
return cbor.buffer.cursor >= cbor.buffer.data.length;
}
/// @notice Decode a CBOR structure from raw bytes.
/// @dev This is the main factory for CBOR instances, which can be later decoded into native EVM types.
/// @param bytecode Raw bytes representing a CBOR-encoded value.
/// @return A `CBOR` instance containing a partially decoded value.
function fromBytes(bytes memory bytecode)
internal pure
returns (CBOR memory)
{
WitnetBuffer.Buffer memory buffer = WitnetBuffer.Buffer(bytecode, 0);
return fromBuffer(buffer);
}
/// @notice Decode a CBOR structure from raw bytes.
/// @dev This is an alternate factory for CBOR instances, which can be later decoded into native EVM types.
/// @param buffer A Buffer structure representing a CBOR-encoded value.
/// @return A `CBOR` instance containing a partially decoded value.
function fromBuffer(WitnetBuffer.Buffer memory buffer)
internal pure
notEmpty(buffer)
returns (CBOR memory)
{
uint8 initialByte;
uint8 majorType = 255;
uint8 additionalInformation;
uint64 tag = UINT64_MAX;
uint256 len;
bool isTagged = true;
while (isTagged) {
// Extract basic CBOR properties from input bytes
initialByte = buffer.readUint8();
len ++;
majorType = initialByte >> 5;
additionalInformation = initialByte & 0x1f;
// Early CBOR tag parsing.
if (majorType == MAJOR_TYPE_TAG) {
uint _cursor = buffer.cursor;
tag = readLength(buffer, additionalInformation);
len += buffer.cursor - _cursor;
} else {
isTagged = false;
}
}
if (majorType > MAJOR_TYPE_CONTENT_FREE) {
revert UnsupportedMajorType(majorType);
}
return CBOR(
buffer,
initialByte,
majorType,
additionalInformation,
uint64(len),
tag
);
}
function fork(WitnetCBOR.CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
return CBOR({
buffer: self.buffer.fork(),
initialByte: self.initialByte,
majorType: self.majorType,
additionalInformation: self.additionalInformation,
len: self.len,
tag: self.tag
});
}
function settle(CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
if (!self.eof()) {
return fromBuffer(self.buffer);
} else {
return self;
}
}
function skip(CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
if (
self.majorType == MAJOR_TYPE_INT
|| self.majorType == MAJOR_TYPE_NEGATIVE_INT
|| (
self.majorType == MAJOR_TYPE_CONTENT_FREE
&& self.additionalInformation >= 25
&& self.additionalInformation <= 27
)
) {
self.buffer.cursor += self.peekLength();
} else if (
self.majorType == MAJOR_TYPE_STRING
|| self.majorType == MAJOR_TYPE_BYTES
) {
uint64 len = readLength(self.buffer, self.additionalInformation);
self.buffer.cursor += len;
} else if (
self.majorType == MAJOR_TYPE_ARRAY
|| self.majorType == MAJOR_TYPE_MAP
) {
self.len = readLength(self.buffer, self.additionalInformation);
} else if (
self.majorType != MAJOR_TYPE_CONTENT_FREE
|| (
self.additionalInformation != 20
&& self.additionalInformation != 21
)
) {
revert("WitnetCBOR.skip: unsupported major type");
}
return self;
}
function peekLength(CBOR memory self)
internal pure
returns (uint64)
{
if (self.additionalInformation < 24) {
return 0;
} else if (self.additionalInformation < 28) {
return uint64(1 << (self.additionalInformation - 24));
} else {
revert InvalidLengthEncoding(self.additionalInformation);
}
}
function readArray(CBOR memory self)
internal pure
isMajorType(self, MAJOR_TYPE_ARRAY)
returns (CBOR[] memory items)
{
// read array's length and move self cursor forward to the first array element:
uint64 len = readLength(self.buffer, self.additionalInformation);
items = new CBOR[](len + 1);
for (uint ix = 0; ix < len; ix ++) {
// settle next element in the array:
self = self.settle();
// fork it and added to the list of items to be returned:
items[ix] = self.fork();
if (self.majorType == MAJOR_TYPE_ARRAY) {
CBOR[] memory _subitems = self.readArray();
// move forward to the first element after inner array:
self = _subitems[_subitems.length - 1];
} else if (self.majorType == MAJOR_TYPE_MAP) {
CBOR[] memory _subitems = self.readMap();
// move forward to the first element after inner map:
self = _subitems[_subitems.length - 1];
} else {
// move forward to the next element:
self.skip();
}
}
// return self cursor as extra item at the end of the list,
// as to optimize recursion when jumping over nested arrays:
items[len] = self;
}
function readMap(CBOR memory self)
internal pure
isMajorType(self, MAJOR_TYPE_MAP)
returns (CBOR[] memory items)
{
// read number of items within the map and move self cursor forward to the first inner element:
uint64 len = readLength(self.buffer, self.additionalInformation) * 2;
items = new CBOR[](len + 1);
for (uint ix = 0; ix < len; ix ++) {
// settle next element in the array:
self = self.settle();
// fork it and added to the list of items to be returned:
items[ix] = self.fork();
if (ix % 2 == 0 && self.majorType != MAJOR_TYPE_STRING) {
revert UnexpectedMajorType(self.majorType, MAJOR_TYPE_STRING);
} else if (self.majorType == MAJOR_TYPE_ARRAY || self.majorType == MAJOR_TYPE_MAP) {
CBOR[] memory _subitems = (self.majorType == MAJOR_TYPE_ARRAY
? self.readArray()
: self.readMap()
);
// move forward to the first element after inner array or map:
self = _subitems[_subitems.length - 1];
} else {
// move forward to the next element:
self.skip();
}
}
// return self cursor as extra item at the end of the list,
// as to optimize recursion when jumping over nested arrays:
items[len] = self;
}
/// Reads the length of the settle CBOR item from a buffer, consuming a different number of bytes depending on the
/// value of the `additionalInformation` argument.
function readLength(
WitnetBuffer.Buffer memory buffer,
uint8 additionalInformation
)
internal pure
returns (uint64)
{
if (additionalInformation < 24) {
return additionalInformation;
}
if (additionalInformation == 24) {
return buffer.readUint8();
}
if (additionalInformation == 25) {
return buffer.readUint16();
}
if (additionalInformation == 26) {
return buffer.readUint32();
}
if (additionalInformation == 27) {
return buffer.readUint64();
}
if (additionalInformation == 31) {
return UINT64_MAX;
}
revert InvalidLengthEncoding(additionalInformation);
}
/// @notice Read a `CBOR` structure into a native `bool` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as a `bool` value.
function readBool(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (bool)
{
if (cbor.additionalInformation == 20) {
return false;
} else if (cbor.additionalInformation == 21) {
return true;
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a native `bytes` value.
/// @param cbor An instance of `CBOR`.
/// @return output The value represented by the input, as a `bytes` value.
function readBytes(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_BYTES)
returns (bytes memory output)
{
cbor.len = readLength(
cbor.buffer,
cbor.additionalInformation
);
if (cbor.len == UINT32_MAX) {
// These checks look repetitive but the equivalent loop would be more expensive.
uint32 length = uint32(_readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
));
if (length < UINT32_MAX) {
output = abi.encodePacked(cbor.buffer.read(length));
length = uint32(_readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
));
if (length < UINT32_MAX) {
output = abi.encodePacked(
output,
cbor.buffer.read(length)
);
}
}
} else {
return cbor.buffer.read(uint32(cbor.len));
}
}
/// @notice Decode a `CBOR` structure into a `fixed16` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`
/// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int128` value.
function readFloat16(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int32)
{
if (cbor.additionalInformation == 25) {
return cbor.buffer.readFloat16();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a `fixed32` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `fixed64`
/// use cases. In other words, the output of this method is 10^9 times the actual value, encoded into an `int`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int` value.
function readFloat32(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int)
{
if (cbor.additionalInformation == 26) {
return cbor.buffer.readFloat32();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a `fixed64` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `fixed64`
/// use cases. In other words, the output of this method is 10^15 times the actual value, encoded into an `int`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int` value.
function readFloat64(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int)
{
if (cbor.additionalInformation == 27) {
return cbor.buffer.readFloat64();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a native `int128[]` value whose inner values follow the same convention
/// @notice as explained in `decodeFixed16`.
/// @param cbor An instance of `CBOR`.
function readFloat16Array(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (int32[] memory values)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
values = new int32[](length);
for (uint64 i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
values[i] = readFloat16(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `int128` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int128` value.
function readInt(CBOR memory cbor)
internal pure
returns (int64)
{
if (cbor.majorType == 1) {
uint64 _value = readLength(
cbor.buffer,
cbor.additionalInformation
);
return int64(-1) - int64(uint64(_value));
} else if (cbor.majorType == 0) {
// Any `uint64` can be safely casted to `int128`, so this method supports majorType 1 as well so as to have offer
// a uniform API for positive and negative numbers
return int64(readUint(cbor));
}
else {
revert UnexpectedMajorType(cbor.majorType, 1);
}
}
/// @notice Decode a `CBOR` structure into a native `int[]` value.
/// @param cbor instance of `CBOR`.
/// @return array The value represented by the input, as an `int[]` value.
function readIntArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (int64[] memory array)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
array = new int64[](length);
for (uint i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
array[i] = readInt(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `string` value.
/// @param cbor An instance of `CBOR`.
/// @return text The value represented by the input, as a `string` value.
function readString(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_STRING)
returns (string memory text)
{
cbor.len = readLength(cbor.buffer, cbor.additionalInformation);
if (cbor.len == UINT64_MAX) {
bool _done;
while (!_done) {
uint64 length = _readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
);
if (length < UINT64_MAX) {
text = string(abi.encodePacked(
text,
cbor.buffer.readText(length / 4)
));
} else {
_done = true;
}
}
} else {
return string(cbor.buffer.readText(cbor.len));
}
}
/// @notice Decode a `CBOR` structure into a native `string[]` value.
/// @param cbor An instance of `CBOR`.
/// @return strings The value represented by the input, as an `string[]` value.
function readStringArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (string[] memory strings)
{
uint length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
strings = new string[](length);
for (uint i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
strings[i] = readString(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `uint64` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `uint64` value.
function readUint(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_INT)
returns (uint64)
{
return readLength(
cbor.buffer,
cbor.additionalInformation
);
}
/// @notice Decode a `CBOR` structure into a native `uint64[]` value.
/// @param cbor An instance of `CBOR`.
/// @return values The value represented by the input, as an `uint64[]` value.
function readUintArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (uint64[] memory values)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
values = new uint64[](length);
for (uint ix = 0; ix < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
values[ix] = readUint(item);
unchecked {
ix ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// Read the length of a CBOR indifinite-length item (arrays, maps, byte strings and text) from a buffer, consuming
/// as many bytes as specified by the first byte.
function _readIndefiniteStringLength(
WitnetBuffer.Buffer memory buffer,
uint8 majorType
)
private pure
returns (uint64 len)
{
uint8 initialByte = buffer.readUint8();
if (initialByte == 0xff) {
return UINT64_MAX;
}
len = readLength(
buffer,
initialByte & 0x1f
);
if (len >= UINT64_MAX) {
revert InvalidLengthEncoding(len);
} else if (majorType != (initialByte >> 5)) {
revert UnexpectedMajorType((initialByte >> 5), majorType);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/// @title A convenient wrapper around the `bytes memory` type that exposes a buffer-like interface
/// @notice The buffer has an inner cursor that tracks the final offset of every read, i.e. any subsequent read will
/// start with the byte that goes right after the last one in the previous read.
/// @dev `uint32` is used here for `cursor` because `uint16` would only enable seeking up to 8KB, which could in some
/// theoretical use cases be exceeded. Conversely, `uint32` supports up to 512MB, which cannot credibly be exceeded.
/// @author The Witnet Foundation.
library WitnetBuffer {
error EmptyBuffer();
error IndexOutOfBounds(uint index, uint range);
error MissingArgs(uint expected, uint given);
/// Iterable bytes buffer.
struct Buffer {
bytes data;
uint cursor;
}
// Ensures we access an existing index in an array
modifier withinRange(uint index, uint _range) {
if (index > _range) {
revert IndexOutOfBounds(index, _range);
}
_;
}
/// @notice Concatenate undefinite number of bytes chunks.
/// @dev Faster than looping on `abi.encodePacked(output, _buffs[ix])`.
function concat(bytes[] memory _buffs)
internal pure
returns (bytes memory output)
{
unchecked {
uint destinationPointer;
uint destinationLength;
assembly {
// get safe scratch location
output := mload(0x40)
// set starting destination pointer
destinationPointer := add(output, 32)
}
for (uint ix = 1; ix <= _buffs.length; ix ++) {
uint source;
uint sourceLength;
uint sourcePointer;
assembly {
// load source length pointer
source := mload(add(_buffs, mul(ix, 32)))
// load source length
sourceLength := mload(source)
// sets source memory pointer
sourcePointer := add(source, 32)
}
memcpy(
destinationPointer,
sourcePointer,
sourceLength
);
assembly {
// increase total destination length
destinationLength := add(destinationLength, sourceLength)
// sets destination memory pointer
destinationPointer := add(destinationPointer, sourceLength)
}
}
assembly {
// protect output bytes
mstore(output, destinationLength)
// set final output length
mstore(0x40, add(mload(0x40), add(destinationLength, 32)))
}
}
}
function fork(WitnetBuffer.Buffer memory buffer)
internal pure
returns (WitnetBuffer.Buffer memory)
{
return Buffer(
buffer.data,
buffer.cursor
);
}
function mutate(
WitnetBuffer.Buffer memory buffer,
uint length,
bytes memory pokes
)
internal pure
withinRange(length, buffer.data.length - buffer.cursor + 1)
{
bytes[] memory parts = new bytes[](3);
parts[0] = peek(
buffer,
0,
buffer.cursor
);
parts[1] = pokes;
parts[2] = peek(
buffer,
buffer.cursor + length,
buffer.data.length - buffer.cursor - length
);
buffer.data = concat(parts);
}
/// @notice Read and consume the next byte from the buffer.
/// @param buffer An instance of `Buffer`.
/// @return The next byte in the buffer counting from the cursor position.
function next(Buffer memory buffer)
internal pure
withinRange(buffer.cursor, buffer.data.length)
returns (bytes1)
{
// Return the byte at the position marked by the cursor and advance the cursor all at once
return buffer.data[buffer.cursor ++];
}
function peek(
WitnetBuffer.Buffer memory buffer,
uint offset,
uint length
)
internal pure
withinRange(offset + length, buffer.data.length)
returns (bytes memory)
{
bytes memory data = buffer.data;
bytes memory peeks = new bytes(length);
uint destinationPointer;
uint sourcePointer;
assembly {
destinationPointer := add(peeks, 32)
sourcePointer := add(add(data, 32), offset)
}
memcpy(
destinationPointer,
sourcePointer,
length
);
return peeks;
}
// @notice Extract bytes array from buffer starting from current cursor.
/// @param buffer An instance of `Buffer`.
/// @param length How many bytes to peek from the Buffer.
// solium-disable-next-line security/no-assign-params
function peek(
WitnetBuffer.Buffer memory buffer,
uint length
)
internal pure
withinRange(length, buffer.data.length - buffer.cursor)
returns (bytes memory)
{
return peek(
buffer,
buffer.cursor,
length
);
}
/// @notice Read and consume a certain amount of bytes from the buffer.
/// @param buffer An instance of `Buffer`.
/// @param length How many bytes to read and consume from the buffer.
/// @return output A `bytes memory` containing the first `length` bytes from the buffer, counting from the cursor position.
function read(Buffer memory buffer, uint length)
internal pure
withinRange(buffer.cursor + length, buffer.data.length)
returns (bytes memory output)
{
// Create a new `bytes memory destination` value
output = new bytes(length);
// Early return in case that bytes length is 0
if (length > 0) {
bytes memory input = buffer.data;
uint offset = buffer.cursor;
// Get raw pointers for source and destination
uint sourcePointer;
uint destinationPointer;
assembly {
sourcePointer := add(add(input, 32), offset)
destinationPointer := add(output, 32)
}
// Copy `length` bytes from source to destination
memcpy(
destinationPointer,
sourcePointer,
length
);
// Move the cursor forward by `length` bytes
seek(
buffer,
length,
true
);
}
}
/// @notice Read and consume the next 2 bytes from the buffer as an IEEE 754-2008 floating point number enclosed in an
/// `int32`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `float16`
/// use cases. In other words, the integer output of this method is 10,000 times the actual value. The input bytes are
/// expected to follow the 16-bit base-2 format (a.k.a. `binary16`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int32` value of the next 4 bytes in the buffer counting from the cursor position.
function readFloat16(Buffer memory buffer)
internal pure
returns (int32 result)
{
uint32 value = readUint16(buffer);
// Get bit at position 0
uint32 sign = value & 0x8000;
// Get bits 1 to 5, then normalize to the [-15, 16] range so as to counterweight the IEEE 754 exponent bias
int32 exponent = (int32(value & 0x7c00) >> 10) - 15;
// Get bits 6 to 15
int32 fraction = int32(value & 0x03ff);
// Add 2^10 to the fraction if exponent is not -15
if (exponent != -15) {
fraction |= 0x400;
} else if (exponent == 16) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat16: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 1024)`
if (exponent >= 0) {
result = int32(int(
int(1 << uint256(int256(exponent)))
* 10000
* fraction
) >> 10);
} else {
result = int32(int(
int(fraction)
* 10000
/ int(1 << uint(int(- exponent)))
) >> 10);
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
/// @notice Consume the next 4 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `float32`
/// use cases. In other words, the integer output of this method is 10^9 times the actual value. The input bytes are
/// expected to follow the 64-bit base-2 format (a.k.a. `binary32`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
function readFloat32(Buffer memory buffer)
internal pure
returns (int result)
{
uint value = readUint32(buffer);
// Get bit at position 0
uint sign = value & 0x80000000;
// Get bits 1 to 8, then normalize to the [-127, 128] range so as to counterweight the IEEE 754 exponent bias
int exponent = (int(value & 0x7f800000) >> 23) - 127;
// Get bits 9 to 31
int fraction = int(value & 0x007fffff);
// Add 2^23 to the fraction if exponent is not -127
if (exponent != -127) {
fraction |= 0x800000;
} else if (exponent == 128) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat32: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 2^23)`
if (exponent >= 0) {
result = (
int(1 << uint(exponent))
* (10 ** 9)
* fraction
) >> 23;
} else {
result = (
fraction
* (10 ** 9)
/ int(1 << uint(-exponent))
) >> 23;
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
/// @notice Consume the next 8 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `float64`
/// use cases. In other words, the integer output of this method is 10^15 times the actual value. The input bytes are
/// expected to follow the 64-bit base-2 format (a.k.a. `binary64`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
function readFloat64(Buffer memory buffer)
internal pure
returns (int result)
{
uint value = readUint64(buffer);
// Get bit at position 0
uint sign = value & 0x8000000000000000;
// Get bits 1 to 12, then normalize to the [-1023, 1024] range so as to counterweight the IEEE 754 exponent bias
int exponent = (int(value & 0x7ff0000000000000) >> 52) - 1023;
// Get bits 6 to 15
int fraction = int(value & 0x000fffffffffffff);
// Add 2^52 to the fraction if exponent is not -1023
if (exponent != -1023) {
fraction |= 0x10000000000000;
} else if (exponent == 1024) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat64: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 1024)`
if (exponent >= 0) {
result = (
int(1 << uint(exponent))
* (10 ** 15)
* fraction
) >> 52;
} else {
result = (
fraction
* (10 ** 15)
/ int(1 << uint(-exponent))
) >> 52;
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
// Read a text string of a given length from a buffer. Returns a `bytes memory` value for the sake of genericness,
/// but it can be easily casted into a string with `string(result)`.
// solium-disable-next-line security/no-assign-params
function readText(
WitnetBuffer.Buffer memory buffer,
uint64 length
)
internal pure
returns (bytes memory text)
{
text = new bytes(length);
unchecked {
for (uint64 index = 0; index < length; index ++) {
uint8 char = readUint8(buffer);
if (char & 0x80 != 0) {
if (char < 0xe0) {
char = (char & 0x1f) << 6
| (readUint8(buffer) & 0x3f);
length -= 1;
} else if (char < 0xf0) {
char = (char & 0x0f) << 12
| (readUint8(buffer) & 0x3f) << 6
| (readUint8(buffer) & 0x3f);
length -= 2;
} else {
char = (char & 0x0f) << 18
| (readUint8(buffer) & 0x3f) << 12
| (readUint8(buffer) & 0x3f) << 6
| (readUint8(buffer) & 0x3f);
length -= 3;
}
}
text[index] = bytes1(char);
}
// Adjust text to actual length:
assembly {
mstore(text, length)
}
}
}
/// @notice Read and consume the next byte from the buffer as an `uint8`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint8` value of the next byte in the buffer counting from the cursor position.
function readUint8(Buffer memory buffer)
internal pure
withinRange(buffer.cursor, buffer.data.length)
returns (uint8 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 1), offset))
}
buffer.cursor ++;
}
/// @notice Read and consume the next 2 bytes from the buffer as an `uint16`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint16` value of the next 2 bytes in the buffer counting from the cursor position.
function readUint16(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 2, buffer.data.length)
returns (uint16 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 2), offset))
}
buffer.cursor += 2;
}
/// @notice Read and consume the next 4 bytes from the buffer as an `uint32`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint32` value of the next 4 bytes in the buffer counting from the cursor position.
function readUint32(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 4, buffer.data.length)
returns (uint32 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 4), offset))
}
buffer.cursor += 4;
}
/// @notice Read and consume the next 8 bytes from the buffer as an `uint64`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint64` value of the next 8 bytes in the buffer counting from the cursor position.
function readUint64(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 8, buffer.data.length)
returns (uint64 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 8), offset))
}
buffer.cursor += 8;
}
/// @notice Read and consume the next 16 bytes from the buffer as an `uint128`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint128` value of the next 16 bytes in the buffer counting from the cursor position.
function readUint128(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 16, buffer.data.length)
returns (uint128 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 16), offset))
}
buffer.cursor += 16;
}
/// @notice Read and consume the next 32 bytes from the buffer as an `uint256`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint256` value of the next 32 bytes in the buffer counting from the cursor position.
function readUint256(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 32, buffer.data.length)
returns (uint256 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 32), offset))
}
buffer.cursor += 32;
}
/// @notice Count number of required parameters for given bytes arrays
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input Bytes array containing strings.
/// @param count Highest wildcard index found, plus 1.
function argsCountOf(bytes memory input)
internal pure
returns (uint8 count)
{
if (input.length < 3) {
return 0;
}
unchecked {
uint ix = 0;
uint length = input.length - 2;
for (; ix < length; ) {
if (
input[ix] == bytes1("\\")
&& input[ix + 2] == bytes1("\\")
&& input[ix + 1] >= bytes1("0")
&& input[ix + 1] <= bytes1("9")
) {
uint8 ax = uint8(uint8(input[ix + 1]) - uint8(bytes1("0")) + 1);
if (ax > count) {
count = ax;
}
ix += 3;
} else {
ix ++;
}
}
}
}
/// @notice Replace indexed bytes-wildcards by correspondent substrings.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input Bytes array containing strings.
/// @param args Array of substring values for replacing indexed wildcards.
/// @return output Resulting bytes array after replacing all wildcards.
/// @return hits Total number of replaced wildcards.
function replace(bytes memory input, string[] memory args)
internal pure
returns (bytes memory output, uint hits)
{
uint ix = 0; uint lix = 0;
uint inputLength;
uint inputPointer;
uint outputLength;
uint outputPointer;
uint source;
uint sourceLength;
uint sourcePointer;
if (input.length < 3) {
return (input, 0);
}
assembly {
// set starting input pointer
inputPointer := add(input, 32)
// get safe output location
output := mload(0x40)
// set starting output pointer
outputPointer := add(output, 32)
}
unchecked {
uint length = input.length - 2;
for (; ix < length; ) {
if (
input[ix] == bytes1("\\")
&& input[ix + 2] == bytes1("\\")
&& input[ix + 1] >= bytes1("0")
&& input[ix + 1] <= bytes1("9")
) {
inputLength = (ix - lix);
if (ix > lix) {
memcpy(
outputPointer,
inputPointer,
inputLength
);
inputPointer += inputLength + 3;
outputPointer += inputLength;
} else {
inputPointer += 3;
}
uint ax = uint(uint8(input[ix + 1]) - uint8(bytes1("0")));
if (ax >= args.length) {
revert MissingArgs(ax + 1, args.length);
}
assembly {
source := mload(add(args, mul(32, add(ax, 1))))
sourceLength := mload(source)
sourcePointer := add(source, 32)
}
memcpy(
outputPointer,
sourcePointer,
sourceLength
);
outputLength += inputLength + sourceLength;
outputPointer += sourceLength;
ix += 3;
lix = ix;
hits ++;
} else {
ix ++;
}
}
ix = input.length;
}
if (outputLength > 0) {
if (ix > lix ) {
memcpy(
outputPointer,
inputPointer,
ix - lix
);
outputLength += (ix - lix);
}
assembly {
// set final output length
mstore(output, outputLength)
// protect output bytes
mstore(0x40, add(mload(0x40), add(outputLength, 32)))
}
}
else {
return (input, 0);
}
}
/// @notice Replace indexed bytes-wildcard by given substring.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input Bytes array containing strings.
/// @param argIndex Index of the wildcard to be replaced.
/// @param argValue Replacing substring to be used.
/// @return output Resulting bytes array after replacing all wildcards.
/// @return hits Total number of replaced wildcards.
function replace(bytes memory input, uint8 argIndex, string memory argValue)
internal pure
returns (bytes memory output, uint hits)
{
uint ix = 0; uint lix = 0;
uint inputLength;
uint inputPointer;
uint outputLength;
uint outputPointer;
uint argValueLength;
uint argValuePointer;
if (input.length < 3) {
return (input, 0);
}
assembly {
// set starting input pointer
inputPointer := add(input, 32)
// get safe output location
output := mload(0x40)
// set starting output pointer
outputPointer := add(output, 32)
// set pointer to arg value substring
argValuePointer := add(argValue, 32)
// set arg value substring length
argValueLength := mload(argValue)
}
unchecked {
uint length = input.length - 2;
for (; ix < length; ) {
if (
input[ix] == bytes1("\\")
&& input[ix + 2] == bytes1("\\")
&& input[ix + 1] >= bytes1("0")
&& input[ix + 1] <= bytes1("9")
&& uint8(input[ix + 1]) - uint8(bytes1("0")) == argIndex
) {
inputLength = (ix - lix);
if (ix > lix) {
memcpy(
outputPointer,
inputPointer,
inputLength
);
inputPointer += inputLength + 3;
outputPointer += inputLength;
} else {
inputPointer += 3;
}
memcpy(
outputPointer,
argValuePointer,
argValueLength
);
outputLength += inputLength + argValueLength;
outputPointer += argValueLength;
ix += 3;
lix = ix;
hits ++;
} else {
ix ++;
}
}
ix = input.length;
}
if (outputLength > 0) {
if (ix > lix ) {
memcpy(
outputPointer,
inputPointer,
ix - lix
);
outputLength += (ix - lix);
}
assembly {
// set final output length
mstore(output, outputLength)
// protect output bytes
mstore(0x40, add(mload(0x40), add(outputLength, 32)))
}
}
else {
return (input, 0);
}
}
/// @notice Replace indexed string wildcards by correspondent substrings.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input String potentially containing wildcards.
/// @param args Array of substring values for replacing indexed wildcards.
/// @return output Resulting string after replacing all wildcards.
function replace(string memory input, string[] memory args)
internal pure
returns (string memory)
{
(bytes memory _outputBytes, ) = replace(bytes(input), args);
return string(_outputBytes);
}
/// @notice Replace last indexed wildcard by given substring.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input String potentially containing wildcards.
/// @param argIndex Index of the wildcard to be replaced.
/// @param argValue Replacing string to be used.
/// @return output Resulting string after replacing all wildcards.
function replace(string memory input, uint8 argIndex, string memory argValue)
internal pure
returns (string memory)
{
(bytes memory _outputBytes, ) = replace(bytes(input), argIndex, argValue);
return string(_outputBytes);
}
/// @notice Move the inner cursor of the buffer to a relative or absolute position.
/// @param buffer An instance of `Buffer`.
/// @param offset How many bytes to move the cursor forward.
/// @param relative Whether to count `offset` from the last position of the cursor (`true`) or the beginning of the
/// buffer (`true`).
/// @return The final position of the cursor (will equal `offset` if `relative` is `false`).
// solium-disable-next-line security/no-assign-params
function seek(
Buffer memory buffer,
uint offset,
bool relative
)
internal pure
withinRange(offset, buffer.data.length)
returns (uint)
{
// Deal with relative offsets
if (relative) {
offset += buffer.cursor;
}
buffer.cursor = offset;
return offset;
}
/// @notice Move the inner cursor a number of bytes forward.
/// @dev This is a simple wrapper around the relative offset case of `seek()`.
/// @param buffer An instance of `Buffer`.
/// @param relativeOffset How many bytes to move the cursor forward.
/// @return The final position of the cursor.
function seek(
Buffer memory buffer,
uint relativeOffset
)
internal pure
returns (uint)
{
return seek(
buffer,
relativeOffset,
true
);
}
/// @notice Copy bytes from one memory address into another.
/// @dev This function was borrowed from Nick Johnson's `solidity-stringutils` lib, and reproduced here under the terms
/// of [Apache License 2.0](https://github.com/Arachnid/solidity-stringutils/blob/master/LICENSE).
/// @param dest Address of the destination memory.
/// @param src Address to the source memory.
/// @param len How many bytes to copy.
// solium-disable-next-line security/no-assign-params
function memcpy(
uint dest,
uint src,
uint len
)
private pure
{
unchecked {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
if (len > 0) {
// Copy remaining bytes
uint _mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(_mask))
let destpart := and(mload(dest), _mask)
mstore(dest, or(destpart, srcpart))
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./Bech32.sol";
import "./Secp256k1.sol";
import "./WitnetCBOR.sol";
library Witnet {
using Bech32 for Witnet.Address;
using WitnetBuffer for WitnetBuffer.Buffer;
using WitnetCBOR for WitnetCBOR.CBOR;
using WitnetCBOR for WitnetCBOR.CBOR[];
type Address is bytes20;
type BlockNumber is uint64;
type QueryEvmReward is uint72;
type QueryUUID is bytes15;
type QueryId is uint64;
type RadonHash is bytes32;
type ServiceProvider is bytes20;
type Timestamp is uint64;
type TransactionHash is bytes32;
uint32 constant internal WIT_1_GENESIS_TIMESTAMP = 0; // TBD
uint32 constant internal WIT_1_SECS_PER_EPOCH = 45;
uint32 constant internal WIT_2_GENESIS_BEACON_INDEX = 0; // TBD
uint32 constant internal WIT_2_GENESIS_BEACON_PREV_INDEX = 0; // TBD
bytes24 constant internal WIT_2_GENESIS_BEACON_PREV_ROOT = 0; // TBD
bytes16 constant internal WIT_2_GENESIS_BEACON_DDR_TALLIES_MERKLE_ROOT = 0; // TBD
bytes16 constant internal WIT_2_GENESIS_BEACON_DRO_TALLIES_MERKLE_ROOT = 0; // TBD
uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_0 = 0; // TBD
uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_1 = 0; // TBD
uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_2 = 0; // TBD
uint256 constant internal WIT_2_GENESIS_BEACON_NEXT_COMMITTEE_AGG_PUBKEY_3 = 0; // TBD
uint32 constant internal WIT_2_GENESIS_EPOCH = 0; // TBD
uint32 constant internal WIT_2_GENESIS_TIMESTAMP = 0; // TBD
uint32 constant internal WIT_2_SECS_PER_EPOCH = 20; // TBD
uint32 constant internal WIT_2_FAST_FORWARD_COMMITTEE_SIZE = 64; // TBD
function channel(address wrb) internal view returns (bytes4) {
return bytes4(keccak256(abi.encode(address(wrb), block.chainid)));
}
struct Beacon {
uint32 index;
uint32 prevIndex;
bytes24 prevRoot;
bytes16 ddrTalliesMerkleRoot;
bytes16 droTalliesMerkleRoot;
uint256[4] nextCommitteeAggPubkey;
}
struct DataPullReport {
QueryId queryId;
QueryUUID queryHash; // KECCAK256(channel | blockhash(block.number - 1) | ...)
bytes witDrRelayerSignature; // ECDSA.signature(queryHash)
BlockNumber witDrResultEpoch;
bytes witDrResultCborBytes;
TransactionHash witDrTxHash;
}
struct DataPushReport {
TransactionHash witDrTxHash;
RadonHash queryRadHash;
QuerySLA queryParams;
Timestamp resultTimestamp;
bytes resultCborBytes;
}
/// Data struct containing the Witnet-provided result to a Data Request.
struct DataResult {
ResultStatus status;
RadonDataTypes dataType;
TransactionHash drTxHash;
uint256 finality;
Timestamp timestamp;
WitnetCBOR.CBOR value;
}
struct FastForward {
Beacon beacon;
uint256[2] committeeAggSignature;
uint256[4][] committeeMissingPubkeys;
}
/// Struct containing both request and response data related to every query posted to the Witnet Request Board
struct Query {
QueryRequest request;
QueryResponse response;
QuerySLA slaParams; // Minimum Service-Level parameters to be committed by the Witnet blockchain.
QueryUUID uuid; // Universal unique identifier determined by the payload, WRB instance, chain id and EVM's previous block hash.
QueryEvmReward reward; // EVM amount in wei eventually to be paid to the legit reporter.
BlockNumber checkpoint;
}
/// Possible status of a Witnet query.
enum QueryStatus {
Unknown,
Posted,
Reported,
Finalized,
Delayed,
Expired,
Disputed
}
struct QueryCallback {
address consumer; // consumer contract address to which the query result will be reported
uint24 gasLimit; // expected max amount of gas required by the callback method in the consumer contract
}
/// Data kept in EVM-storage for every Request posted to the Witnet Request Board.
struct QueryRequest {
address requester; // EVM address from which the request was posted.
uint24 callbackGas; // Max callback gas limit upon response, if a callback is required.
bytes radonBytecode; // Optional: Witnet Data Request bytecode to be solved by the Witnet blockchain.
RadonHash radonHash; // Optional: Previously verified hash of the Witnet Data Request to be solved.
}
/// QueryResponse metadata and result as resolved by the Witnet blockchain.
struct QueryResponse {
address reporter; // EVM address from which the Data Request result was reported.
Timestamp resultTimestamp; // Unix timestamp (seconds) at which the data request was resolved in the Witnet blockchain.
TransactionHash resultDrTxHash; // Unique hash of the commit/reveal act in the Witnet blockchain that resolved the data request.
bytes resultCborBytes; // CBOR-encode result to the request, as resolved in the Witnet blockchain.
address disputer;
}
/// Structure containing all possible SLA security parameters for Wit/2.1 Data Requests
struct QuerySLA {
uint16 witResultMaxSize; // max size permitted to whatever query result may come from the Wit/Oracle blockchain.
uint16 witCommitteeSize; // max number of eligibile witnesses in the Wit/Oracle blockchain for solving some query.
uint64 witUnitaryReward; // min fees in nanowits to be paid for getting the query solved and reported from the Wit/Oracle.
}
enum ResultStatus {
/// 0x00: No errors.
NoErrors,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Source-specific format error sub-codes ============================================================================
/// 0x01: At least one of the source scripts is not a valid CBOR-encoded value.
SourceScriptNotCBOR,
/// 0x02: The CBOR value decoded from a source script is not an Array.
SourceScriptNotArray,
/// 0x03: The Array value decoded form a source script is not a valid Data Request.
SourceScriptNotRADON,
/// 0x04: The request body of at least one data source was not properly formated.
SourceRequestBody,
/// 0x05: The request headers of at least one data source was not properly formated.
SourceRequestHeaders,
/// 0x06: The request URL of at least one data source was not properly formated.
SourceRequestURL,
/// Unallocated
SourceFormat0x07, SourceFormat0x08, SourceFormat0x09, SourceFormat0x0A, SourceFormat0x0B, SourceFormat0x0C,
SourceFormat0x0D, SourceFormat0x0E, SourceFormat0x0F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Complexity error sub-codes ========================================================================================
/// 0x10: The request contains too many sources.
RequestTooManySources,
/// 0x11: The script contains too many calls.
ScriptTooManyCalls,
/// Unallocated
Complexity0x12, Complexity0x13, Complexity0x14, Complexity0x15, Complexity0x16, Complexity0x17, Complexity0x18,
Complexity0x19, Complexity0x1A, Complexity0x1B, Complexity0x1C, Complexity0x1D, Complexity0x1E, Complexity0x1F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Lack of support error sub-codes ===================================================================================
/// 0x20: Some Radon operator code was found that is not supported (1+ args).
UnsupportedOperator,
/// 0x21: Some Radon filter opcode is not currently supported (1+ args).
UnsupportedFilter,
/// 0x22: Some Radon request type is not currently supported (1+ args).
UnsupportedHashFunction,
/// 0x23: Some Radon reducer opcode is not currently supported (1+ args)
UnsupportedReducer,
/// 0x24: Some Radon hash function is not currently supported (1+ args).
UnsupportedRequestType,
/// 0x25: Some Radon encoding function is not currently supported (1+ args).
UnsupportedEncodingFunction,
/// Unallocated
Operator0x26, Operator0x27,
/// 0x28: Wrong number (or type) of arguments were passed to some Radon operator.
WrongArguments,
/// Unallocated
Operator0x29, Operator0x2A, Operator0x2B, Operator0x2C, Operator0x2D, Operator0x2E, Operator0x2F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Retrieve-specific circumstantial error sub-codes ================================================================================
/// 0x30: A majority of data sources returned an HTTP status code other than 200 (1+ args):
HttpErrors,
/// 0x31: A majority of data sources timed out:
RetrievalsTimeout,
/// Unallocated
RetrieveCircumstance0x32, RetrieveCircumstance0x33, RetrieveCircumstance0x34, RetrieveCircumstance0x35,
RetrieveCircumstance0x36, RetrieveCircumstance0x37, RetrieveCircumstance0x38, RetrieveCircumstance0x39,
RetrieveCircumstance0x3A, RetrieveCircumstance0x3B, RetrieveCircumstance0x3C, RetrieveCircumstance0x3D,
RetrieveCircumstance0x3E, RetrieveCircumstance0x3F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Scripting-specific runtime error sub-code =========================================================================
/// 0x40: Math operator caused an underflow.
MathUnderflow,
/// 0x41: Math operator caused an overflow.
MathOverflow,
/// 0x42: Math operator tried to divide by zero.
MathDivisionByZero,
/// 0x43: Wrong input to subscript call.
WrongSubscriptInput,
/// 0x44: Value cannot be extracted from input binary buffer.
BufferIsNotValue,
/// 0x45: Value cannot be decoded from expected type.
Decode,
/// 0x46: Unexpected empty array.
EmptyArray,
/// 0x47: Value cannot be encoded to expected type.
Encode,
/// 0x48: Failed to filter input values (1+ args).
Filter,
/// 0x49: Failed to hash input value.
Hash,
/// 0x4A: Mismatching array ranks.
MismatchingArrays,
/// 0x4B: Failed to process non-homogenous array.
NonHomegeneousArray,
/// 0x4C: Failed to parse syntax of some input value, or argument.
Parse,
/// 0x4D: Parsing logic limits were exceeded.
ParseOverflow,
/// Unallocated
ScriptError0x4E, ScriptError0x4F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Actual first-order result error codes =============================================================================
/// 0x50: Not enough reveals were received in due time:
InsufficientReveals,
/// 0x51: No actual reveal majority was reached on tally stage:
InsufficientMajority,
/// 0x52: Not enough commits were received before tally stage:
InsufficientCommits,
/// 0x53: Generic error during tally execution (to be deprecated after WIP #0028)
TallyExecution,
/// 0x54: A majority of data sources could either be temporarily unresponsive or failing to report the requested data:
CircumstantialFailure,
/// 0x55: At least one data source is inconsistent when queried through multiple transports at once:
InconsistentSources,
/// 0x56: Any one of the (multiple) Retrieve, Aggregate or Tally scripts were badly formated:
MalformedDataRequest,
/// 0x57: Values returned from a majority of data sources don't match the expected schema:
MalformedQueryResponses,
/// Unallocated:
OtherError0x58, OtherError0x59, OtherError0x5A, OtherError0x5B, OtherError0x5C, OtherError0x5D, OtherError0x5E,
/// 0x5F: Size of serialized tally result exceeds allowance:
OversizedTallyResult,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Inter-stage runtime error sub-codes ===============================================================================
/// 0x60: Data aggregation reveals could not get decoded on the tally stage:
MalformedReveals,
/// 0x61: The result to data aggregation could not get encoded:
EncodeReveals,
/// 0x62: A mode tie ocurred when calculating some mode value on the aggregation or the tally stage:
ModeTie,
/// Unallocated:
OtherError0x63, OtherError0x64, OtherError0x65, OtherError0x66, OtherError0x67, OtherError0x68, OtherError0x69,
OtherError0x6A, OtherError0x6B, OtherError0x6C, OtherError0x6D, OtherError0x6E, OtherError0x6F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Runtime access error sub-codes ====================================================================================
/// 0x70: Tried to access a value from an array using an index that is out of bounds (1+ args):
ArrayIndexOutOfBounds,
/// 0x71: Tried to access a value from a map using a key that does not exist (1+ args):
MapKeyNotFound,
/// 0X72: Tried to extract value from a map using a JSON Path that returns no values (+1 args):
JsonPathNotFound,
/// Unallocated:
OtherError0x73, OtherError0x74, OtherError0x75, OtherError0x76, OtherError0x77, OtherError0x78,
OtherError0x79, OtherError0x7A, OtherError0x7B, OtherError0x7C, OtherError0x7D, OtherError0x7E, OtherError0x7F,
OtherError0x80, OtherError0x81, OtherError0x82, OtherError0x83, OtherError0x84, OtherError0x85, OtherError0x86,
OtherError0x87, OtherError0x88, OtherError0x89, OtherError0x8A, OtherError0x8B, OtherError0x8C, OtherError0x8D,
OtherError0x8E, OtherError0x8F, OtherError0x90, OtherError0x91, OtherError0x92, OtherError0x93, OtherError0x94,
OtherError0x95, OtherError0x96, OtherError0x97, OtherError0x98, OtherError0x99, OtherError0x9A, OtherError0x9B,
OtherError0x9C, OtherError0x9D, OtherError0x9E, OtherError0x9F, OtherError0xA0, OtherError0xA1, OtherError0xA2,
OtherError0xA3, OtherError0xA4, OtherError0xA5, OtherError0xA6, OtherError0xA7, OtherError0xA8, OtherError0xA9,
OtherError0xAA, OtherError0xAB, OtherError0xAC, OtherError0xAD, OtherError0xAE, OtherError0xAF, OtherError0xB0,
OtherError0xB1, OtherError0xB2, OtherError0xB3, OtherError0xB4, OtherError0xB5, OtherError0xB6, OtherError0xB7,
OtherError0xB8, OtherError0xB9, OtherError0xBA, OtherError0xBB, OtherError0xBC, OtherError0xBD, OtherError0xBE,
OtherError0xBF, OtherError0xC0, OtherError0xC1, OtherError0xC2, OtherError0xC3, OtherError0xC4, OtherError0xC5,
OtherError0xC6, OtherError0xC7, OtherError0xC8, OtherError0xC9, OtherError0xCA, OtherError0xCB, OtherError0xCC,
OtherError0xCD, OtherError0xCE, OtherError0xCF, OtherError0xD0, OtherError0xD1, OtherError0xD2, OtherError0xD3,
OtherError0xD4, OtherError0xD5, OtherError0xD6, OtherError0xD7, OtherError0xD8, OtherError0xD9, OtherError0xDA,
OtherError0xDB, OtherError0xDC, OtherError0xDD, OtherError0xDE, OtherError0xDF,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Inter-client generic error codes ==================================================================================
/// Data requests that cannot be relayed into the Witnet blockchain should be reported
/// with one of these errors.
/// 0xE0: Requests that cannot be parsed must always get this error as their result.
BridgeMalformedDataRequest,
/// 0xE1: Witnesses exceeds 100
BridgePoorIncentives,
/// 0xE2: The request is rejected on the grounds that it may cause the submitter to spend or stake an
/// amount of value that is unjustifiably high when compared with the reward they will be getting
BridgeOversizedTallyResult,
/// Unallocated:
OtherError0xE3, OtherError0xE4, OtherError0xE5, OtherError0xE6, OtherError0xE7, OtherError0xE8, OtherError0xE9,
OtherError0xEA, OtherError0xEB, OtherError0xEC, OtherError0xED, OtherError0xEE, OtherError0xEF,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Transient errors as determined by the Request Board contract ======================================================
/// 0xF0:
BoardAwaitingResult,
/// 0xF1:
BoardFinalizingResult,
/// 0xF2:
BoardBeingDisputed,
/// Unallocated
OtherError0xF3, OtherError0xF4, OtherError0xF5, OtherError0xF6, OtherError0xF7,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Final errors as determined by the Request Board contract ==========================================================
/// 0xF8:
BoardAlreadyDelivered,
/// 0xF9:
BoardResolutionTimeout,
/// Unallocated:
OtherError0xFA, OtherError0xFB, OtherError0xFC, OtherError0xFD, OtherError0xFE,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 0xFF: Some tally error is not intercepted but it should (0+ args)
UnhandledIntercept
}
/// Possible types either processed by Witnet Radon Scripts or included within results to Witnet Data Requests.
enum RadonDataTypes {
/* 0x00 */ Any,
/* 0x01 */ Array,
/* 0x02 */ Bool,
/* 0x03 */ Bytes,
/* 0x04 */ Integer,
/* 0x05 */ Float,
/* 0x06 */ Map,
/* 0x07 */ String,
Unused0x08, Unused0x09, Unused0x0A, Unused0x0B,
Unused0x0C, Unused0x0D, Unused0x0E, Unused0x0F,
/* 0x10 */ Same,
/* 0x11 */ Inner,
/* 0x12 */ Match,
/* 0x13 */ Subscript
}
/// Structure defining some data filtering that can be applied at the Aggregation or the Tally stages
/// within a Witnet Data Request resolution workflow.
struct RadonFilter {
RadonFilterOpcodes opcode;
bytes cborArgs;
}
/// Filtering methods currently supported on the Witnet blockchain.
enum RadonFilterOpcodes {
/* 0x00 */ Reserved0x00, //GreaterThan,
/* 0x01 */ Reserved0x01, //LessThan,
/* 0x02 */ Reserved0x02, //Equals,
/* 0x03 */ Reserved0x03, //AbsoluteDeviation,
/* 0x04 */ Reserved0x04, //RelativeDeviation
/* 0x05 */ StandardDeviation,
/* 0x06 */ Reserved0x06, //Top,
/* 0x07 */ Reserved0x07, //Bottom,
/* 0x08 */ Mode,
/* 0x09 */ Reserved0x09 //LessOrEqualThan
}
/// Structure defining the array of filters and reducting function to be applied at either the Aggregation
/// or the Tally stages within a Witnet Data Request resolution workflow.
struct RadonReducer {
RadonReduceOpcodes opcode;
RadonFilter[] filters;
}
/// Reducting functions currently supported on the Witnet blockchain.
enum RadonReduceOpcodes {
/* 0x00 */ Reserved0x00, //Minimum,
/* 0x01 */ Reserved0x01, //Maximum,
/* 0x02 */ Mode,
/* 0x03 */ AverageMean,
/* 0x04 */ Reserved0x04, //AverageMeanWeighted,
/* 0x05 */ AverageMedian,
/* 0x06 */ Reserved0x06, //AverageMedianWeighted,
/* 0x07 */ StandardDeviation,
/* 0x08 */ Reserved0x08, //AverageDeviation,
/* 0x09 */ Reserved0x09, //MedianDeviation,
/* 0x0A */ Reserved0x10, //MaximumDeviation,
/* 0x0B */ ConcatenateAndHash
}
/// Structure containing the Retrieve-Attestation-Delivery parts of a Witnet-compliant Data Request.
struct RadonRequest {
RadonRetrieval[] retrieve;
RadonReducer aggregate;
RadonReducer tally;
}
/// Structure containing all the parameters that fully describe a Witnet Radon Retrieval within a Witnet Data Request.
struct RadonRetrieval {
uint8 argsCount;
RadonRetrievalMethods method;
RadonDataTypes dataType;
string url;
string body;
string[2][] headers;
bytes radonScript;
}
/// Possible Radon retrieval methods that can be used within a Radon Retrieval.
enum RadonRetrievalMethods {
/* 0 */ Unknown,
/* 1 */ HttpGet,
/* 2 */ RNG,
/* 3 */ HttpPost,
/* 4 */ HttpHead
}
/// Structure containing all possible SLA security parameters of a Witnet-compliant Data Request.
struct RadonSLAv1 {
uint8 numWitnesses;
uint8 minConsensusPercentage;
uint64 witnessReward;
uint64 witnessCollateral;
uint64 minerCommitRevealFee;
}
/// =======================================================================
/// --- Witnet.Address helper functions -----------------------------------
function eq(Address a, Address b) internal pure returns (bool) {
return Address.unwrap(a) == Address.unwrap(b);
}
function fromBech32(string memory pkh, bool mainnet) internal pure returns (Address) {
require(bytes(pkh).length == (mainnet ? 42 : 43), "Bech32: invalid length");
return Address.wrap(bytes20(Bech32.fromBech32(pkh, mainnet ? "wit" : "twit")));
}
function toBech32(Address witAddress, bool mainnet) internal pure returns (string memory) {
return Bech32.toBech32(address(Address.unwrap(witAddress)), mainnet ? "wit" : "twit");
}
function isZero(Address a) internal pure returns (bool) {
return Address.unwrap(a) == bytes20(0);
}
/// =======================================================================
/// --- Witnet.Beacon helper functions ------------------------------------
function equals(Beacon storage self, Beacon calldata other)
internal view returns (bool)
{
return (
root(self) == root(other)
);
}
function root(Beacon calldata self) internal pure returns (bytes24) {
return bytes24(keccak256(abi.encode(
self.index,
self.prevIndex,
self.prevRoot,
self.ddrTalliesMerkleRoot,
self.droTalliesMerkleRoot,
self.nextCommitteeAggPubkey
)));
}
function root(Beacon storage self) internal view returns (bytes24) {
return bytes24(keccak256(abi.encode(
self.index,
self.prevIndex,
self.prevRoot,
self.ddrTalliesMerkleRoot,
self.droTalliesMerkleRoot,
self.nextCommitteeAggPubkey
)));
}
/// =======================================================================
/// --- BlockNumber helper functions --------------------------------------
function egt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
return BlockNumber.unwrap(a) >= BlockNumber.unwrap(b);
}
function elt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
return BlockNumber.unwrap(a) <= BlockNumber.unwrap(b);
}
function gt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
return BlockNumber.unwrap(a) > BlockNumber.unwrap(b);
}
function lt(BlockNumber a, BlockNumber b) internal pure returns (bool) {
return BlockNumber.unwrap(a) < BlockNumber.unwrap(b);
}
function isZero(BlockNumber b) internal pure returns (bool) {
return (BlockNumber.unwrap(b) == 0);
}
/// ===============================================================================================================
/// --- Data*Report helper methods --------------------------------------------------------------------------------
function queryRelayer(DataPullReport calldata self) internal pure returns (address) {
return recoverEvmAddr(
self.witDrRelayerSignature,
hashify(self.queryHash)
);
}
function tallyHash(DataPullReport calldata self) internal pure returns (bytes32) {
return keccak256(abi.encode(
self.queryHash,
self.witDrRelayerSignature,
self.witDrTxHash,
self.witDrResultEpoch,
self.witDrResultCborBytes
));
}
function digest(DataPushReport calldata self) internal pure returns (bytes32) {
return keccak256(abi.encode(
self.witDrTxHash,
self.queryRadHash,
self.queryParams.witResultMaxSize,
self.queryParams.witCommitteeSize,
self.queryParams.witUnitaryReward,
self.resultTimestamp,
self.resultCborBytes
));
}
/// ========================================================================================================
/// --- 'DataResult' helper methods ------------------------------------------------------------------------
function noErrors(DataResult memory self) internal pure returns (bool) {
return self.status == ResultStatus.NoErrors;
}
function keepWaiting(DataResult memory self) internal pure returns (bool) {
return keepWaiting(self.status);
}
function hasErrors(DataResult memory self) internal pure returns (bool) {
return hasErrors(self.status);
}
modifier _checkDataType(DataResult memory self, RadonDataTypes expectedDataType) {
require(
!keepWaiting(self)
&& self.dataType == expectedDataType
, "cbor: cannot fetch data"
); _;
self.dataType = peekRadonDataType(self.value);
}
function fetchAddress(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Bytes)
returns (address _res)
{
return toAddress(self.value.readBytes());
}
function fetchBool(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Bool)
returns (bool)
{
return self.value.readBool();
}
function fetchBytes(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Bytes)
returns (bytes memory)
{
return self.value.readBytes();
}
function fetchBytes4(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Bytes)
returns (bytes4)
{
return toBytes4(self.value.readBytes());
}
function fetchBytes32(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Bytes)
returns (bytes32)
{
return toBytes32(self.value.readBytes());
}
function fetchCborArray(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Array)
returns (WitnetCBOR.CBOR[] memory)
{
return self.value.readArray();
}
/// @dev Decode a fixed16 (half-precision) numeric value from the Result's CBOR value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values.
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`.
/// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
function fetchFloatFixed16(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Float)
returns (int32)
{
return self.value.readFloat16();
}
/// @dev Decode an array of fixed16 values from the Result's CBOR value.
function fetchFloatFixed16Array(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Array)
returns (int32[] memory)
{
return self.value.readFloat16Array();
}
/// @dev Decode a `int64` value from the DataResult's CBOR value.
function fetchInt(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Integer)
returns (int64)
{
return self.value.readInt();
}
function fetchInt64Array(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Array)
returns (int64[] memory)
{
return self.value.readIntArray();
}
function fetchString(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.String)
returns (string memory)
{
return self.value.readString();
}
function fetchStringArray(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Array)
returns (string[] memory)
{
return self.value.readStringArray();
}
/// @dev Decode a `uint64` value from the DataResult's CBOR value.
function fetchUint(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Integer)
returns (uint64)
{
return self.value.readUint();
}
function fetchUint64Array(DataResult memory self)
internal pure
_checkDataType(self, RadonDataTypes.Array)
returns (uint64[] memory)
{
return self.value.readUintArray();
}
bytes7 private constant _CBOR_MAJOR_TYPE_TO_RADON_DATA_TYPES_MAP = 0x04040307010600;
function peekRadonDataType(WitnetCBOR.CBOR memory cbor) internal pure returns (RadonDataTypes _type) {
_type = RadonDataTypes.Any;
if (!cbor.eof()) {
if (cbor.majorType <= 6) {
return RadonDataTypes(uint8(bytes1(_CBOR_MAJOR_TYPE_TO_RADON_DATA_TYPES_MAP[cbor.majorType])));
} else if (cbor.majorType == 7) {
if (cbor.additionalInformation == 20 || cbor.additionalInformation == 21) {
return RadonDataTypes.Bool;
} else if (cbor.additionalInformation >= 25 && cbor.additionalInformation <= 27) {
return RadonDataTypes.Float;
}
}
}
}
/// =======================================================================
/// --- FastForward helper functions --------------------------------------
function head(FastForward[] calldata rollup)
internal pure returns (Beacon calldata)
{
return rollup[rollup.length - 1].beacon;
}
/// ===============================================================================================================
/// --- Query* helper methods -------------------------------------------------------------------------------------
function equalOrGreaterThan(QuerySLA calldata self, QuerySLA storage stored) internal view returns (bool) {
return (
self.witCommitteeSize >= stored.witCommitteeSize
&& self.witUnitaryReward >= stored.witUnitaryReward
&& self.witResultMaxSize <= stored.witResultMaxSize
);
}
function hashify(QueryUUID hash) internal pure returns (bytes32) {
return keccak256(abi.encode(QueryUUID.unwrap(hash)));
}
function hashify(QueryId _queryId, Witnet.RadonHash _radHash, bytes32 _slaHash) internal view returns (Witnet.QueryUUID) {
return Witnet.QueryUUID.wrap(bytes15(
keccak256(abi.encode(
channel(address(this)),
blockhash(block.number - 1),
_queryId, Witnet.RadonHash.unwrap(_radHash), _slaHash
))
));
}
function hashify(QuerySLA memory querySLA) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(
querySLA.witResultMaxSize,
querySLA.witCommitteeSize,
querySLA.witUnitaryReward
));
}
function isValid(QuerySLA memory self) internal pure returns (bool) {
return (
self.witResultMaxSize >= 0
&& self.witCommitteeSize > 0
&& self.witCommitteeSize <= 127
&& self.witUnitaryReward > 0
);
}
function isZero(QueryId a) internal pure returns (bool) {
return (QueryId.unwrap(a) == 0);
}
function toV1(QuerySLA calldata self) internal pure returns (RadonSLAv1 memory) {
return RadonSLAv1({
numWitnesses: uint8(self.witCommitteeSize),
minConsensusPercentage: 51,
witnessReward: self.witUnitaryReward,
witnessCollateral: self.witUnitaryReward * self.witCommitteeSize,
minerCommitRevealFee: self.witUnitaryReward / self.witCommitteeSize
});
}
/// ===============================================================================================================
/// --- RadonHash helper methods ----------------------------------------------------------------------------------
function eq(RadonHash a, RadonHash b) internal pure returns (bool) {
return RadonHash.unwrap(a) == RadonHash.unwrap(b);
}
function isZero(RadonHash h) internal pure returns (bool) {
return RadonHash.unwrap(h) == bytes32(0);
}
/// ===============================================================================================================
/// --- ResultStatus helper methods -------------------------------------------------------------------------------
function hasErrors(ResultStatus self) internal pure returns (bool) {
return (
self != ResultStatus.NoErrors
&& !keepWaiting(self)
);
}
function isCircumstantial(ResultStatus self) internal pure returns (bool) {
return (self == ResultStatus.CircumstantialFailure);
}
function isRetriable(ResultStatus self) internal pure returns (bool) {
return (
lackOfConsensus(self)
|| isCircumstantial(self)
|| poorIncentives(self)
);
}
function keepWaiting(ResultStatus self) internal pure returns (bool) {
return (
self == ResultStatus.BoardAwaitingResult
|| self == ResultStatus.BoardFinalizingResult
);
}
function lackOfConsensus(ResultStatus self) internal pure returns (bool) {
return (
self == ResultStatus.InsufficientCommits
|| self == ResultStatus.InsufficientMajority
|| self == ResultStatus.InsufficientReveals
);
}
function poorIncentives(ResultStatus self) internal pure returns (bool) {
return (
self == ResultStatus.OversizedTallyResult
|| self == ResultStatus.InsufficientCommits
|| self == ResultStatus.BridgePoorIncentives
|| self == ResultStatus.BridgeOversizedTallyResult
);
}
/// ===============================================================================================================
/// --- Timestamp helper methods ----------------------------------------------------------------------------------
function gt(Timestamp a, Timestamp b) internal pure returns (bool) {
return Timestamp.unwrap(a) > Timestamp.unwrap(b);
}
function egt(Timestamp a, Timestamp b) internal pure returns (bool) {
return Timestamp.unwrap(a) >= Timestamp.unwrap(b);
}
function elt(Timestamp a, Timestamp b) internal pure returns (bool) {
return Timestamp.unwrap(a) <= Timestamp.unwrap(b);
}
function isZero(Timestamp t) internal pure returns (bool) {
return Timestamp.unwrap(t) == 0;
}
/// ===============================================================================================================
/// --- 'bytes*' helper methods -----------------------------------------------------------------------------------
function intoMemArray(bytes32[1] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 1, _values), (bytes32[]));
}
function intoMemArray(bytes32[2] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 2, _values), (bytes32[]));
}
function intoMemArray(bytes32[3] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 3, _values), (bytes32[]));
}
function intoMemArray(bytes32[4] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 4, _values), (bytes32[]));
}
function intoMemArray(bytes32[5] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 5, _values), (bytes32[]));
}
function intoMemArray(bytes32[6] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 6, _values), (bytes32[]));
}
function intoMemArray(bytes32[7] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 7, _values), (bytes32[]));
}
function intoMemArray(bytes32[8] memory _values) internal pure returns (bytes32[] memory) {
return abi.decode(abi.encode(uint256(32), 8, _values), (bytes32[]));
}
function merkleHash(bytes32 a, bytes32 b) internal pure returns (bytes32) {
return (a < b
? _merkleHash(a, b)
: _merkleHash(b, a)
);
}
function merkleRoot(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32 _root) {
_root = leaf;
for (uint _ix = 0; _ix < proof.length; _ix ++) {
_root = merkleHash(_root, proof[_ix]);
}
}
function radHash(bytes calldata bytecode) internal pure returns (Witnet.RadonHash) {
return Witnet.RadonHash.wrap(keccak256(bytecode));
}
function recoverEvmAddr(bytes memory signature, bytes32 hash_)
internal pure
returns (address)
{
if (signature.length != 65) {
return (address(0));
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return address(0);
}
if (v != 27 && v != 28) {
return address(0);
}
return ecrecover(hash_, v, r, s);
}
function verifyWitAddressAuthorization(
address evmAuthorized,
Address witSigner,
bytes memory witSignature
)
internal pure
returns (bool)
{
bytes32 _publicKeyX = recoverWitPublicKey(keccak256(abi.encodePacked(evmAuthorized)), witSignature);
bytes20 _witSigner = Address.unwrap(witSigner);
return (
_witSigner == bytes20(sha256(abi.encodePacked(bytes1(0x00), _publicKeyX)))
|| _witSigner == bytes20(sha256(abi.encodePacked(bytes1(0x01), _publicKeyX)))
|| _witSigner == bytes20(sha256(abi.encodePacked(bytes1(0x02), _publicKeyX)))
|| _witSigner == bytes20(sha256(abi.encodePacked(bytes1(0x03), _publicKeyX)))
);
}
function recoverWitPublicKey(bytes32 evmDigest, bytes memory witSignature)
internal pure
returns (bytes32 _witPublicKey)
{
if (witSignature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(witSignature, 0x20))
s := mload(add(witSignature, 0x40))
v := byte(0, mload(add(witSignature, 0x60)))
}
if (
uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
&& (v == 27 || v == 28)
) {
(uint256 x,) = Secp256k1.recover(uint256(evmDigest), v - 27, uint256(r), uint256(s));
_witPublicKey = bytes32(x);
}
}
}
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);
}
}
}
/// @notice Converts bytes32 into string.
function asAscii(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 toHexString(bytes32 _bytes32)
internal pure
returns (string memory)
{
bytes memory _bytes = new bytes(64);
for (uint8 _i; _i < _bytes.length;) {
_bytes[_i ++] = _toHexChar(uint8(_bytes32[_i / 2] >> 4));
_bytes[_i ++] = _toHexChar(uint8(_bytes32[_i / 2] & 0x0f));
}
return string(_bytes);
}
/// ===============================================================================================================
/// --- '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);
}
// Function to parse a hex string into a byte array
function parseHexString(string memory hexString) internal pure returns (bytes memory result) {
unchecked {
result = new bytes(bytes(hexString).length / 2);
for (uint256 i; i < result.length; i ++) {
uint8 byte1 = _hexCharToByte(uint8(bytes(hexString)[2 * i]));
uint8 byte2 = _hexCharToByte(uint8(bytes(hexString)[2 * i + 1]));
result[i] = bytes1(byte1 * 16 + byte2); // Combining the two hex digits into one byte
}
}
}
function tryUint(string memory str)
internal pure
returns (uint res, bool)
{
unchecked {
for (uint256 i = 0; i < bytes(str).length; i++) {
if (
(uint8(bytes(str)[i]) - 48) < 0
|| (uint8(bytes(str)[i]) - 48) > 9
) {
return (0, false);
}
res += (uint8(bytes(str)[i]) - 48) * 10 ** (bytes(str).length - i - 1);
}
return (res, true);
}
}
/// ===============================================================================================================
/// --- 'uint*' helper methods ------------------------------------------------------------------------------------
function determineBeaconIndexFromEpoch(BlockNumber epoch) internal pure returns (uint64) {
return BlockNumber.unwrap(epoch) / 10;
}
function determineBeaconIndexFromTimestamp(Timestamp timestamp) internal pure returns (uint64) {
return determineBeaconIndexFromEpoch(
determineEpochFromTimestamp(
timestamp
)
);
}
function determineEpochFromTimestamp(Timestamp timestamp) internal pure returns (BlockNumber) {
if (Timestamp.unwrap(timestamp) > WIT_2_GENESIS_TIMESTAMP) {
return BlockNumber.wrap(
WIT_2_GENESIS_EPOCH
+ (Timestamp.unwrap(timestamp) - WIT_2_GENESIS_TIMESTAMP)
/ WIT_2_SECS_PER_EPOCH
);
} else if (Timestamp.unwrap(timestamp) > WIT_1_GENESIS_TIMESTAMP) {
return BlockNumber.wrap(
(Timestamp.unwrap(timestamp) - WIT_1_GENESIS_TIMESTAMP)
/ WIT_1_SECS_PER_EPOCH
);
} else {
return BlockNumber.wrap(0);
}
}
function determineTimestampFromEpoch(BlockNumber epoch) internal pure returns (Timestamp) {
if (BlockNumber.unwrap(epoch) >= WIT_2_GENESIS_EPOCH) {
return Timestamp.wrap(
WIT_2_GENESIS_TIMESTAMP
+ (WIT_2_SECS_PER_EPOCH * (
BlockNumber.unwrap(epoch)
- WIT_2_GENESIS_EPOCH)
)
);
} else return Timestamp.wrap(
WIT_1_GENESIS_TIMESTAMP
+ (WIT_1_SECS_PER_EPOCH * BlockNumber.unwrap(epoch))
);
}
/// Generates a pseudo-random uint32 number uniformly distributed within the range `[0 .. range)`, based on
/// the given `nonce` and `seed` values.
function randomUniformUint64(uint64 range, uint256 nonce, bytes32 seed)
internal pure
returns (uint64)
{
uint256 _number = uint256(
keccak256(
abi.encode(seed, nonce)
)
) & uint256(2 ** 192 - 1);
return uint64((_number * range) >> 192);
}
/// @notice Convert a `uint8` into a 2 characters long `string` representing its two less significant hexadecimal values.
function toHexString(uint8 _u)
internal pure
returns (string memory)
{
bytes memory b2 = new bytes(2);
uint8 d0 = uint8(_u / 16) + 48;
uint8 d1 = uint8(_u % 16) + 48;
if (d0 > 57)
d0 += 7;
if (d1 > 57)
d1 += 7;
b2[0] = bytes1(d0);
b2[1] = bytes1(d1);
return string(b2);
}
/// @notice Convert a `uint8` into a 1, 2 or 3 characters long `string` representing its.
/// three less significant decimal values.
function toString(uint8 _u)
internal pure
returns (string memory)
{
if (_u < 10) {
bytes memory b1 = new bytes(1);
b1[0] = bytes1(uint8(_u) + 48);
return string(b1);
} else if (_u < 100) {
bytes memory b2 = new bytes(2);
b2[0] = bytes1(uint8(_u / 10) + 48);
b2[1] = bytes1(uint8(_u % 10) + 48);
return string(b2);
} else {
bytes memory b3 = new bytes(3);
b3[0] = bytes1(uint8(_u / 100) + 48);
b3[1] = bytes1(uint8(_u % 100 / 10) + 48);
b3[2] = bytes1(uint8(_u % 10) + 48);
return string(b3);
}
}
/// @notice Convert a `uint` into a string` representing its value.
function toString(uint v)
internal pure
returns (string memory)
{
uint maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint i = 0;
do {
uint8 remainder = uint8(v % 10);
v = v / 10;
reversed[i ++] = bytes1(48 + remainder);
} while (v != 0);
bytes memory buf = new bytes(i);
for (uint j = 1; j <= i; j ++) {
buf[j - 1] = reversed[i - j];
}
return string(buf);
}
/// ===============================================================================================================
/// --- Witnet library private methods ----------------------------------------------------------------------------
function _hexCharToByte(uint8 hexChar) private pure returns (uint8) {
if (hexChar >= 0x30 && hexChar <= 0x39) {
return hexChar - 0x30; // '0'-'9' to 0-9
} else if (hexChar >= 0x41 && hexChar <= 0x46) {
return hexChar - 0x41 + 10; // 'A'-'F' to 10-15
} else if (hexChar >= 0x61 && hexChar <= 0x66) {
return hexChar - 0x61 + 10; // 'a'-'f' to 10-15
} else {
revert("Invalid hex character");
}
}
function _merkleHash(bytes32 _a, bytes32 _b) private pure returns (bytes32 _hash) {
assembly {
mstore(0x0, _a)
mstore(0x20, _b)
_hash := keccak256(0x0, 0x40)
}
}
function _toHexChar(uint8 _uint8) private pure returns (bytes1) {
return _uint8 < 10 ? bytes1(_uint8 + 48) : bytes1(_uint8 + 87);
}
/// @dev Calculate length of string-equivalent to given bytes32.
function _toStringLength(bytes32 _bytes32)
private pure
returns (uint _length)
{
for (; _length < 32; ) {
if (_bytes32[_length] == 0) {
break;
}
unchecked {
_length ++;
}
}
}
}// SPDX-License-Identifier: APACHE-2.0 pragma solidity >=0.8.0 <0.9.0; /* * @title String & Slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'Slice'. A Slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length Slice). Since a Slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on Slice that need to return * a Slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original Slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second Slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * Slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new Slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ library Slices { struct Slice { uint _len; uint _ptr; } function _memcpy(uint _dest, uint _src, uint _len) private pure { // Copy word-length chunks while possible for(; _len >= 32; _len -= 32) { assembly { mstore(_dest, mload(_src)) } _dest += 32; _src += 32; } // Copy remaining bytes uint _mask = type(uint).max; if (_len > 0) { _mask = 256 ** (32 - _len) - 1; } assembly { let srcpart := and(mload(_src), not(_mask)) let destpart := and(mload(_dest), _mask) mstore(_dest, or(destpart, srcpart)) } } /* * @dev Returns a Slice containing the entire string. * @param self The string to make a Slice from. * @return A newly allocated Slice containing the entire string. */ function toSlice(string memory self) internal pure returns (Slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return Slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & type(uint128).max == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & type(uint64).max == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & type(uint32).max == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & type(uint16).max == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & type(uint8).max == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a Slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a Slice. * @return A new Slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (Slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new Slice containing the same data as the current Slice. * @param self The Slice to copy. * @return A new Slice containing the same data as `self`. */ function copy(Slice memory self) internal pure returns (Slice memory) { return Slice(self._len, self._ptr); } /* * @dev Copies a Slice to a new string. * @param self The Slice to copy. * @return A newly allocated string containing the Slice's text. */ function toString(Slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } _memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the Slice. Note that this operation * takes time proportional to the length of the Slice; avoid using it * in loops, and call `Slice.empty()` if you only need to know whether * the Slice is empty or not. * @param self The Slice to operate on. * @return The length of the Slice in runes. */ function len(Slice memory self) internal pure returns (uint _l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (_l = 0; ptr < end; _l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the Slice is empty (has a length of 0). * @param self The Slice to operate on. * @return True if the Slice is empty, False otherwise. */ function empty(Slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first Slice to compare. * @param other The second Slice to compare. * @return The result of the comparison. */ function compare(Slice memory self, Slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint mask = type(uint).max; // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } unchecked { uint diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first Slice to compare. * @param self The second Slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(Slice memory self, Slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the Slice into `rune`, advancing the * Slice to point to the next rune and returning `self`. * @param self The Slice to operate on. * @param rune The Slice that will contain the first rune. * @return `rune`. */ function nextRune(Slice memory self, Slice memory rune) internal pure returns (Slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint _l; uint _b; // Load the first byte of the rune into the LSBs of _b assembly { _b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (_b < 0x80) { _l = 1; } else if(_b < 0xE0) { _l = 2; } else if(_b < 0xF0) { _l = 3; } else { _l = 4; } // Check for truncated codepoints if (_l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += _l; self._len -= _l; rune._len = _l; return rune; } /* * @dev Returns the first rune in the Slice, advancing the Slice to point * to the next rune. * @param self The Slice to operate on. * @return A Slice containing only the first rune from `self`. */ function nextRune(Slice memory self) internal pure returns (Slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the Slice. * @param self The Slice to operate on. * @return The number of the first codepoint in the Slice. */ function ord(Slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the Slice. * @param self The Slice to hash. * @return The hash of the Slice. */ function keccak(Slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return True if the Slice starts with the provided text, false otherwise. */ function startsWith(Slice memory self, Slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return `self` */ function beyond(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the Slice ends with `needle`. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return True if the Slice starts with the provided text, false otherwise. */ function endsWith(Slice memory self, Slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The Slice to operate on. * @param needle The Slice to search for. * @return `self` */ function until(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the Slice. `self` is set to the empty Slice * if `needle` is not found. * @param self The Slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty Slice. * @param self The Slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(Slice memory self, Slice memory needle) internal pure returns (Slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the Slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and `token` is set to the entirety of `self`. * @param self The Slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the Slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and the entirety of `self` is returned. * @param self The Slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) { split(self, needle, token); } /* * @dev Splits the Slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and `token` is set to the entirety of `self`. * @param self The Slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(Slice memory self, Slice memory needle, Slice memory token) internal pure returns (Slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the Slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty Slice, * and the entirety of `self` is returned. * @param self The Slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(Slice memory self, Slice memory needle) internal pure returns (Slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The Slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(Slice memory self, Slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The Slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(Slice memory self, Slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first Slice to concatenate. * @param other The second Slice to concatenate. * @return The concatenation of the two strings. */ function concat(Slice memory self, Slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } _memcpy(retptr, self._ptr, self._len); _memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(Slice memory self, Slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(uint i = 0; i < parts.length; i++) { _memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { _memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } }
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.17;
/**
* @title Secp256k1 public key recovery Library
* @dev Library providing arithmetic operations over signed `secpk256k1` signed message due to recover the signer public key EC point in `Solidity`.
* @author cyphered.eth
*/
library Secp256k1 {
// Elliptic curve Constants
uint256 private constant U255_MAX_PLUS_1 =
57896044618658097711785492504343953926634992332820282019728792003956564819968;
// Curve Constants
uint256 private constant A = 0;
uint256 private constant B = 7;
uint256 private constant GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;
uint256 private constant GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;
uint256 private constant P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;
uint256 private constant N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
/// @dev recovers signer public key point value.
/// @param digest hashed message
/// @param v recovery
/// @param r first 32 bytes of signature
/// @param v last 32 bytes of signature
/// @return (x, y) EC point
function recover(
uint256 digest,
uint8 v,
uint256 r,
uint256 s
) internal pure returns (uint256, uint256) {
uint256 x = addmod(r, P * (v >> 1), P);
if (x > P || s > N || r > N || s == 0 || r == 0 || v > 1) {
return (0, 0);
}
uint256 rInv = invMod(r, N);
uint256 y2 = addmod(mulmod(x, mulmod(x, x, P), P), addmod(mulmod(x, A, P), B, P), P);
y2 = expMod(y2, (P + 1) / 4);
uint256 y = ((y2 + v + 2) & 1 == 0) ? y2 : P - y2;
(uint256 qx, uint256 qy, uint256 qz) = jacMul(mulmod(rInv, N - digest, N), GX, GY, 1);
(uint256 qx2, uint256 qy2, uint256 qz2) = jacMul(mulmod(rInv, s, N), x, y, 1);
(uint256 qx3, uint256 qy3) = ecAdd(qx, qy, qz, qx2, qy2, qz2);
return (qx3, qy3);
}
/// @dev Modular exponentiation, b^e % P.
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// Source: https://github.com/androlo/standard-contracts/blob/master/contracts/src/crypto/ECCMath.sol
/// @param _base base
/// @param _exp exponent
/// @return r such that r = b**e (mod P)
function expMod(uint256 _base, uint256 _exp) internal pure returns (uint256) {
if (_base == 0) return 0;
if (_exp == 0) return 1;
uint256 r = 1;
uint256 bit = U255_MAX_PLUS_1;
assembly {
for {
} gt(bit, 0) {
} {
r := mulmod(mulmod(r, r, P), exp(_base, iszero(iszero(and(_exp, bit)))), P)
r := mulmod(mulmod(r, r, P), exp(_base, iszero(iszero(and(_exp, div(bit, 2))))), P)
r := mulmod(mulmod(r, r, P), exp(_base, iszero(iszero(and(_exp, div(bit, 4))))), P)
r := mulmod(mulmod(r, r, P), exp(_base, iszero(iszero(and(_exp, div(bit, 8))))), P)
bit := div(bit, 16)
}
}
return r;
}
/// @dev Adds two points (x1, y1, z1) and (x2 y2, z2).
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _x1 coordinate x of P1
/// @param _y1 coordinate y of P1
/// @param _z1 coordinate z of P1
/// @param _x2 coordinate x of square
/// @param _y2 coordinate y of square
/// @param _z2 coordinate z of square
/// @return (qx, qy, qz) P1+square in Jacobian
function jacAdd(
uint256 _x1,
uint256 _y1,
uint256 _z1,
uint256 _x2,
uint256 _y2,
uint256 _z2
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
if (_x1 == 0 && _y1 == 0) return (_x2, _y2, _z2);
if (_x2 == 0 && _y2 == 0) return (_x1, _y1, _z1);
// We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
uint256[4] memory zs; // z1^2, z1^3, z2^2, z2^3
zs[0] = mulmod(_z1, _z1, P);
zs[1] = mulmod(_z1, zs[0], P);
zs[2] = mulmod(_z2, _z2, P);
zs[3] = mulmod(_z2, zs[2], P);
// u1, s1, u2, s2
zs = [mulmod(_x1, zs[2], P), mulmod(_y1, zs[3], P), mulmod(_x2, zs[0], P), mulmod(_y2, zs[1], P)];
// In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used
require(zs[0] != zs[2] || zs[1] != zs[3], 'Use jacDouble function instead');
uint256[4] memory hr;
//h
hr[0] = addmod(zs[2], P - zs[0], P);
//r
hr[1] = addmod(zs[3], P - zs[1], P);
//h^2
hr[2] = mulmod(hr[0], hr[0], P);
// h^3
hr[3] = mulmod(hr[2], hr[0], P);
// qx = -h^3 -2u1h^2+r^2
uint256 qx = addmod(mulmod(hr[1], hr[1], P), P - hr[3], P);
qx = addmod(qx, P - mulmod(2, mulmod(zs[0], hr[2], P), P), P);
// qy = -s1*z1*h^3+r(u1*h^2 -x^3)
uint256 qy = mulmod(hr[1], addmod(mulmod(zs[0], hr[2], P), P - qx, P), P);
qy = addmod(qy, P - mulmod(zs[1], hr[3], P), P);
// qz = h*z1*z2
uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, P), P);
return (qx, qy, qz);
}
/// @dev Multiply point (x, y, z) times d.
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _d scalar to multiply
/// @param _x coordinate x of P1
/// @param _y coordinate y of P1
/// @param _z coordinate z of P1
/// @return (qx, qy, qz) d*P1 in Jacobian
function jacMul(
uint256 _d,
uint256 _x,
uint256 _y,
uint256 _z
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
// Early return in case that `_d == 0`
if (_d == 0) {
return (_x, _y, _z);
}
uint256 remaining = _d;
uint256 qx = 0;
uint256 qy = 0;
uint256 qz = 1;
// Double and add algorithm
while (remaining != 0) {
if ((remaining & 1) != 0) {
(qx, qy, qz) = jacAdd(qx, qy, qz, _x, _y, _z);
}
remaining = remaining / 2;
(_x, _y, _z) = jacDouble(_x, _y, _z);
}
return (qx, qy, qz);
}
/// @dev Doubles a points (x, y, z).
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _x coordinate x of P1
/// @param _y coordinate y of P1
/// @param _z coordinate z of P1
/// @return (qx, qy, qz) 2P in Jacobian
function jacDouble(
uint256 _x,
uint256 _y,
uint256 _z
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
if (_z == 0) return (_x, _y, _z);
// We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
// Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4)
// x, y, z at this point represent the squares of _x, _y, _z
uint256 x = mulmod(_x, _x, P); //x1^2
uint256 y = mulmod(_y, _y, P); //y1^2
uint256 z = mulmod(_z, _z, P); //z1^2
// s
uint256 s = mulmod(4, mulmod(_x, y, P), P);
// m
uint256 m = addmod(mulmod(3, x, P), mulmod(A, mulmod(z, z, P), P), P);
// x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper
// This allows to reduce the gas cost and stack footprint of the algorithm
// qx
x = addmod(mulmod(m, m, P), P - addmod(s, s, P), P);
// qy = -8*y1^4 + M(S-T)
y = addmod(mulmod(m, addmod(s, P - x, P), P), P - mulmod(8, mulmod(y, y, P), P), P);
// qz = 2*y1*z1
z = mulmod(2, mulmod(_y, _z, P), P);
return (x, y, z);
}
/// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates.
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _x1 coordinate x of P1
/// @param _y1 coordinate y of P1
/// @param _x2 coordinate x of P2
/// @param _y2 coordinate y of P2
/// @return (qx, qy) = P1+P2 in affine coordinates
function ecAdd(
uint256 _x1,
uint256 _y1,
uint256 _z1,
uint256 _x2,
uint256 _y2,
uint256 _z2
) internal pure returns (uint256, uint256) {
uint256 x = 0;
uint256 y = 0;
uint256 z = 0;
// Double if x1==x2 else add
if (_x1 == _x2) {
// y1 = -y2 mod p
if (addmod(_y1, _y2, P) == 0) {
return (0, 0);
} else {
// P1 = P2
(x, y, z) = jacDouble(_x1, _y1, _z1);
}
} else {
(x, y, z) = jacAdd(_x1, _y1, _z1, _x2, _y2, _z2);
}
// Get back to affine
return toAffine(x, y, z);
}
/// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1).
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _x coordinate x
/// @param _y coordinate y
/// @param _z coordinate z
/// @return (x', y') affine coordinates
function toAffine(
uint256 _x,
uint256 _y,
uint256 _z
) internal pure returns (uint256, uint256) {
uint256 zInv = invMod(_z, P);
uint256 zInv2 = mulmod(zInv, zInv, P);
uint256 x2 = mulmod(_x, zInv2, P);
uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, P), P);
return (x2, y2);
}
/// @dev Modular euclidean inverse of a number (mod p).
/// Source: https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
/// @param _x The number
/// @param _pp The modulus
/// @return q such that x*q = 1 (mod _pp)
function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) {
require(_x != 0 && _x != _pp && _pp != 0, 'Invalid number');
uint256 q = 0;
uint256 newT = 1;
uint256 r = _pp;
uint256 t;
while (_x != 0) {
t = r / _x;
(q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp));
(r, _x) = (_x, r - t * _x);
}
return q;
}
}// SPDX-License-Identifier: MIT
// Stratonet Contracts (last updated v1.0.0) (utils/Bech32.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the Bech32 address generation
*/
library Bech32 {
bytes constant ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
bytes constant ALPHABET_REV = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0fff0a1115141a1e0705ffffffffffffff1dff180d19090817ff12161f1b13ff010003100b1c0c0e060402ffffffffffff1dff180d19090817ff12161f1b13ff010003100b1c0c0e060402ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
bytes constant ALPHABET_REV_LOWER_ONLY = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0fff0a1115141a1e0705ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1dff180d19090817ff12161f1b13ff010003100b1c0c0e060402ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
// 0f <= 0: 48 | 30
// 0a <= 2: 50 | 32
// 11 <= 3: 51 | 33
// 15 <= 4: 52 | 34
// 14 <= 5: 53 | 35
// 1a <= 6: 54 | 36
// 1e <= 7: 55 | 37
// 07 <= 8: 56 | 38
// 05 <= 9: 57 | 39
// 1d <= a: 97, 65 | 61, 41
// 18 <= c: 99, 67 | 63, 43
// 0d <= d: 100, 68 | 64, 44
// 19 <= e: 101, 69 | 65, 45
// 09 <= f: 102, 70 | 66, 46
// 08 <= g: 103, 71 | 67, 47
// 17 <= h: 104, 72 | 68, 48
// 12 <= j: 106, 74 | 6A, 4A
// 16 <= k: 107, 75 | 6B, 4B
// 1f <= l: 108, 76 | 6C, 4C
// 1b <= m: 109, 77 | 6D, 4D
// 13 <= n: 110, 78 | 6E, 4E
// 01 <= p: 112, 80 | 70, 50
// 00 <= q: 113, 81 | 71, 51
// 03 <= r: 114, 82 | 72, 52
// 10 <= s: 115, 83 | 73, 53
// 0b <= t: 116, 84 | 74, 54
// 1c <= u: 117, 85 | 75, 55
// 0c <= v: 118, 86 | 76, 56
// 0e <= w: 119, 87 | 77, 57
// 06 <= x: 120, 88 | 78, 58
// 04 <= y: 121, 89 | 79, 59
// 02 <= z: 122, 90 | 7A, 5A
uint32 constant ENC_BECH32 = 1;
uint32 constant ENC_BECH32M = 0x2bc830a3;
function toBech32(
address addr,
string memory prefix
) internal pure returns (string memory) {
return toBech32(abi.encodePacked(addr), prefix);
}
function toBech32(
bytes memory data,
string memory prefix
) internal pure returns (string memory) {
bytes memory hrp = abi.encodePacked(prefix);
bytes memory input = convertBits(data, 8, 5, true);
return encode(hrp, input, ENC_BECH32);
}
function toBech32(
address addr,
string memory prefix,
uint8 version
) internal pure returns (string memory) {
return toBech32(abi.encodePacked(addr), prefix, version);
}
function toBech32(
bytes memory data,
string memory prefix,
uint8 version
) internal pure returns (string memory) {
bytes memory hrp = abi.encodePacked(prefix);
bytes memory input = convertBits(data, 8, 5, true);
uint32 enc = ENC_BECH32;
if (version > 0) {
enc = ENC_BECH32M;
}
bytes memory inputWithV = abi.encodePacked(bytes1(version), input);
return encode(hrp, inputWithV, enc);
}
function fromBech32(
string memory bechAddr
) internal pure returns (address) {
(, uint8[] memory data) = decode(
abi.encodePacked(bechAddr),
ENC_BECH32
);
bytes memory input = convertBits(data, 5, 8, false);
return getAddressFromBytes(input);
}
function fromBech32(
string memory bechAddr,
string memory prefix
) internal pure returns (address) {
(bytes memory dHrp, uint8[] memory data) = decode(
abi.encodePacked(bechAddr),
ENC_BECH32
);
_requireHrpMatch(abi.encodePacked(prefix), dHrp);
bytes memory input = convertBits(data, 5, 8, false);
return getAddressFromBytes(input);
}
function fromBech32WithVersion(
string memory bechAddr,
string memory prefix,
uint32 enc
) internal pure returns (uint8, bytes memory) {
(bytes memory dHrp, uint8[] memory data) = decode(
abi.encodePacked(bechAddr),
enc
);
_requireHrpMatch(abi.encodePacked(prefix), dHrp);
require(!(data.length < 1 || data[0] > 16), "Bech32: wrong version");
uint8[] memory dataNoV = new uint8[](data.length - 1);
for (uint8 i = 1; i < data.length; ++i) {
dataNoV[i - 1] = data[i];
}
bytes memory input = convertBits(dataNoV, 5, 8, false);
require(
input.length >= 2 && input.length <= 40,
"Bech32: wrong bits length"
);
require(
!(data[0] == 0 && input.length != 20 && input.length != 32),
"Bech32: wrong bits length for version"
);
return (uint8(data[0]), input);
}
function _requireHrpMatch(
bytes memory hrp1,
bytes memory hrp2
) internal pure {
require(keccak256(hrp1) == keccak256(hrp2), "Bech32: hrp mismatch");
}
function getAddressFromBytes(
bytes memory data
) internal pure returns (address) {
require(data.length == 20, "Bech32: invalid data length");
address addr;
assembly {
addr := mload(add(data, 20))
}
return addr;
}
function encode(
bytes memory hrp,
bytes memory input,
uint32 enc
) internal pure returns (string memory) {
unchecked {
uint8[] memory checksum = createChecksum(hrp, input, enc);
bytes memory result = new bytes(hrp.length + input.length + checksum.length + 1);
for (uint i; i < hrp.length; ++ i) {
result[i] = hrp[i];
}
result[hrp.length] = bytes1("1");
uint offset = hrp.length + 1;
for (uint i; i < input.length; ++ i) {
uint8 _data = uint8(input[i]);
if (_data < ALPHABET.length) {
result[i + offset] = ALPHABET[_data];
}
}
offset += input.length;
for (uint i; i < checksum.length; ++ i) {
uint8 _data = uint8(checksum[i]);
if (_data < ALPHABET.length) {
result[i + offset] = ALPHABET[_data];
}
}
return string(result);
}
}
function decode(bytes memory bechStr, uint32 enc)
internal pure
returns (bytes memory hrp, uint8[] memory data)
{
unchecked {
uint pos;
require(
bechStr.length <= 90,
"Bech32: invalid string length"
);
for (uint p = 0; p < bechStr.length; ++ p) {
uint8 charAt = uint8(bechStr[p]);
require(
charAt >= 33
&& charAt <= 126,
"Bech32: wrong char"
);
if (charAt == uint8(bytes1("1"))) {
require(
pos == 0
&& p >= 1
&& p + 7 <= bechStr.length,
"Bech32: wrong pos of 1"
);
pos = p;
}
}
hrp = new bytes(pos);
for (uint i; i < pos; ++ i) {
hrp[i] = bechStr[i];
}
data = new uint8[](bechStr.length - pos - 1);
for (uint i; i < data.length; ++ i) {
bytes1 charAt = ALPHABET_REV_LOWER_ONLY[uint8(bechStr[i + pos + 1])];
require(charAt != 0xff, "Bech32: byte not in alphabet");
data[i] = uint8(charAt);
}
require(
verifyChecksum(hrp, data, enc),
"Bech32: wrong checksum"
);
uint dataLength = data.length - 6;
assembly {
mstore(data, dataLength)
}
}
}
function hrpExpand(
bytes memory hrp
) internal pure returns (uint8[] memory ret) {
unchecked {
ret = new uint8[](hrp.length + hrp.length + 1);
for (uint p; p < hrp.length; ++ p) {
ret[p] = uint8(hrp[p]) >> 5;
ret[p + hrp.length + 1] = uint8(hrp[p]) & 31;
}
}
}
function polymod(uint32[] memory values) internal pure returns (uint32) {
uint32 chk = 1;
uint32[5] memory GEN = [
0x3b6a57b2,
0x26508e6d,
0x1ea119fa,
0x3d4233dd,
0x2a1462b3
];
unchecked {
for (uint32 i = 0; i < values.length; ++i) {
uint32 top = chk >> 25;
chk = (uint32(chk & 0x1ffffff) << 5) ^ uint32(values[i]);
for (uint32 j = 0; j < 5; ++j) {
if (((top >> j) & 1) == 1) {
chk ^= GEN[j];
}
}
}
}
return chk;
}
function createChecksum(
bytes memory hrp,
bytes memory data,
uint32 enc
) internal pure returns (uint8[] memory res) {
unchecked {
uint8[] memory values = hrpExpand(hrp);
uint32[] memory comb = new uint32[](values.length + data.length + 6);
for (uint i; i < values.length + data.length; ++ i) {
if (i < values.length) {
comb[i] = uint32(values[i]);
} else {
comb[i] = uint32(uint8(data[i - values.length]));
}
}
res = new uint8[](6);
uint32 mod = polymod(comb) ^ enc;
for (uint p = 0; p < 6; ++ p) {
res[p] = uint8((mod >> (5 * (5 - p))) & 31);
}
}
}
function verifyChecksum(
bytes memory hrp,
uint8[] memory data,
uint32 enc
) internal pure returns (bool) {
unchecked {
uint8[] memory ehrp = hrpExpand(hrp);
uint32[] memory cData = new uint32[](ehrp.length + data.length);
for (uint i; i < ehrp.length; ++ i) {
cData[i] = uint32(ehrp[i]);
}
for (uint i; i < data.length; ++ i) {
cData[i + ehrp.length] = uint32(data[i]);
}
return polymod(cData) == enc;
}
}
function convertBits(
bytes memory data,
uint frombits,
uint tobits,
bool pad
) internal pure returns (bytes memory) {
uint8[] memory dataBits = new uint8[](data.length);
for (uint32 p = 0; p < dataBits.length; ++p) {
dataBits[p] = uint8(data[p]);
}
return _convertBits(dataBits, frombits, tobits, pad);
}
function convertBits(
uint8[] memory data,
uint frombits,
uint tobits,
bool pad
) internal pure returns (bytes memory) {
return _convertBits(data, frombits, tobits, pad);
}
function _convertBits(
uint8[] memory dataBits,
uint frombits,
uint tobits,
bool pad
) internal pure returns (bytes memory ret) {
uint acc = 0;
uint bits = 0;
uint maxv = (1 << tobits) - 1;
unchecked {
for (uint p; p < dataBits.length; ++p) {
uint8 value = dataBits[p];
require(
value >= 0 && (value >> frombits) == 0,
"Bech32: value must be non-negative and fit in frombits"
);
acc = (acc << frombits) | value;
bits += frombits;
while (bits >= tobits) {
bits -= tobits;
ret = abi.encodePacked(
ret,
bytes1(uint8((acc >> bits) & maxv))
);
}
}
}
if (pad) {
if (bits > 0) {
ret = abi.encodePacked(
ret,
bytes1(uint8((acc << (tobits - bits)) & maxv))
);
}
} else {
require(
bits < frombits || ((acc << (tobits - bits)) & maxv) == 0,
"Bech32: invalid padding or value size"
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
interface IWitPriceFeedsLegacySolverFactory {
event NewPriceFeedsSolver(address solver, bytes32 codehash, bytes constructorParams);
function deployPriceSolver(bytes calldata initcode, bytes calldata additionalParams) external returns (address);
function determinePriceSolverAddress(bytes calldata initcode, bytes calldata additionalParams) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../../libs/Witnet.sol";
interface IWitPriceFeedsLegacySolver {
enum LatestUpdateStatus {
Void,
Awaiting,
Ready,
Error
}
struct Price {
uint64 value;
Witnet.Timestamp timestamp;
Witnet.TransactionHash drTxHash;
LatestUpdateStatus latestStatus;
}
function class() external pure returns (string memory);
function delegator() external view returns (address);
function solve(bytes4 feedId) external view returns (Price memory);
function specs() external pure returns (bytes4);
function validate(bytes4 feedId, string[] calldata initdata) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../../libs/Witnet.sol";
import "./IWitOracleRequest.sol";
import "./IWitOracleRequestTemplate.sol";
import "./IWitPriceFeedsLegacy.sol";
interface IWitPriceFeedsLegacyAdmin {
event WitFeedDeleted(string caption, bytes4 feedId);
event WitFeedSettled(string caption, bytes4 feedId, bytes32 radHash);
event WitFeedSolverSettled(string caption, bytes4 feedId, address solver);
function acceptOwnership() external;
function baseFeeOverheadPercentage() external view returns (uint16);
function deleteFeed(string calldata caption) external;
function deleteFeeds() external;
function owner() external view returns (address);
function pendingOwner() external returns (address);
function settleBaseFeeOverheadPercentage(uint16) external;
function settleDefaultRadonSLA(IWitPriceFeedsLegacy.RadonSLAv2 calldata) external;
function settleFeedRequest(string calldata caption, bytes32 radHash) external;
function settleFeedRequest(string calldata caption, IWitOracleRequest request) external;
function settleFeedRequest(string calldata caption, IWitOracleRequestTemplate 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 "./IWitOracleLegacy.sol";
import "./IWitPriceFeedsLegacySolver.sol";
interface IWitPriceFeedsLegacy {
/// A fresh update on the data feed identified as `erc2364Id4` has just been
/// requested and paid for by some `evmSender`, under command of the
/// `evmOrigin` externally owned account.
event PullingUpdate(
address evmOrigin,
address evmSender,
bytes4 erc2362Id4,
uint256 witOracleQueryId
);
struct RadonSLAv1 {
uint8 numWitnesses;
uint8 minConsensusPercentage;
uint64 witnessReward;
uint64 witnessCollateral;
uint64 minerCommitRevealFee;
}
struct RadonSLAv2 {
uint8 numWitnesses;
uint64 unitaryReward;
}
/// Primitive data type produced by successful data updates of all supported
/// feeds (e.g. Witnet.RadonDataTypes.Integer in WitPriceFeeds).
function dataType() external view returns (Witnet.RadonDataTypes);
function defaultRadonSLA() external view returns (RadonSLAv1 memory);
function estimateUpdateBaseFee(uint256 evmGasPrice) external view returns (uint);
/// Returns a unique hash determined by the combination of data sources being used by
/// supported non-routed price feeds, and dependencies of all supported routed
/// price feeds. The footprint changes if any price feed is modified, added, removed
/// or if the dependency tree of any routed price feed is altered.
function footprint() external view returns (bytes4);
/// This pure function determines the ERC-2362 identifier of the given data feed
/// caption string, truncated to bytes4.
function hash(string calldata caption) external pure returns (bytes4);
/// Returns the query id (in the context of the WitOracle addressed by witOracle())
/// that solved the most recently updated value for the given feed.
function lastValidQueryId(bytes4 feedId) external view returns (uint256);
/// Returns the actual response from the Witnet oracle blockchain to the last
/// successful update for the given data feed.
function lastValidQueryResponse(bytes4 feedId) external view returns (Witnet.QueryResponse memory);
function latestPrice(bytes4 feedId) external view returns (IWitPriceFeedsLegacySolver.Price memory);
function latestPrices(bytes4[] calldata feedIds) external view returns (IWitPriceFeedsLegacySolver.Price[] memory);
/// Returns the Witnet query id of the latest update attempt for the given data feed.
function latestUpdateQueryId(bytes4 feedId) external view returns (uint256);
/// Returns the actual request queried to the the Witnet oracle blockchain on the latest
/// update attempt for the given data feed.
function latestUpdateQueryRequest(bytes4 feedId) external view returns (Witnet.QueryRequest memory);
function latestUpdateResponse(bytes4 feedId) external view returns (Witnet.QueryResponse memory);
function latestUpdateResponseStatus(bytes4 feedId) external view returns (IWitOracleLegacy.QueryResponseStatus);
function latestUpdateResultError(bytes4 feedId) external view returns (IWitOracleLegacy.ResultError memory);
/// Returns the ERC-2362 caption of the given feed identifier, if known.
function lookupCaption(bytes4) external view returns (string memory);
function lookupDecimals(bytes4 feedId) external view returns (uint8);
function lookupPriceSolver(bytes4 feedId) external view returns (
address solverAddress,
string[] memory solverDeps
);
function lookupWitnetBytecode(bytes4) external view returns (bytes memory);
function lookupWitnetRadHash(bytes4) external view returns (bytes32);
function lookupWitnetRetrievals(bytes4) external view returns (Witnet.RadonRetrieval[] memory);
/// ERC-2362 caption prefix shared by all supported feeds (e.g. "Price-" in WitPriceFeeds).
function prefix() external view returns (string memory);
/// Triggers a fresh update on the Witnet oracle blockchain for the given data feed,
/// using the defaultRadonSLA() security parameters.
function requestUpdate(bytes4 feedId) external payable returns (uint256 usedFunds);
function requestUpdate(bytes4, RadonSLAv2 calldata) external payable returns (uint256 usedFunds);
/// Returns the list of feed ERC-2362 ids, captions and RAD hashes of all currently supported
/// data feeds. The RAD hash of a data feed determines in a verifiable way the actual data sources
/// and off-chain computations solved by the Witnet oracle blockchain upon every data update.
/// The RAD hash value for a routed feed actually contains the address of the IWitnetPriceSolver
/// logic contract that solves it.
function supportedFeeds() external view returns (bytes4[] memory, string[] memory, bytes32[] memory);
/// Tells whether the given ERC-2362 feed caption is currently supported.
function supportsCaption(string calldata) external view returns (bool);
/// Total number of data feeds, routed or not, that are currently supported.
function totalFeeds() external view returns (uint256);
function witnet() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./IWitOracleRequest.sol";
interface IWitOracleRequestTemplate {
/// Builds a WitOracleRequest instance that will provide the bytecode and RAD
/// hash of some Witnet-compliant Radon Request, provably made out of the
/// data sources, aggregate and tally Radon Reducers that compose this instance.
/// Reverts if the ranks of passed array don't match either the number of this template's
/// data sources, or the number of required parameters by each one of those.
/// @dev Produced addresses are counter-factual to the template address and the given values.
function buildWitOracleRequest (string[][] calldata args) external returns (IWitOracleRequest);
/// Builds a WitOracleRequest instance by specifying one single parameter value
/// that will be equally applied to all the template's data sources.
/// Reverts if any of the underlying data sources requires more than just one parameter.
/// @dev Produced addresses are counter-factual to the template address and the given value.
function buildWitOracleRequest (string calldata singleArgValue) external returns (IWitOracleRequest);
/// Returns an array of integers telling the number of parameters required
/// by every single data source (i.e. Radon Retrievals) that compose this
/// WitOracleRequestTemplate. The length of the returned array tells the number
/// of data sources that compose this instance.
function getArgsCount() external view returns (uint256[] memory);
/// Returns the filters and reducing functions to be applied by witnessing nodes
/// on the Witnet blockchain both at the:
/// - Aggregate stage: when aggregating data extracted from the public
/// data sources (i.e. Radon Retrievals).
/// - Tally stage: when aggregating values revealed by witnesses.
function getRadonReducers() external view returns (
Witnet.RadonReducer memory aggregateStage,
Witnet.RadonReducer memory tallyStage
);
/// Returns metadata concerning the data source specified by the given index.
function getRadonRetrievalByIndex(uint256) external view returns (Witnet.RadonRetrieval memory);
/// Returns the array of one or more parameterized data sources that compose
/// this WitOracleRequestTemplate.
function getRadonRetrievals() external view returns (Witnet.RadonRetrieval[] memory);
/// Returns the expected data type produced by successful resolutions of
/// any WitOracleRequest that gets built out of this WitOracleRequestTemplate.
function getResultDataType() external view returns (Witnet.RadonDataTypes);
/// Verifies into the bounded WitOracle's registry the actual bytecode
/// and RAD hash of the Witnet-compliant Radon Request that gets provably
/// made out of the data sources, aggregate and tally Radon Reducers that
/// compose this WitOracleRequestTemplate. While no WitOracleRequest instance is
/// actually constructed, the returned value will be accepted as a valid
/// RAD hash on the witOracle() contract from now on.
/// Reverts if:
/// - the ranks of passed array don't match either the number of this
/// template's data sources, or the number of required parameters by
/// each one of those.
/// @dev This method requires less gas than buildWitOracleRequest(string[][]), and
/// @dev it's usually preferred when data requests built out of this template
/// @dev are intended to be used just once in lifetime.
function verifyRadonRequest(string[][] calldata args) external returns (Witnet.RadonHash);
/// Verifies into the bounded WitOracle's registry the actual bytecode
/// and RAD hash of the Witnet-compliant Radon Request that gets provably
/// made out as a result of applying the given parameter value to the underlying
/// data sources, aggregate and tally reducers that compose this template.
/// While no actual WitOracleRequest instance gets constructed, the returned value
/// will be accepted as a valid RAD hash on the bounded WitOracle contract from now on.
/// Reverts if any of the underlying data sources requires more than just one parameter.
/// @dev This method requires less gas than buildWitOracleRequest(string), and
/// @dev it's usually preferred when data requests built out of this template
/// @dev are intended to be used just once in lifetime.
function verifyRadonRequest(string calldata singleArgValue) external returns (Witnet.RadonHash);
/// If built out of an upgradable factory, returns the SemVer tag of the
/// factory implementation at the time when this WitOracleRequestTemplate got built.
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../../libs/Witnet.sol";
interface IWitOracleRequest {
/// Returns the Witnet-compliant RAD bytecode for the data request (i.e. Radon Request)
/// contained within this WitOracleRequest.
function bytecode() external view returns (bytes memory);
/// Returns the Witnet-compliant RAD hash of the data request (i.e. Radon Request)
/// contained within this WitOracleRequest.
function radHash() external view returns (Witnet.RadonHash);
/// Returns the filters and reducing functions to be applied by witnessing nodes
/// on the Witnet blockchain both at the:
/// - Aggregate stage: when aggregating data extracted from the public
/// data sources (i.e. Radon Retrievals).
/// - Tally stage: when aggregating values revealed by witnesses.
function getRadonReducers() external view returns (
Witnet.RadonReducer memory aggregateStage,
Witnet.RadonReducer memory tallyStage
);
/// Returns metadata concerning the data source specified by the given index.
function getRadonRetrievalByIndex(uint256) external view returns (Witnet.RadonRetrieval memory);
/// Returns the array of one or more data sources (i.e. Radon Retrievals)
/// that compose this WitOracleRequest.
function getRadonRetrievals() external view returns (Witnet.RadonRetrieval[] memory);
/// Returns the expected data type produced by successful resolutions of the
/// Witnet-compliant data request contained within this WitOracleRequest.
function getResultDataType() external view returns (Witnet.RadonDataTypes);
/// If built out of an upgradable factory, or template, returns the SemVer tag of
/// the actual implementation version at the time when this WitOracleRequest got built.
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../IWitOracleRadonRegistry.sol";
interface IWitOracleLegacy {
struct Query {
QueryRequest request;
QueryResponse response;
}
struct QueryRequest {
address requester;
uint24 callbackGas;
uint72 evmReward;
bytes radonBytecode;
bytes32 radonHash;
RadonSLA radonParams;
}
struct QueryResponse {
address reporter;
uint64 finality;
uint32 timestamp;
bytes32 trail;
bytes cborBytes;
}
struct RadonSLA {
uint8 numWitnesses;
uint64 witnessReward;
}
event WitnetQuery(uint256 id, uint256 evmReward, RadonSLA witnetSLA);
/// @notice Estimate the minimum reward required for posting a data request.
/// @dev Underestimates if the size of returned data is greater than `resultMaxSize`.
/// @param gasPrice Expected gas price to pay upon posting the data request.
/// @param resultMaxSize Maximum expected size of returned data (in bytes).
function estimateBaseFee(uint256 gasPrice, uint16 resultMaxSize) external view returns (uint256);
/// @notice Estimate the minimum reward required for posting a data request.
/// @dev Fails if the RAD hash was not previously verified on the WitOracleRadonRegistry registry.
/// @param gasPrice Expected gas price to pay upon posting the data request.
/// @param radHash The RAD hash of the data request to be solved by Witnet.
function estimateBaseFee(uint256 gasPrice, bytes32 radHash) external view returns (uint256);
function getQuery(uint256) external view returns (Query memory);
function getQueryRequest(uint256) external view returns (QueryRequest memory);
function getQueryResponse(uint256) external view returns (QueryResponse 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.
/// @notice - 4 => Finalizing: some result to the query has been reported, but cannot yet be considered finalized.
/// @notice - 5 => Delivered: at least one response, either successful or with errors, was delivered to the requesting contract.
function getQueryResponseStatus(uint256) external view returns (QueryResponseStatus);
/// QueryResponse status from a requester's point of view.
enum QueryResponseStatus {
Void,
Awaiting,
Ready,
Error,
Finalizing,
Delivered,
Expired
}
/// @notice Retrieves the CBOR-encoded buffer containing the Witnet-provided result to the given query.
function getQueryResultCborBytes(uint256) external view returns (bytes memory);
/// @notice Gets error code identifying some possible failure on the resolution of the given query.
function getQueryResultError(uint256) external view returns (ResultError memory);
/// Data struct describing an error when trying to fetch a Witnet-provided result to a Data Request.
struct ResultError {
uint8 code;
string reason;
}
function extractWitnetDataRequests(uint256[] calldata queryIds) external view returns (bytes[] memory);
function fetchQueryResponse(uint256 queryId) external returns (bytes memory);
function postRequest(bytes32, RadonSLA calldata) external payable returns (uint256);
function postRequestWithCallback(bytes32, RadonSLA calldata, uint24) external payable returns (uint256);
function reportResult(uint256, uint32, bytes32, bytes calldata) external returns (uint256);
function reportResult(uint256, bytes32, bytes calldata) external returns (uint256);
struct BatchResultLegacy {
uint256 queryId;
uint32 resultTimestamp;
bytes32 drTxHash;
bytes resultCborBytes;
}
function reportResultBatch(BatchResultLegacy[] calldata) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../libs/Witnet.sol";
interface IWitOracleRadonRegistry {
/// @notice Returns the Witnet-compliant DRO bytecode for some data request object
/// made out of the given Radon Request and Radon SLA security parameters.
function bytecodeOf(
Witnet.RadonHash radonRequestHash,
Witnet.QuerySLA calldata queryParams
) external view returns (bytes memory);
/// @notice Returns the Witnet-compliant DRO bytecode for some data request object
/// made out of the given RAD bytecode and Radon SLA security parameters.
function bytecodeOf(
bytes calldata radonRequestBytecode,
Witnet.QuerySLA calldata queryParams
) external view returns (bytes memory);
/// @notice Returns the hash of the given Witnet-compliant bytecode. Returned value
/// can be used to trace back in the Witnet blockchain all past resolutions
/// of the given data request payload.
function hashOf(bytes calldata) external view returns (Witnet.RadonHash);
/// @notice Tells whether the specified Radon Reducer has been formally verified into the registry.
function isVerifiedRadonReducer(bytes32) external view returns (bool);
/// @notice Tells whether the given Radon Hash has been formally verified into the registry.
function isVerifiedRadonRequest(Witnet.RadonHash) external view returns (bool);
/// @notice Tells whether the specified Radon Retrieval has been formally verified into the registry.
function isVerifiedRadonRetrieval(bytes32) external view returns (bool);
/// @notice Returns the whole Witnet.RadonReducer metadata struct for the given hash.
/// @dev Reverts if unknown.
function lookupRadonReducer(bytes32 hash) external view returns (Witnet.RadonReducer memory);
// /// @notice Returns the whole Witnet.RadonRequest metadata struct for the given RAD hash value.
// /// @dev Reverts if unknown.
// function lookupRadonRequest(Witnet.RadonHash radonRequestHash) external view returns (Witnet.RadonRequest memory);
/// @notice Returns the Witnet-compliant RAD bytecode for some Radon Request
/// identified by its unique RAD hash.
function lookupRadonRequestBytecode(Witnet.RadonHash radonRequestHash) external view returns (bytes memory);
/// @notice Returns the Tally reducer that is applied to aggregated values revealed by the witnessing nodes on the
/// Witnet blockchain.
/// @dev Reverts if unknown.
function lookupRadonRequestCrowdAttestationTally(Witnet.RadonHash radonRequestHash) external view returns (Witnet.RadonReducer memory);
/// @notice Returns the deterministic data type returned by successful resolutions of the given Radon Request.
/// @dev Reverts if unknown.
function lookupRadonRequestResultDataType(Witnet.RadonHash radonRequestHash) external view returns (Witnet.RadonDataTypes);
/// @notice Returns introspective metadata for the index-th data source of some pre-verified Radon Request.
/// @dev Reverts if out of range.
// function lookupRadonRequestRetrievalByIndex(Witnet.RadonHash radonRequestHash, uint256 index) external view returns (Witnet.RadonRetrieval memory);
/// @notice Returns an array (one or more items) containing the introspective metadata of the given Radon Request's
/// data sources (i.e. Radon Retrievals).
/// @dev Reverts if unknown.
function lookupRadonRequestRetrievals(Witnet.RadonHash radonRequestHash) external view returns (Witnet.RadonRetrieval[] memory);
/// @notice Returns the Aggregate reducer that is applied to the data extracted from the data sources
/// (i.e. Radon Retrievals) whenever the given Radon Request gets solved on the Witnet blockchain.
/// @dev Reverts if unknown.
function lookupRadonRequestRetrievalsAggregator(Witnet.RadonHash radonRequestHash) external view returns (Witnet.RadonReducer memory);
function lookupRadonRequestRetrievalsCount(Witnet.RadonHash radonRequestHash) external view returns (uint8);
/// @notice Returns introspective metadata of some previously verified Radon Retrieval (i.e. public data source).
///@dev Reverts if unknown.
function lookupRadonRetrieval(bytes32 hash) external view returns (Witnet.RadonRetrieval memory);
/// @notice Returns the number of indexed parameters required to be fulfilled when
/// eventually using the given Radon Retrieval.
/// @dev Reverts if unknown.
function lookupRadonRetrievalArgsCount(bytes32 hash) external view returns (uint8);
/// @notice Returns the type of the data that would be retrieved by the given Radon Retrieval
/// (i.e. public data source).
/// @dev Reverts if unknown.
function lookupRadonRetrievalResultDataType(bytes32 hash) external view returns (Witnet.RadonDataTypes);
/// @notice Verifies and registers the given sequence of dataset filters and reducing function to be
/// potentially used as either Aggregate or Tally reducers within the resolution workflow
/// of Radon Requests in the Wit/Oracle blockchain. Returns a unique hash that identifies the
/// given Radon Reducer in the registry.
/// @dev Reverts if unsupported reducing or filtering methods are specified.
function verifyRadonReducer(Witnet.RadonReducer calldata reducer) external returns (bytes32 hash);
/// @notice Verifies and registers the specified Radon Request out of the given data sources (i.e. retrievals)
/// and the aggregate and tally Radon Reducers. Returns a unique RAD hash that identifies the
/// verified Radon Request.
/// @dev Reverts if:
/// - unverified retrievals are passed;
/// - retrievals return different data types;
/// - any of passed retrievals is parameterized;
/// - unsupported reducers are passed.
function verifyRadonRequest(
bytes32[] calldata radonRetrieveHashes,
Witnet.RadonReducer calldata dataSourcesAggregator,
Witnet.RadonReducer calldata crowsAttestationTally
) external returns (Witnet.RadonHash radonRequestHash);
/// @notice Verifies and registers the specified Radon Request out of the given data sources (i.e. retrievals),
/// data sources parameters (if required), and some pre-verified aggregate and tally Radon Reducers.
/// Returns a unique RAD hash that identifies the verified Radon Request.
/// @dev Reverts if:
/// - unverified retrievals are passed;
/// - retrievals return different data types;
/// - ranks of passed args don't match with those required by each given retrieval;
/// - unverified reducers are passed.
function verifyRadonRequest(
bytes32[] calldata retrieveHashes,
bytes32 aggregateReducerHash,
bytes32 tallyReducerHash
) external returns (Witnet.RadonHash radonRequestHash);
/// @notice Verifies and registers the specified Radon Request out of the given data sources (i.e. retrievals),
/// data sources parameters (if required), and the aggregate and tally Radon Reducers. Returns a unique
/// RAD hash that identifies the verified Radon Request.
/// @dev Reverts if:
/// - unverified retrievals are passed;
/// - retrievals return different data types;
/// - ranks of passed args don't match with those required by each given retrieval;
/// - unsupported reducers are passed.
function verifyRadonRequest(
bytes32[] calldata radonRetrieveHashes,
string[][] calldata radonRetrieveArgs,
Witnet.RadonReducer calldata dataSourcesAggregator,
Witnet.RadonReducer calldata crowdAttestationTally
) external returns (Witnet.RadonHash radonRequestHash);
/// @notice Verifies and registers the specified Radon Request out of a single modal retrieval where first
/// parameter corresponds to data provider's URL, an array of data providers (i.e. URLs), and an array
/// of parmeter values common to all data providers. Some pre-verified aggregate and tally Radon Reducers
/// must also be provided. Returns a unique RAD hash that identifies the verified Radon Request.
/// @dev Reverts if:
/// - unverified retrieval is passed;
/// - ranks of passed args don't match with those expected by given retrieval, after replacing the data provider URL.
/// - unverified reducers are passed.
function verifyRadonRequest(
bytes32[] calldata radonRetrieveHashes,
string[][] calldata radonRetrieveArgs,
bytes32 dataSourcesAggregatorHash,
bytes32 crowdAttestationTallyHash
) external returns (Witnet.RadonHash radonRequestHash);
function verifyRadonRequest(
bytes32 commonRetrieveHash,
string[] calldata commonRetrieveArgs,
string[] calldata dataProviders,
bytes32 dataSourcesAggregatorHash,
bytes32 crowdAttestationTallyHash
) external returns (Witnet.RadonHash radonRequestHash);
/// @notice Verifies and registers the specified Radon Retrieval (i.e. public data source) into this registry contract.
/// Returns a unique retrieval hash that identifies the verified Radon Retrieval.
/// All parameters but the retrieval method are parameterizable by using embedded wildcard \x\ substrings (with x='0'..'9').
/// @dev Reverts if:
/// - unsupported retrieval method is given;
/// - no URL is provided Http/* requests;
/// - non-empty strings given on RNG reqs.
function verifyRadonRetrieval(
Witnet.RadonRetrievalMethods requestMethod,
string calldata requestURL,
string calldata requestBody,
string[2][] calldata requestHeaders,
bytes calldata requestRadonScript
) external returns (bytes32 hash);
// /// Verifies a new Radon Retrieval by specifying the value to the highest indexed parameter of an already existing one.
// /// Returns the unique hash that identifies the resulting Radon Retrieval.
// /// Reverts if an unverified retrieval hash is passed.
// function verifyRadonRetrieval(
// bytes32 retrieveHash,
// string calldata lastArgValue
// ) external returns (bytes32 hash);
// }
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../libs/Witnet.sol";
interface IWitOracleQueriableEvents {
/// Emitted every time a new query containing some verified data request is posted to the WitOracle.
event WitOracleQuery(
address indexed evmRequester,
uint256 evmGasPrice,
uint256 evmReward,
Witnet.QueryId queryId,
Witnet.RadonHash radonHash,
Witnet.QuerySLA radonParams
);
/// Emitted when the reward of some not-yet reported query gets upgraded.
event WitOracleQueryUpgrade(
Witnet.QueryId queryId,
address evmSender,
uint256 evmGasPrice,
uint256 evmReward
);
/// Emitted when a query with no callback gets reported into the WRB.
event WitOracleQueryReport(
Witnet.QueryId queryId,
uint256 evmGasPrice
);
event WitOracleQueryReportDispute(
Witnet.QueryId queryId,
address evmDisputer
);
/// Emitted when a query with a callback gets successfully reported into the WRB.
event WitOracleQueryReportDelivery(
Witnet.QueryId queryId,
address evmConsumer,
uint256 evmGasPrice,
uint256 evmCallbackGas
);
/// Emitted when a query with a callback cannot get reported into the WRB.
event WitOracleResportDeliveryFailed(
Witnet.QueryId queryId,
address evmConsumer,
uint256 evmGasPrice,
uint256 evmCallbackActualGas,
string evmCallbackRevertReason,
bytes resultCborBytes
);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../libs/Witnet.sol";
interface IWitOracleQueriable {
/// @notice Removes all query data from storage. Pays back reward on expired queries.
/// @dev Fails if the query is not in a final status, or not called from the actual requester.
/// @param queryId The unique query identifier.
function deleteQuery(uint256 queryId) external returns (Witnet.QueryEvmReward);
/// @notice Estimate the minimum reward required for posting a data request.
/// @param evmGasPrice Expected gas price to pay upon posting the data request.
function estimateBaseFee(uint256 evmGasPrice) external view returns (uint256);
/// @notice Estimate the minimum reward required for posting a data request with a callback.
/// @param evmGasPrice Expected gas price to pay upon posting the data request.
/// @param callbackGas Maximum gas to be spent when reporting the data request result.
function estimateBaseFeeWithCallback(uint256 evmGasPrice, uint24 callbackGas) external view returns (uint256);
/// @notice Estimate the extra reward (i.e. over the base fee) to be paid when posting a new
/// @notice data query in order to avoid getting provable "too low incentives" results from
/// @notice the Wit/Oracle blockchain.
/// @dev The extra fee gets calculated in proportion to:
/// @param evmGasPrice Tentative EVM gas price at the moment the query result is ready.
/// @param evmWitPrice Tentative nanoWit price in Wei at the moment the query is solved on the Wit/Oracle blockchain.
/// @param querySLA The query SLA data security parameters as required for the Wit/Oracle blockchain.
function estimateExtraFee(uint256 evmGasPrice, uint256 evmWitPrice, Witnet.QuerySLA calldata querySLA) external view returns (uint256);
/// @notice Returns next query id to be generated by the Witnet Request Board.
function getNextQueryId() external view returns (Witnet.QueryId);
/// @notice Gets the whole Query data contents, if any, no matter its current status.
function getQuery(Witnet.QueryId queryId) external view returns (Witnet.Query memory);
/// @notice Gets the current EVM reward the reporter can claim, if not done yet.
function getQueryEvmReward(uint256) external view returns (Witnet.QueryEvmReward);
/// @notice Retrieves the RAD hash and SLA parameters of the given query.
function getQueryRequest(Witnet.QueryId) external view returns (Witnet.QueryRequest memory);
/// @notice Retrieves the whole `Witnet.QueryResponse` record referred to a previously posted Witnet Data Request.
function getQueryResponse(Witnet.QueryId) external view returns (Witnet.QueryResponse memory);
function getQueryResult(uint256) external view returns (Witnet.DataResult memory);
function getQueryResultStatus(uint256) external view returns (Witnet.ResultStatus);
function getQueryResultStatusDescription(uint256) external view returns (string memory);
/// @notice Gets query's result back tracing trails
function getQueryResultTrails(uint256)
external view returns (
bytes32 queryUUID,
Witnet.TransactionHash resultDrTxHash,
Witnet.Timestamp resultTimestamp,
uint256 resultFinalityBlock
);
/// @notice Gets current status of given query.
function getQueryStatus(uint256) external view returns (Witnet.QueryStatus);
function getQueryStatusString(uint256) external view returns (string memory);
/// @notice Get current status of all given query ids.
function getQueryStatusBatch(uint256[] calldata) external view returns (Witnet.QueryStatus[] memory);
/// @notice Request real world data from the Wit/Oracle sidechain.
/// @notice The paid fee is escrowed as a reward for the reporter that eventually relays back
/// @notice a valid query result from the Wit/Oracle sidechain.
/// @notice Query results are CBOR-encoded, and can contain either some data, or an error.
/// @dev Reasons to revert:
/// @dev - the data request's RAD hash was not previously verified into the WitOracleRadonRegistry contract;
/// @dev - invalid query SLA parameters were provided;
/// @dev - insufficient value is paid as reward.
/// @param radonHash The unique hash of the Radon Request to be solved by Wit/Oracle sidechain.
function queryData(
Witnet.RadonHash radonHash,
Witnet.QuerySLA calldata
)
external payable returns (uint256);
/// @notice Request real world data from the Wit/Oracle sidechain.
/// @notice The paid fee is escrowed as a reward for the reporter that eventually relays back
/// @notice a valid query result from the Wit/Oracle sidechain.
/// @notice The Witnet-provable result will be reported directly to the requesting contract.
/// @notice Query results are CBOR-encoded, and can contain either some data, or an error.
/// @dev Reasons to revert:
/// @dev - the data request's RAD hash was not previously verified into the Radon Registry;
/// @dev - invalid query SLA parameters were provided;
/// @dev - insufficient value is paid as reward.
/// @dev - passed `consumer` is not a contract implementing the IWitOracleQueriableConsumer interface;
/// @param radonHash The unique hash of the Radon Request to be solved by Wit/Oracle sidechain.
function queryDataWithCallback(
Witnet.RadonHash radonHash,
Witnet.QuerySLA calldata,
Witnet.QueryCallback calldata
)
external payable returns (uint256);
/// @notice Increments the reward of a previously posted request by adding the transaction value to it.
function upgradeQueryEvmReward(uint256) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IWitAppliance.sol";
abstract contract IWitOracleAppliance
is
IWitAppliance
{
/// @notice Returns the WitOracle address that this appliance is bound to.
function witOracle() virtual external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./IWitOracleRadonRegistry.sol";
interface IWitOracle {
error InvalidDataReport();
event WitOracleReport(
address indexed evmOrigin,
address indexed evmConsumer,
address evmReporter,
Witnet.TransactionHash witDrTxHash,
Witnet.RadonHash queryRadHash,
Witnet.QuerySLA queryParams,
Witnet.Timestamp resultTimestamp,
bytes resultCborBytes
);
/// @notice Uniquely identifies the WitOracle instance and the chain on which it's deployed.
function channel() external view returns (bytes4);
/// @notice Verify the data report (as provided by Wit/Kermit API) is well-formed and authentic,
/// returning the parsed Witnet.DataResult if so, or reverting otherwise.
function parseDataReport(Witnet.DataPushReport calldata report, bytes calldata proof) external view returns (Witnet.DataResult memory);
/// @notice Same as `parseDataReport` but on certain implementations it may store roll-up information
/// that will contribute to reduce the cost of verifying and/or rolling-up future data reports.
/// Emits `DataReport` if report is authentic.
function pushDataReport(Witnet.DataPushReport calldata report, bytes calldata proof) external returns (Witnet.DataResult memory);
/// @notice Returns the WitOracleRadonRegistry in which Witnet-compliant Radon requests
/// @notice can be formally verified and forever registered as a away to let smart contracts
/// and users to track actual data sources and offchain computations applied on data updates
/// safely reported from the Wit/Oracle blockchain.
function registry() external view returns (IWitOracleRadonRegistry);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract IWitAppliance {
/// @notice Returns the name of the actual contract implementing the logic of this Witnet appliance.
function class() virtual public view returns (string memory);
/// @notice Returns the ERC-165 id of the minimal functionality expected for this appliance.
function specs() virtual external view returns (bytes4);
function _require(bool _condition, string memory _message) virtual internal view {
if (!_condition) {
_revert(_message);
}
}
function _revert(string memory _message) virtual internal view {
revert(
string(abi.encodePacked(
class(),
": ",
_message
))
);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../WitOracle.sol";
import "../interfaces/legacy/IWitPriceFeedsLegacy.sol";
import "../interfaces/legacy/IWitPriceFeedsLegacyAdmin.sol";
import "../interfaces/legacy/IWitPriceFeedsLegacySolver.sol";
import "../libs/Slices.sol";
/// @title WitPriceFeedsLegacy data model.
/// @author The Witnet Foundation.
library WitPriceFeedsLegacyDataLib {
using Slices for string;
using Slices for Slices.Slice;
using Witnet for Witnet.DataResult;
using Witnet for Witnet.QueryId;
using Witnet for Witnet.ResultStatus;
bytes32 private constant _WIT_FEEDS_DATA_SLOTHASH =
/* keccak256("io.witnet.feeds.data") */
0xe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff;
struct Storage {
bytes32 reserved;
bytes4[] ids;
mapping (bytes4 => Record) records;
}
struct Record {
string caption;
uint8 decimals;
uint256 index;
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 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 = data().records[feedId].solverDepsFlag;
_deps = new bytes4[](8);
uint _len;
for (_len = 0; _len < 8; _len ++) {
_deps[_len] = bytes4(_solverDepsFlag);
if (_deps[_len] == 0) {
break;
} else {
_solverDepsFlag <<= 32;
}
}
assembly {
// reset length to actual number of dependencies:
mstore(_deps, _len)
}
}
/// @notice Returns storage pointer to where Storage data is located.
function data()
internal pure
returns (Storage storage _ptr)
{
assembly {
_ptr.slot := _WIT_FEEDS_DATA_SLOTHASH
}
}
function hash(string memory caption) internal pure returns (bytes4) {
return bytes4(keccak256(bytes(caption)));
}
function lastValidQueryId(IWitOracleQueriable witOracle, bytes4 feedId)
internal view
returns (uint256 _queryId)
{
_queryId = seekRecord(feedId).latestUpdateQueryId;
if (
_queryId == 0
|| witOracle.getQueryResultStatus(_queryId) != Witnet.ResultStatus.NoErrors
) {
_queryId = seekRecord(feedId).lastValidQueryId;
}
}
function latestUpdateQueryResultStatus(IWitOracleQueriable witOracle, bytes4 feedId)
internal view
returns (Witnet.ResultStatus)
{
uint256 _queryId = seekRecord(feedId).latestUpdateQueryId;
if (_queryId != 0) {
return witOracle.getQueryResultStatus(_queryId);
} else {
return Witnet.ResultStatus.NoErrors;
}
}
/// @notice Returns storage pointer to where Record for given feedId is located.
function seekRecord(bytes4 feedId) internal view returns (Record storage) {
return data().records[feedId];
}
function seekPriceSolver(bytes4 feedId) internal view returns (
address _solverAddress,
string[] memory _solverDeps
)
{
_solverAddress = seekRecord(feedId).solver;
bytes4[] memory _deps = depsOf(feedId);
_solverDeps = new string[](_deps.length);
for (uint _ix = 0; _ix < _deps.length; _ix ++) {
_solverDeps[_ix] = seekRecord(_deps[_ix]).caption;
}
}
// ================================================================================================
// --- Public functions ---------------------------------------------------------------------------
function deleteFeed(string calldata caption) public {
bytes4 feedId = hash(caption);
bytes4[] storage __ids = data().ids;
Record storage __record = seekRecord(feedId);
uint _index = __record.index;
require(_index != 0, "unknown feed");
bytes4 _lastFeedId = __ids[__ids.length - 1];
__ids[_index - 1] = _lastFeedId;
__ids.pop();
seekRecord(_lastFeedId).index = _index;
delete data().records[feedId];
emit IWitPriceFeedsLegacyAdmin.WitFeedDeleted(caption, feedId);
}
function deleteFeeds() public {
bytes4[] storage __ids = data().ids;
for (uint _ix = __ids.length; _ix > 0; _ix --) {
bytes4 _feedId = __ids[_ix - 1];
string memory _caption = data().records[_feedId].caption;
delete data().records[_feedId]; __ids.pop();
emit IWitPriceFeedsLegacyAdmin.WitFeedDeleted(_caption, _feedId);
}
}
function latestPrice(
IWitOracleQueriable witOracle,
bytes4 feedId
)
public view
returns (IWitPriceFeedsLegacySolver.Price memory)
{
uint256 _queryId = lastValidQueryId(witOracle, feedId);
if (_queryId != 0) {
Witnet.DataResult memory _lastValidResult = witOracle.getQueryResult(_queryId);
return IWitPriceFeedsLegacySolver.Price({
value: _lastValidResult.fetchUint(),
timestamp: _lastValidResult.timestamp,
drTxHash: _lastValidResult.drTxHash,
latestStatus: _intoLatestUpdateStatus(latestUpdateQueryResultStatus(witOracle, feedId))
});
} else {
address _solver = seekRecord(feedId).solver;
if (_solver != address(0)) {
// solhint-disable-next-line avoid-low-level-calls
(bool _success, bytes memory _result) = address(this).staticcall(abi.encodeWithSelector(
IWitPriceFeedsLegacySolver.solve.selector,
feedId
));
if (!_success) {
assembly {
_result := add(_result, 4)
}
revert(string(abi.decode(_result, (string))));
} else {
return abi.decode(_result, (IWitPriceFeedsLegacySolver.Price));
}
} else {
return IWitPriceFeedsLegacySolver.Price({
value: 0,
timestamp: Witnet.Timestamp.wrap(0),
drTxHash: Witnet.TransactionHash.wrap(0),
latestStatus: _intoLatestUpdateStatus(latestUpdateQueryResultStatus(witOracle, feedId))
});
}
}
}
function requestUpdate(
IWitOracleQueriable witOracle,
bytes4 feedId,
Witnet.QuerySLA memory querySLA,
uint256 evmUpdateRequestFee
)
public
returns (
uint256 _latestQueryId,
uint256 _evmUsedFunds
)
{
Record storage __feed = seekRecord(feedId);
_latestQueryId = __feed.latestUpdateQueryId;
Witnet.ResultStatus _latestStatus = latestUpdateQueryResultStatus(witOracle, feedId);
if (_latestStatus.keepWaiting()) {
uint72 _evmUpdateRequestCurrentFee = Witnet.QueryEvmReward.unwrap(
witOracle.getQueryEvmReward(_latestQueryId)
);
if (evmUpdateRequestFee > _evmUpdateRequestCurrentFee) {
// latest update is still pending, so just increase the reward
// accordingly to current tx gasprice:
_evmUsedFunds = (evmUpdateRequestFee - _evmUpdateRequestCurrentFee);
witOracle.upgradeQueryEvmReward{
value: _evmUsedFunds
}(
_latestQueryId
);
} else {
_evmUsedFunds = 0;
}
} else {
// Check if latest update ended successfully:
if (_latestStatus == Witnet.ResultStatus.NoErrors) {
// If so, remove previous last valid query from the WRB:
if (__feed.lastValidQueryId != 0) {
try witOracle.deleteQuery(__feed.lastValidQueryId) returns (Witnet.QueryEvmReward _unusedReward) {
evmUpdateRequestFee += Witnet.QueryEvmReward.unwrap(_unusedReward);
} catch {}
}
__feed.lastValidQueryId = _latestQueryId;
} else {
// Otherwise, try to delete latest query, as it was faulty
// and we are about to post a new update request:
try witOracle.deleteQuery(_latestQueryId) returns (Witnet.QueryEvmReward _unsedReward) {
evmUpdateRequestFee += Witnet.QueryEvmReward.unwrap(_unsedReward);
} catch {}
}
// Post update request to the WRB:
_evmUsedFunds = evmUpdateRequestFee;
_latestQueryId = witOracle.queryData{
value: _evmUsedFunds
}(
Witnet.RadonHash.wrap(__feed.radHash),
querySLA
);
// Update latest query id:
__feed.latestUpdateQueryId = _latestQueryId;
}
}
function settleFeedRequest(
string calldata caption,
bytes32 radHash
)
public
{
bytes4 feedId = hash(caption);
Record storage __record = seekRecord(feedId);
if (__record.index == 0) {
// settle new feed:
__record.caption = caption;
__record.decimals = validateCaption(caption);
__record.index = data().ids.length + 1;
__record.radHash = radHash;
data().ids.push(feedId);
} else if (__record.radHash != radHash) {
// update radHash on existing feed:
__record.radHash = radHash;
__record.solver = address(0);
}
emit IWitPriceFeedsLegacyAdmin.WitFeedSettled(caption, feedId, radHash);
}
function settleFeedSolver(
string calldata caption,
address solver,
string[] calldata deps
)
public
{
bytes4 feedId = hash(caption);
Record storage __record = seekRecord(feedId);
if (__record.index == 0) {
// settle new feed:
__record.caption = caption;
__record.decimals = validateCaption(caption);
__record.index = data().ids.length + 1;
__record.solver = solver;
data().ids.push(feedId);
} else if (__record.solver != solver) {
// update radHash on existing feed:
__record.radHash = 0;
__record.solver = solver;
}
// validate solver first-level dependencies
{
// solhint-disable-next-line avoid-low-level-calls
(bool _success, bytes memory _reason) = solver.delegatecall(abi.encodeWithSelector(
IWitPriceFeedsLegacySolver.validate.selector,
feedId,
deps
));
if (!_success) {
assembly {
_reason := add(_reason, 4)
}
revert(string(abi.encodePacked(
"solver validation failed: ",
string(abi.decode(_reason,(string)))
)));
}
}
// smoke-test the solver
{
// solhint-disable-next-line avoid-low-level-calls
(bool _success, bytes memory _reason) = address(this).staticcall(abi.encodeWithSelector(
IWitPriceFeedsLegacySolver.solve.selector,
feedId
));
if (!_success) {
assembly {
_reason := add(_reason, 4)
}
revert(string(abi.encodePacked(
"smoke-test failed: ",
string(abi.decode(_reason,(string)))
)));
}
}
emit IWitPriceFeedsLegacyAdmin.WitFeedSolverSettled(caption, feedId, solver);
}
function supportedFeeds() public view returns (
bytes4[] memory _ids,
string[] memory _captions,
bytes32[] memory _solvers
)
{
_ids = data().ids;
_captions = new string[](_ids.length);
_solvers = new bytes32[](_ids.length);
for (uint _ix = 0; _ix < _ids.length; _ix ++) {
Record storage __record = seekRecord(_ids[_ix]);
_captions[_ix] = __record.caption;
_solvers[_ix] = (
address(__record.solver) == address(0)
? __record.radHash
: bytes32(bytes20(__record.solver))
);
}
}
// --- IWitPriceFeedsLegacySolver public functions -------------------------------------------------------------
function deployPriceSolver(
bytes calldata initcode,
bytes calldata constructorParams
)
public
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(
IWitPriceFeedsLegacySolver(_solver).specs() == type(IWitPriceFeedsLegacySolver).interfaceId,
"uncompliant solver implementation"
);
}
}
function determinePriceSolverAddress(
bytes calldata initcode,
bytes calldata constructorParams
)
public view
returns (address)
{
return address(
uint160(uint(keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
bytes32(0),
keccak256(_completeInitCode(initcode, constructorParams))
)
)))
);
}
function validateCaption(string calldata caption) public pure returns (uint8) {
Slices.Slice memory _caption = caption.toSlice();
Slices.Slice memory _delim = string("-").toSlice();
string[] memory _parts = new string[](_caption.count(_delim) + 1);
for (uint _ix = 0; _ix < _parts.length; _ix ++) {
_parts[_ix] = _caption.split(_delim).toString();
}
(uint _decimals, bool _success) = Witnet.tryUint(_parts[_parts.length - 1]);
require(_success, "bad decimals");
return uint8(_decimals);
}
// ================================================================================================
// --- Private functions --------------------------------------------------------------------------
function _completeInitCode(bytes calldata initcode, bytes calldata constructorParams)
private pure
returns (bytes memory)
{
return abi.encodePacked(
initcode,
constructorParams
);
}
function _intoLatestUpdateStatus(Witnet.ResultStatus _resultStatus)
private pure
returns (IWitPriceFeedsLegacySolver.LatestUpdateStatus)
{
return (_resultStatus.keepWaiting()
? IWitPriceFeedsLegacySolver.LatestUpdateStatus.Awaiting
: (_resultStatus.hasErrors()
? IWitPriceFeedsLegacySolver.LatestUpdateStatus.Error
: IWitPriceFeedsLegacySolver.LatestUpdateStatus.Ready
)
);
}
}// SPDX-License-Identifier: MIT // solhint-disable var-name-mixedcase // solhint-disable payable-fallback pragma solidity >=0.8.0 <0.9.0; import "../patterns/Ownable2Step.sol"; import "../patterns/ReentrancyGuard.sol"; import "../patterns/Upgradeable.sol"; import "./WitnetProxy.sol"; /// @title Witnet Request Board base contract, with an Upgradeable (and Destructible) touch. /// @author Guillermo Díaz <[email protected]> abstract contract WitnetUpgradableBase is Ownable2Step, Upgradeable, ReentrancyGuard { bytes32 internal immutable _WITNET_UPGRADABLE_VERSION; address public immutable deployer = msg.sender; constructor( bool _upgradable, bytes32 _versionTag, string memory _proxiableUUID ) Upgradeable(_upgradable) { _WITNET_UPGRADABLE_VERSION = _versionTag; proxiableUUID = keccak256(bytes(_proxiableUUID)); } /// @dev Reverts if proxy delegatecalls to unexistent method. /* solhint-disable no-complex-fallback */ fallback() virtual external { revert(string(abi.encodePacked( "WitnetUpgradableBase: not implemented: 0x", _toHexString(uint8(bytes1(msg.sig))), _toHexString(uint8(bytes1(msg.sig << 8))), _toHexString(uint8(bytes1(msg.sig << 16))), _toHexString(uint8(bytes1(msg.sig << 24))) ))); } // ================================================================================================================ // --- Overrides 'Proxiable' -------------------------------------------------------------------------------------- /// @dev Gets immutable "heritage blood line" (ie. genotype) as a Proxiable, and eventually Upgradeable, contract. /// If implemented as an Upgradeable touch, upgrading this contract to another one with a different /// `proxiableUUID()` value should fail. bytes32 public immutable override proxiableUUID; // ================================================================================================================ // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------ /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. /// @dev Must fail when trying to upgrade to same logic contract more than once. function initialize(bytes memory _initData) virtual override public { address _owner = owner(); if (_owner == address(0)) { // upon first upgrade, extract decode owner address from _intidata (_owner, _initData) = abi.decode(_initData, (address, bytes)); _transferOwnership(_owner); } else { // only owner can initialize an existing proxy: require(msg.sender == _owner, "not the owner"); } __initializeUpgradableData(_initData); if ( __proxiable().codehash != bytes32(0) && __proxiable().codehash == codehash() ) { revert("already initialized codehash"); } __proxiable().codehash = codehash(); emit Upgraded(owner(), base(), codehash(), version()); } /// Tells whether provided address could eventually upgrade the contract. function isUpgradableFrom(address _from) external view virtual override returns (bool) { return ( // false if the WRB is intrinsically not upgradable, or `_from` is no owner isUpgradable() && owner() == _from ); } /// Retrieves human-readable version tag of current implementation. function version() public view virtual override returns (string memory) { return _toString(_WITNET_UPGRADABLE_VERSION); } // ================================================================================================================ // --- Internal methods ------------------------------------------------------------------------------------------- function _toHexString(uint8 _u) internal pure returns (string memory) { bytes memory b2 = new bytes(2); uint8 d0 = uint8(_u / 16) + 48; uint8 d1 = uint8(_u % 16) + 48; if (d0 > 57) d0 += 7; if (d1 > 57) d1 += 7; b2[0] = bytes1(d0); b2[1] = bytes1(d1); return string(b2); } /// Converts bytes32 into string. function _toString(bytes32 _bytes32) internal pure returns (string memory) { bytes memory _bytes = new bytes(_toStringLength(_bytes32)); for (uint _i = 0; _i < _bytes.length;) { _bytes[_i] = _bytes32[_i]; unchecked { _i ++; } } return string(_bytes); } // Calculate length of string-equivalent to given bytes32. function _toStringLength(bytes32 _bytes32) internal pure returns (uint _length) { for (; _length < 32; ) { if (_bytes32[_length] == 0) { break; } unchecked { _length ++; } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "../patterns/Upgradeable.sol"; /// @title WitnetProxy: upgradable delegate-proxy contract. /// @author Guillermo Díaz <[email protected]> contract WitnetProxy { /// Event emitted every time the implementation gets updated. event Upgraded(address indexed implementation); /// Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470). constructor () {} receive() virtual external payable {} /// Payable fallback accepts delegating calls to payable functions. fallback() external payable { /* solhint-disable no-complex-fallback */ address _implementation = implementation(); assembly { /* solhint-disable avoid-low-level-calls */ // Gas optimized delegate call to 'implementation' contract. // Note: `msg.data`, `msg.sender` and `msg.value` will be passed over // to actual implementation of `msg.sig` within `implementation` contract. let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), _implementation, ptr, calldatasize(), 0, 0) let size := returndatasize() returndatacopy(ptr, 0, size) switch result case 0 { // pass back revert message: revert(ptr, size) } default { // pass back same data as returned by 'implementation' contract: return(ptr, size) } } } /// Returns proxy's current implementation address. function implementation() public view returns (address) { return __proxySlot().implementation; } /// Upgrades the `implementation` address. /// @param _newImplementation New implementation address. /// @param _initData Raw data with which new implementation will be initialized. /// @return Returns whether new implementation would be further upgradable, or not. function upgradeTo(address _newImplementation, bytes memory _initData) public returns (bool) { // New implementation cannot be null: require(_newImplementation != address(0), "WitnetProxy: null implementation"); address _oldImplementation = implementation(); if (_oldImplementation != address(0)) { // New implementation address must differ from current one: require(_newImplementation != _oldImplementation, "WitnetProxy: nothing to upgrade"); // Assert whether current implementation is intrinsically upgradable: try Upgradeable(_oldImplementation).isUpgradable() returns (bool _isUpgradable) { require(_isUpgradable, "WitnetProxy: not upgradable"); } catch { revert("WitnetProxy: unable to check upgradability"); } // Assert whether current implementation allows `msg.sender` to upgrade the proxy: (bool _wasCalled, bytes memory _result) = _oldImplementation.delegatecall( abi.encodeWithSignature( "isUpgradableFrom(address)", msg.sender ) ); require(_wasCalled, "WitnetProxy: uncompliant implementation"); require(abi.decode(_result, (bool)), "WitnetProxy: not authorized"); require( Upgradeable(_oldImplementation).proxiableUUID() == Upgradeable(_newImplementation).proxiableUUID(), "WitnetProxy: proxiableUUIDs mismatch" ); } // Initialize new implementation within proxy-context storage: (bool _wasInitialized, bytes memory _returnData) = _newImplementation.delegatecall( abi.encodeWithSignature( "initialize(bytes)", _initData ) ); if (!_wasInitialized) { if (_returnData.length < 68) { revert("WitnetProxy: initialization failed"); } else { assembly { _returnData := add(_returnData, 0x04) } revert(abi.decode(_returnData, (string))); } } // If all checks and initialization pass, update implementation address: __proxySlot().implementation = _newImplementation; emit Upgraded(_newImplementation); // Asserts new implementation complies w/ minimal implementation of Upgradeable interface: try Upgradeable(_newImplementation).isUpgradable() returns (bool _isUpgradable) { return _isUpgradable; } catch { revert ("WitnetProxy: uncompliant implementation"); } } /// @dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address. function __proxySlot() private pure returns (Proxiable.ProxiableSlot storage _slot) { assembly { // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) _slot.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc } } }
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "ado-contracts/contracts/interfaces/IERC2362.sol";
import "./interfaces/IWitOracleAppliance.sol";
import "./interfaces/legacy/IWitPriceFeedsLegacy.sol";
import "./interfaces/legacy/IWitPriceFeedsLegacyAdmin.sol";
import "./interfaces/legacy/IWitPriceFeedsLegacySolverFactory.sol";
/// @title WitPriceFeedsLegacy: Price Feeds live repository reliant on the Wit/Oracle blockchain.
/// @author The Witnet Foundation.
abstract contract WitPriceFeedsLegacy
is
IERC2362,
IWitPriceFeedsLegacy,
IWitPriceFeedsLegacyAdmin,
IWitPriceFeedsLegacySolverFactory,
IWitOracleAppliance
{
Witnet.RadonDataTypes immutable public override dataType = Witnet.RadonDataTypes.Integer;
bytes32 immutable internal __prefix = "Price-";
function prefix() virtual override external view returns (string memory) {
return Witnet.asAscii(__prefix);
}
function specs() virtual override external pure returns (bytes4) {
return (
type(IERC2362).interfaceId
^ type(IWitOracleAppliance).interfaceId
^ type(IWitPriceFeedsLegacy).interfaceId
^ type(IWitPriceFeedsLegacyAdmin).interfaceId
^ type(IWitPriceFeedsLegacySolverFactory).interfaceId
);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./interfaces/IWitOracle.sol";
import "./interfaces/IWitOracleAppliance.sol";
import "./interfaces/IWitOracleQueriable.sol";
import "./interfaces/IWitOracleQueriableEvents.sol";
/// @title Witnet Request Board functionality base contract.
/// @author The Witnet Foundation.
abstract contract WitOracle
is
IWitAppliance,
IWitOracle,
IWitOracleQueriable,
IWitOracleQueriableEvents
{
function specs() virtual override external pure returns (bytes4) {
return (
type(IWitOracle).interfaceId
^ type(IWitOracleQueriable).interfaceId
);
}
}// 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.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.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 reinitialization) 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 Pointer to storage slot. Allows integrators to override it with a custom storage location.
*
* NOTE: Consider following the ERC-7201 formula to derive storage locations.
*/
function _initializableStorageSlot() internal pure virtual returns (bytes32) {
return INITIALIZABLE_STORAGE;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
bytes32 slot = _initializableStorageSlot();
assembly {
$.slot := slot
}
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "prague",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {
"/contracts/apps/WitPriceFeedsLegacyUpgradable.sol": {
"WitPriceFeedsLegacyDataLib": "0xbffa2ec6225390c517a1beb83b27a171c6734294"
}
}
}Contract ABI
API[{"inputs":[{"internalType":"contract WitOracle","name":"_witOracle","type":"address"},{"internalType":"bytes32","name":"_versionTag","type":"bytes32"},{"internalType":"bool","name":"_upgradable","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"solver","type":"address"},{"indexed":false,"internalType":"bytes32","name":"codehash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"NewPriceFeedsSolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"evmOrigin","type":"address"},{"indexed":false,"internalType":"address","name":"evmSender","type":"address"},{"indexed":false,"internalType":"bytes4","name":"erc2362Id4","type":"bytes4"},{"indexed":false,"internalType":"uint256","name":"witOracleQueryId","type":"uint256"}],"name":"PullingUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"baseAddr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"baseCodehash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"versionTag","type":"string"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"WitFeedDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"bytes32","name":"radHash","type":"bytes32"}],"name":"WitFeedSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"caption","type":"string"},{"indexed":false,"internalType":"bytes4","name":"feedId","type":"bytes4"},{"indexed":false,"internalType":"address","name":"solver","type":"address"}],"name":"WitFeedSolverSettled","type":"event"},{"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 IWitPriceFeedsLegacy.RadonSLAv1","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"deleteFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deleteFeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"deployPriceSolver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initcode","type":"bytes"},{"internalType":"bytes","name":"constructorParams","type":"bytes"}],"name":"determinePriceSolverAddress","outputs":[{"internalType":"address","name":"_address","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_evmGasPrice","type":"uint256"}],"name":"estimateUpdateBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":"lastValidQueryResponse","outputs":[{"components":[{"internalType":"address","name":"reporter","type":"address"},{"internalType":"Witnet.Timestamp","name":"resultTimestamp","type":"uint64"},{"internalType":"Witnet.TransactionHash","name":"resultDrTxHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"internalType":"address","name":"disputer","type":"address"}],"internalType":"struct Witnet.QueryResponse","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestPrice","outputs":[{"components":[{"internalType":"uint64","name":"value","type":"uint64"},{"internalType":"Witnet.Timestamp","name":"timestamp","type":"uint64"},{"internalType":"Witnet.TransactionHash","name":"drTxHash","type":"bytes32"},{"internalType":"enum IWitPriceFeedsLegacySolver.LatestUpdateStatus","name":"latestStatus","type":"uint8"}],"internalType":"struct IWitPriceFeedsLegacySolver.Price","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"feedIds","type":"bytes4[]"}],"name":"latestPrices","outputs":[{"components":[{"internalType":"uint64","name":"value","type":"uint64"},{"internalType":"Witnet.Timestamp","name":"timestamp","type":"uint64"},{"internalType":"Witnet.TransactionHash","name":"drTxHash","type":"bytes32"},{"internalType":"enum IWitPriceFeedsLegacySolver.LatestUpdateStatus","name":"latestStatus","type":"uint8"}],"internalType":"struct IWitPriceFeedsLegacySolver.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":"latestUpdateQueryRequest","outputs":[{"components":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"uint24","name":"callbackGas","type":"uint24"},{"internalType":"bytes","name":"radonBytecode","type":"bytes"},{"internalType":"Witnet.RadonHash","name":"radonHash","type":"bytes32"}],"internalType":"struct Witnet.QueryRequest","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":"Witnet.Timestamp","name":"resultTimestamp","type":"uint64"},{"internalType":"Witnet.TransactionHash","name":"resultDrTxHash","type":"bytes32"},{"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"internalType":"address","name":"disputer","type":"address"}],"internalType":"struct Witnet.QueryResponse","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResponseStatus","outputs":[{"internalType":"enum IWitOracleLegacy.QueryResponseStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"latestUpdateResultError","outputs":[{"components":[{"internalType":"uint8","name":"code","type":"uint8"},{"internalType":"string","name":"reason","type":"string"}],"internalType":"struct IWitOracleLegacy.ResultError","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupCaption","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"lookupPriceSolver","outputs":[{"internalType":"address","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.RadonRetrievalMethods","name":"method","type":"uint8"},{"internalType":"enum Witnet.RadonDataTypes","name":"dataType","type":"uint8"},{"internalType":"string","name":"url","type":"string"},{"internalType":"string","name":"body","type":"string"},{"internalType":"string[2][]","name":"headers","type":"string[2][]"},{"internalType":"bytes","name":"radonScript","type":"bytes"}],"internalType":"struct Witnet.RadonRetrieval[]","name":"_retrievals","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prefix","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"feedId","type":"bytes4"},{"components":[{"internalType":"uint8","name":"numWitnesses","type":"uint8"},{"internalType":"uint64","name":"unitaryReward","type":"uint64"}],"internalType":"struct IWitPriceFeedsLegacy.RadonSLAv2","name":"legacySLA","type":"tuple"}],"name":"requestUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_baseFeeOverheadPercentage","type":"uint16"}],"name":"settleBaseFeeOverheadPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"numWitnesses","type":"uint8"},{"internalType":"uint64","name":"unitaryReward","type":"uint64"}],"internalType":"struct IWitPriceFeedsLegacy.RadonSLAv2","name":"radonSLAv2","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 IWitOracleRequest","name":"request","type":"address"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"contract IWitOracleRequestTemplate","name":"template","type":"address"},{"internalType":"string[][]","name":"args","type":"string[][]"}],"name":"settleFeedRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"string[]","name":"deps","type":"string[]"}],"name":"settleFeedSolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specs","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"supportedFeeds","outputs":[{"internalType":"bytes4[]","name":"_ids","type":"bytes4[]"},{"internalType":"string[]","name":"_captions","type":"string[]"},{"internalType":"bytes32[]","name":"_solvers","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"caption","type":"string"}],"name":"supportsCaption","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"feedId","type":"bytes32"}],"name":"valueFor","outputs":[{"internalType":"int256","name":"_value","type":"int256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"},{"internalType":"uint256","name":"_status","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witnet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101c060405260046080526550726963652d60d01b60a0523361014052348015610027575f5ffd5b5060405161508c38038061508c833981016040819052610046916102cf565b60408051808201909152601f81527f696f2e7769746e65742e70726f786961626c652e66656564732e7072696365006020820152819083908233806100a557604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6100ae816101e6565b503060c052151561010052600160025561012091909152805160209182012061016052604080518082019091526011815270696e6578697374656e74206f7261636c6560781b9181019190915261011391506001600160a01b0385163b151590610202565b6101d2637cd906ed60e11b636d11bc5160e11b186001600160e01b031916846001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561016d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610191919061031e565b6001600160e01b0319161460405180604001604052806012815260200171756e636f6d706c69616e74206f7261636c6560701b81525061020260201b60201c565b50506001600160a01b0316610180526103c1565b600180546001600160a01b03191690556101ff81610214565b50565b816102105761021081610263565b5050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408051808201909152601d81527f576974507269636546656564734c656761637955706772616461626c650000006020820152816040516020016102a9929190610363565b60408051601f198184030181529082905262461bcd60e51b825261009c9160040161038c565b5f5f5f606084860312156102e1575f5ffd5b83516001600160a01b03811681146102f7575f5ffd5b6020850151604086015191945092508015158114610313575f5ffd5b809150509250925092565b5f6020828403121561032e575f5ffd5b81516001600160e01b031981168114610345575f5ffd5b9392505050565b5f81518060208401855e5f93019283525090919050565b5f61036e828561034c565b6101d160f51b8152610383600282018561034c565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051614bd66104b65f395f50505f81816104bf0152818161056601528181610d70015281816112560152818161142c01528181611ca201528181611eca01528181611efc01528181611fb4015281816121640152818161278e01528181612b8f0152612f4201525f61062501525f610ade01525f6113b701525f818161065501526114f801525f50505f81816105f001528181610925015281816110e2015281816111530152818161119a01526111bc01525f8181610e2e01526115f801525f81816106f501526116b10152614bd65ff3fe60806040526004361061034f575f3560e01c80638da5cb5b116101c5578063d3471e34116100f6578063f14cb81211610094578063f9f34bb61161006e578063f9f34bb614610c21578063fae91a5114610c4d578063ff24fb4f14610c6c578063ff75890f14610c8b5761034f565b8063f14cb81214610b9c578063f2fde38b14610bc8578063f78eea8314610be75761034f565b8063e1c9e3c0116100d0578063e1c9e3c014610b33578063e30c397814610b47578063eb92b29b14610b5b578063ef1dff2b14610b7d5761034f565b8063d3471e3414610aae578063d5f3948814610acd578063d6a3614f14610b005761034f565b8063b411ee9411610163578063c064d3721161013d578063c064d37214610a18578063c3d98ea814610a37578063c5010d1714610a63578063cfae692914610a825761034f565b8063b411ee9414610995578063b8d38c96146109b4578063bff852fa146109d35761034f565b8063a9e954b91161019f578063a9e954b914610917578063abc86c6e1461094a578063ac82c6081461095d578063adb7c3f71461097c5761034f565b80638da5cb5b146108bd5780638df3fdfd146108d9578063a55b471c146108f85761034f565b806354fd4d501161029f578063715018a61161023d578063806d7e8f11610217578063806d7e8f1461082657806384292f071461085257806386ac03e0146108715780638a416ea9146108905761034f565b8063715018a6146107ea57806375dadb32146107fe57806379ba5097146108125761034f565b80636175ff00116102795780636175ff00146106e45780636ab221f8146107245780636b58960a146107555780636d1178e5146107745761034f565b806354fd4d50146106855780635be93984146106995780635c0d9d80146106b85761034f565b8063439fab911161030c5780634efef9c0116102e65780634efef9c0146105b65780635001f3b5146105e257806352d1902d146106145780635479d940146106475761034f565b8063439fab911461053957806346d1d21a1461055857806349492ef11461058a5761034f565b8063029db9581461043a5780630306732e1461046c57806303f3813d1461048f5780631014d375146104ae578063384ac938146104f95780633e088e1214610526575b34801561035a575f5ffd5b505f356001600160e01b03191663e0d20f7360e01b14801561037b57503330145b15610408575f6103a160206103903684613333565b6001600160c01b031916901b610caa565b6006015460408051808201909152601081526f3ab739b2ba3a3632b21039b7b63b32b960811b60208201526001600160a01b0390911691506103e69082151590610ce3565b604051365f82375f5f3683855af43d805f843e818015610404578184f35b8184fd5b6104386040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610cf5565b005b348015610445575f5ffd5b5061045961045436600461337e565b610d6a565b6040519081526020015b60405180910390f35b348015610477575f5ffd5b50610480610d9b565b60405161046393929190613421565b34801561049a575f5ffd5b506104386104a9366004613556565b610e18565b3480156104b9575f5ffd5b506104e17f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610463565b348015610504575f5ffd5b5061051861051336600461337e565b610fb1565b6040516104639291906135d6565b61045961053436600461337e565b610fc6565b348015610544575f5ffd5b50610438610553366004613713565b61100c565b348015610563575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000006104e1565b348015610595575f5ffd5b506105a96105a436600461337e565b611240565b6040516104639190613757565b3480156105c1575f5ffd5b506105d56105d036600461337e565b6112eb565b604051610463919061377e565b3480156105ed575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000006104e1565b34801561061f575f5ffd5b506104597f000000000000000000000000000000000000000000000000000000000000000081565b348015610652575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519015158152602001610463565b348015610690575f5ffd5b506105d56113b0565b3480156106a4575f5ffd5b506104596106b336600461337e565b6113e0565b3480156106c3575f5ffd5b506106d76106d236600461337e565b6113f4565b6040516104639190613790565b3480156106ef575f5ffd5b506107177f000000000000000000000000000000000000000000000000000000000000000081565b604051610463919061380a565b34801561072f575f5ffd5b5061074361073e36600461337e565b6114ca565b60405160ff9091168152602001610463565b348015610760575f5ffd5b5061067561076f366004613818565b6114e1565b34801561077f575f5ffd5b5061078861153a565b60405161046391905f60a08201905060ff835116825260ff60208401511660208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526001600160401b03608084015116608083015292915050565b3480156107f5575f5ffd5b506104386115de565b348015610809575f5ffd5b506105d56115f1565b34801561081d575f5ffd5b5061043861161c565b348015610831575f5ffd5b5061084561084036600461337e565b611624565b60405161046391906138c0565b34801561085d575f5ffd5b5061043861086c3660046139b1565b6116a4565b34801561087c575f5ffd5b5061043861088b3660046139f8565b611873565b34801561089b575f5ffd5b506108a4611948565b6040516001600160e01b03199091168152602001610463565b3480156108c8575f5ffd5b505f546001600160a01b03166104e1565b3480156108e4575f5ffd5b506104596108f336600461337e565b611a46565b348015610903575f5ffd5b506104e1610912366004613a36565b611a5a565b348015610922575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000003f610459565b610459610958366004613ab0565b611b9e565b348015610968575f5ffd5b50610438610977366004613ae4565b611bbf565b348015610987575f5ffd5b506331f74adb60e11b6108a4565b3480156109a0575f5ffd5b506108a46109af366004613713565b611c2c565b3480156109bf575f5ffd5b506104386109ce366004613b45565b611c3a565b3480156109de575f5ffd5b5060408051808201909152601d81527f576974507269636546656564734c656761637955706772616461626c6500000060208201526105d5565b348015610a23575f5ffd5b50610459610a32366004613b60565b611c5a565b348015610a42575f5ffd5b50610a56610a5136600461337e565b611c64565b6040516104639190613bc1565b348015610a6e575f5ffd5b50610675610a7d3660046139f8565b611da7565b348015610a8d575f5ffd5b50610aa1610a9c36600461337e565b611e9f565b6040516104639190613bcf565b348015610ab9575f5ffd5b50610aa1610ac836600461337e565b611f89565b348015610ad8575f5ffd5b506104e17f000000000000000000000000000000000000000000000000000000000000000081565b348015610b0b575f5ffd5b507fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20054610459565b348015610b3e575f5ffd5b50610438611fea565b348015610b52575f5ffd5b506104e16120b5565b348015610b66575f5ffd5b5060045460405161ffff9091168152602001610463565b348015610b88575f5ffd5b506105d5610b9736600461337e565b6120c8565b348015610ba7575f5ffd5b50610bbb610bb636600461337e565b612161565b6040516104639190613c3a565b348015610bd3575f5ffd5b50610438610be2366004613818565b6121f7565b348015610bf2575f5ffd5b50610c06610c01366004613b60565b612208565b60408051938452602084019290925290820152606001610463565b348015610c2c575f5ffd5b50610c40610c3b366004613c54565b612292565b6040516104639190613c86565b348015610c58575f5ffd5b50610438610c67366004613cd3565b612367565b348015610c77575f5ffd5b50610438610c86366004613556565b612443565b348015610c96575f5ffd5b506104e1610ca5366004613a36565b61249a565b6001600160e01b0319165f9081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b81610cf157610cf181610cf5565b5050565b60408051808201909152601d81527f576974507269636546656564734c656761637955706772616461626c65000000602082015281604051602001610d3b929190613d04565b60408051601f198184030181529082905262461bcd60e51b8252610d619160040161377e565b60405180910390fd5b5f610d957f000000000000000000000000000000000000000000000000000000000000000083612524565b92915050565b606080606073bffa2ec6225390c517a1beb83b27a171c6734294630306732e6040518163ffffffff1660e01b81526004015f60405180830381865af4158015610de6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e0d9190810190613e9e565b925092509250909192565b610e206125d1565b610e936001600160d01b03197f000000000000000000000000000000000000000000000000000000000000000016610e588688613f97565b6001600160d01b03191614604051806040016040528060128152602001710c4c2c840c6c2e0e8d2dedc40e0e4caccd2f60731b815250610ce3565b6040805180820190915260118152706e6f20736f6c766572206164647265737360781b6020820152610ed1906001600160a01b038516151590610ce3565b6040516303f3813d60e01b815273bffa2ec6225390c517a1beb83b27a171c6734294906303f3813d90610f109088908890889088908890600401614036565b5f6040518083038186803b158015610f26575f5ffd5b505af4925050508015610f37575060015b610faa57610f436140c4565b806308c379a003610f715750610f576140dc565b80610f625750610f73565b610f6b81610cf5565b50610faa565b505b3d808015610f9c576040519150601f19603f3d011682016040523d82523d5f602084013e610fa1565b606091505b50610f6b6125fd565b5050505050565b5f6060610fbd8361260d565b91509150915091565b6040805160608101825260035461ffff808216835262010000820416602083015264010000000090046001600160401b0316918101919091525f90610d95908390612763565b5f546001600160a01b0316806110425781806020019051810190611030919061415e565b9250905061103d816129e6565b61108a565b336001600160a01b0382161461108a5760405162461bcd60e51b815260206004820152600d60248201526c3737ba103a34329037bbb732b960991b6044820152606401610d61565b611093826129ff565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe541580159061110457507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f00000000000000000000000000000000000000000000000000000000000000003f145b156111515760405162461bcd60e51b815260206004820152601c60248201527f616c726561647920696e697469616c697a656420636f646568617368000000006044820152606401610d61565b7f00000000000000000000000000000000000000000000000000000000000000003f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600201557f00000000000000000000000000000000000000000000000000000000000000003f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166111f55f546001600160a01b031690565b6001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f66112276113b0565b604051611234919061377e565b60405180910390a45050565b604080518082019091525f8152606060208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a77fc1a461128c846113e0565b6040518263ffffffff1660e01b81526004016112aa91815260200190565b5f60405180830381865afa1580156112c4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d9591908101906141c4565b60605f6112f783610caa565b905061132f81600501545f5f1b14156040518060400160405280600b81526020016a0dcde40a4828840d0c2e6d60ab1b815250610ce3565b611337612b8c565b6001600160a01b0316638a22776482600501546040518263ffffffff1660e01b815260040161136891815260200190565b5f60405180830381865afa158015611382573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526113a99190810190614245565b9392505050565b60606113db7f0000000000000000000000000000000000000000000000000000000000000000612c0d565b905090565b5f6113ea82610caa565b6004015492915050565b61142a60405180608001604052805f6001600160a01b031681526020015f62ffffff168152602001606081526020015f81525090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a667533f611462846113e0565b6040516001600160e01b031960e084901b1681526001600160401b0390911660048201526024015f60405180830381865afa1580156114a3573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d959190810190614276565b5f6114d482610caa565b6001015460ff1692915050565b5f5f6114f45f546001600160a01b031690565b90507f000000000000000000000000000000000000000000000000000000000000000080156113a95750826001600160a01b0316816001600160a01b0316149392505050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091526003546040805160a08101825262010000830460ff8116808352603360208401526401000000009094046001600160401b031692820183905261ffff169260608201906115b19084614331565b6001600160401b031681526020016115cc60ff851684614367565b6001600160401b031690529392505050565b6115e66125d1565b6115ef5f6129e6565b565b60606113db7f0000000000000000000000000000000000000000000000000000000000000000612cae565b6115ef612d4f565b606061162e612b8c565b6001600160a01b03166377c1125961164584611a46565b6040518263ffffffff1660e01b815260040161166391815260200190565b5f60405180830381865afa15801561167d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d95919081019061449b565b6116ac6125d1565b6117997f000000000000000000000000000000000000000000000000000000000000000060138111156116e1576116e16137e2565b6116e9612b8c565b6001600160a01b0316634c729104846040518263ffffffff1660e01b815260040161171691815260200190565b602060405180830381865afa158015611731573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117559190614648565b6013811115611766576117666137e2565b146040518060400160405280601481526020017362616420726573756c742064617461207479706560601b815250610ce3565b6040516384292f0760e01b815273bffa2ec6225390c517a1beb83b27a171c6734294906384292f07906117d490869086908690600401614661565b5f6040518083038186803b1580156117ea575f5ffd5b505af49250505080156117fb575060015b61186e576118076140c4565b806308c379a003611835575061181b6140dc565b806118265750611837565b61182f81610cf5565b50505050565b505b3d808015611860576040519150601f19603f3d011682016040523d82523d5f602084013e611865565b606091505b5061182f6125fd565b505050565b61187b6125d1565b604051630435601f60e51b815273bffa2ec6225390c517a1beb83b27a171c6734294906386ac03e0906118b49085908590600401614684565b5f6040518083038186803b1580156118ca575f5ffd5b505af49250505080156118db575060015b610cf1576118e76140c4565b806308c379a00361190f57506118fb6140dc565b806119065750611911565b61186e81610cf5565b505b3d80801561193a576040519150601f19603f3d011682016040523d82523d5f602084013e61193f565b606091505b5061186e6125fd565b7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200545f9015611a43576119cf7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001015f815481106119a9576119a9614697565b905f5260205f2090600891828204019190066004029054906101000a900460e01b612dca565b905060015b7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20054811015611a4157611a357fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff60010182815481106119a9576119a9614697565b909118906001016119d4565b505b90565b5f611a5082610caa565b6005015492915050565b5f611a636125d1565b604051632956d1c760e21b815273bffa2ec6225390c517a1beb83b27a171c67342949063a55b471c90611aa09088908890889088906004016146ab565b602060405180830381865af4925050508015611ad9575060408051601f3d908101601f19168201909252611ad6918101906146dc565b60015b611b4c57611ae56140c4565b806308c379a003611b135750611af96140dc565b80611b045750611b15565b611b0d81610cf5565b50611b96565b505b3d808015611b3e576040519150601f19603f3d011682016040523d82523d5f602084013e611b43565b606091505b50611b0d6125fd565b7f18678abae9a91a452648053bebd7d23122fb9204cddc206fa8193750abb8940f81826001600160a01b03163f8686604051611b8b94939291906146f7565b60405180910390a190505b949350505050565b5f6113a983611bba611bb53686900386018661473c565b612e53565b612763565b611bc76125d1565b61186e8383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c08573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086c9190614781565b805160208201205f90610d95565b611c426125d1565b6004805461ffff191661ffff92909216919091179055565b5f610d9582612f26565b611c8b604080516080810182525f8082526020820181905291810182905290606082015290565b6040516384ee241160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526001600160e01b03198316602482015273bffa2ec6225390c517a1beb83b27a171c6734294906384ee241190604401608060405180830381865af4925050508015611d2f575060408051601f3d908101601f19168201909252611d2c91810190614798565b60015b610d9557611d3b6140c4565b806308c379a003611d695750611d4f6140dc565b80611d5a5750611d6b565b611d6381610cf5565b50919050565b505b3d808015611d94576040519150601f19603f3d011682016040523d82523d5f602084013e611d99565b606091505b50611d636125fd565b919050565b5f5f611de784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611c2c92505050565b90506001600160e01b03198116611e8c611e0083610caa565b8054611e0b906147fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611e37906147fd565b8015611e825780601f10611e5957610100808354040283529160200191611e82565b820191905f5260205f20905b815481529060010190602001808311611e6557829003601f168201915b5050505050611c2c565b6001600160e01b03191614949350505050565b6040805160a0810182525f8082526020820181905291810182905260608082015260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca7da98b611f217f000000000000000000000000000000000000000000000000000000000000000085612524565b6040516001600160e01b031960e084901b1681526001600160401b0390911660048201526024015f60405180830381865afa158015611f62573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d95919081019061482f565b6040805160a0810182525f8082526020820181905291810182905260608082015260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca7da98b611f21846113e0565b611ff26125d1565b73bffa2ec6225390c517a1beb83b27a171c673429463e1c9e3c06040518163ffffffff1660e01b81526004015f6040518083038186803b158015612034575f5ffd5b505af4925050508015612045575060015b6115ef576120516140c4565b806308c379a00361207c57506120656140dc565b80612070575061207e565b61207981610cf5565b50565b505b3d8080156120a7576040519150601f19603f3d011682016040523d82523d5f602084013e6120ac565b606091505b506120796125fd565b5f6113db6001546001600160a01b031690565b60606120d382610caa565b80546120de906147fd565b80601f016020809104026020016040519081016040528092919081815260200182805461210a906147fd565b80156121555780601f1061212c57610100808354040283529160200191612155565b820191905f5260205f20905b81548152906001019060200180831161213857829003601f168201915b50505050509050919050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663234fe6e361219a846113e0565b6040518263ffffffff1660e01b81526004016121b891815260200190565b602060405180830381865afa1580156121d3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9591906148e4565b6121ff6125d1565b61207981612fe1565b5f5f5f5f61221585611c64565b805160208201519192506001600160401b031690600283606001516003811115612241576122416137e2565b146122735760018360600151600381111561225e5761225e6137e2565b1461226b57610190612276565b610194612276565b60c85b9195506001600160401b0316935061ffff169150509193909250565b6060816001600160401b038111156122ac576122ac6135f9565b60405190808252806020026020018201604052801561230457816020015b6122f1604080516080810182525f8082526020820181905291810182905290606082015290565b8152602001906001900390816122ca5790505b5090505f5b828110156123605761233b84848381811061232657612326614697565b9050602002016020810190610a51919061337e565b82828151811061234d5761234d614697565b6020908102919091010152600101612309565b5092915050565b61236f6125d1565b61237c6020820182614902565b6003805463ffff0000191660ff9290921662010000029190911790556123a8604082016020830161491d565b600380546001600160401b039283166401000000009081026bffffffffffffffff000000001983168117938490556040805160608101825261ffff92831694831694909417845262010000850490911660208401529204909216908201526120799061241390613012565b60405180604001604052806012815260200171696e76616c69642075706461746520534c4160701b815250610ce3565b61244b6125d1565b610faa8585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161247e92919061498d565b6020604051808303815f875af1158015611c08573d5f5f3e3d5ffd5b6040516001628a76f160e01b031981525f9073bffa2ec6225390c517a1beb83b27a171c67342949063ff75890f906124dc9088908890889088906004016146ab565b602060405180830381865af41580156124f7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061251b91906146dc565b95945050505050565b5f61252e82610caa565b6004015490508015806125b857505f604051634cddf61560e01b8152600481018390526001600160a01b03851690634cddf61590602401602060405180830381865afa158015612580573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a49190614a2e565b60ff8111156125b5576125b56137e2565b14155b15610d95576125c682610caa565b600301549392505050565b5f546001600160a01b031633146115ef5760405163118cdaa760e01b8152336004820152602401610d61565b6115ef61260861304d565b610cf5565b5f606061261983610caa565b600601546001600160a01b031691505f612632846130a9565b905080516001600160401b0381111561264d5761264d6135f9565b60405190808252806020026020018201604052801561268057816020015b606081526020019060019003908161266b5790505b5091505f5b815181101561275c576126b08282815181106126a3576126a3614697565b6020026020010151610caa565b80546126bb906147fd565b80601f01602080910402602001604051908101604052809291908181526020018280546126e7906147fd565b80156127325780601f1061270957610100808354040283529160200191612732565b820191905f5260205f20905b81548152906001019060200180831161271557829003601f168201915b505050505083828151811061274957612749614697565b6020908102919091010152600101612685565b5050915091565b5f61276d83610caa565b600501541561295c57604080516303f8890160e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526001600160e01b031985166024820152835161ffff90811660448301526020850151166064820152908301516001600160401b031660848201523460a482018190529073bffa2ec6225390c517a1beb83b27a171c6734294906307f112029060c4016040805180830381865af492505050801561284d575060408051601f3d908101601f1916820190925261284a91810190614a4d565b60015b6128c0576128596140c4565b806308c379a003612887575061286d6140dc565b806128785750612889565b61288181610cf5565b50612956565b505b3d8080156128b2576040519150601f19603f3d011682016040523d82523d5f602084013e6128b7565b606091505b506128816125fd565b348110156128fd57336108fc6128d68334614a6f565b6040518115909202915f818181858888f193505050501580156128fb573d5f5f3e3d5ffd5b505b604080513281523360208201526001600160e01b03198816818301526060810184905290517f0bd652a116bb5006c2e07594e8a3fe9b5ba51acf6cd9572568913fda51ad26c49181900360800190a19250610d95915050565b50610d95565b5f61296684610caa565b600601546001600160a01b0316146129b9576129b2612984846130a9565b6040518060400160405280856020015160ff16815260200185604001516001600160401b0316815250613191565b9050610d95565b610d956040518060400160405280600c81526020016b1d5b9adb9bdddb881999595960a21b815250610cf5565b600180546001600160a01b031916905561207981613274565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54612a76576040805160608101825260108152600360208201819052630bebc20091909201528054670bebc200000300106bffffffffffffffffffffffff199091161790556004805461ffff1916600a17905550565b805115612b05575f5f82806020019051810190612a939190614a82565b6004805461ffff93841661ffff1990911617905580516003805460208401516040909401516001600160401b0316640100000000026bffffffffffffffff0000000019948616620100000263ffffffff1990921693909516929092179190911791909116919091179055506120799050565b6040805160608101825260035461ffff808216835262010000820416602083015264010000000090046001600160401b031691810191909152612b4790613012565b61207957506040805160608101825260108152600360208201819052630bebc200919092015280546bffffffffffffffffffffffff1916670bebc20000030010179055565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612be9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113db91906146dc565b60605f612c19836132c3565b6001600160401b03811115612c3057612c306135f9565b6040519080825280601f01601f191660200182016040528015612c5a576020820181803683370190505b5090505f5b815181101561236057838160208110612c7a57612c7a614697565b1a60f81b828281518110612c9057612c90614697565b60200101906001600160f81b03191690815f1a905350600101612c5f565b60605f612cba836132fb565b6001600160401b03811115612cd157612cd16135f9565b6040519080825280601f01601f191660200182016040528015612cfb576020820181803683370190505b5090505f5b815181101561236057838160208110612d1b57612d1b614697565b1a60f81b828281518110612d3157612d31614697565b60200101906001600160f81b03191690815f1a905350600101612d00565b3380612d596120b5565b6001600160a01b031614612dc15760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610d61565b612079816129e6565b5f80612dd583610caa565b6005015414612e255781612de883610caa565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b81612e2f83610caa565b60080154604080516001600160e01b03199093166020840152820152606001612e08565b604080516060810182525f808252602082018190529181019190915260035482516201000090910461ffff1660ff90911610801590612ead575060035460208301516001600160401b036401000000009092048216911610155b15612ee857506040805160608101825260035461ffff168152825160ff16602080830191909152909201516001600160401b03169082015290565b611da26040518060400160405280601781526020017f756e736563757265207570646174652072657175657374000000000000000000815250610cf5565b6004545f90606490612f3c9061ffff1682614b19565b61ffff167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166339a8653e856040518263ffffffff1660e01b8152600401612f8e91815260200190565b602060405180830381865afa158015612fa9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fcd9190614781565b612fd79190614b33565b610d959190614b4a565b612fe96125d1565b6001600160a01b038116612dc157604051631e4fbdf760e01b81525f6004820152602401610d61565b5f5f826020015161ffff161180156130335750607f826020015161ffff1611155b8015610d95575050604001516001600160401b0316151590565b606060405180604001604052601a8152806020017f576974507269636546656564734c6567616379446174614c69620000000000008152506040516020016130959190614b5d565b604051602081830303815290604052905090565b6001600160e01b031981165f9081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20160209081526040918290206008908101548351828152610120810190945260609390929091908201610100803683370190505091505f5b6008811015613189578183828151811061312c5761312c614697565b60200260200101906001600160e01b03191690816001600160e01b0319168152505082818151811061316057613160614697565b60209081029190910101516001600160e01b0319161561318957602082901b9150600101613110565b825250919050565b5f5f8351346131a09190614b4a565b90505f5b845181101561326c57306001600160a01b031663abc86c6e838784815181106131cf576131cf614697565b6020908102919091018101516040516001600160e01b031960e086901b811682529091166004820152885160ff166024820152908801516001600160401b0316604482015260640160206040518083038185885af1158015613233573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906132589190614781565b6132629084614b8d565b92506001016131a4565b505092915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f5b6020811015611da2578181602081106132e0576132e0614697565b1a60f81b6001600160f81b03191615611da2576001016132c5565b5f5b6020811015611da25781816020811061331857613318614697565b1a60f81b6001600160f81b03191615611da2576001016132fd565b80356001600160c01b03198116906008841015612360576001600160c01b031960089490940360031b84901b1690921692915050565b6001600160e01b031981168114612079575f5ffd5b5f6020828403121561338e575f5ffd5b81356113a981613369565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561341557601f198584030188526133ff838351613399565b60209889019890935091909101906001016133e3565b50909695505050505050565b606080825284519082018190525f9060208601906080840190835b818110156134645783516001600160e01b03191683526020938401939092019160010161343c565b5050838103602085015261347881876133c7565b848103604086015285518082526020808801945090910191505f5b818110156134b1578351835260209384019390920191600101613493565b5090979650505050505050565b5f5f83601f8401126134ce575f5ffd5b5081356001600160401b038111156134e4575f5ffd5b6020830191508360208285010111156134fb575f5ffd5b9250929050565b6001600160a01b0381168114612079575f5ffd5b5f5f83601f840112613526575f5ffd5b5081356001600160401b0381111561353c575f5ffd5b6020830191508360208260051b85010111156134fb575f5ffd5b5f5f5f5f5f6060868803121561356a575f5ffd5b85356001600160401b0381111561357f575f5ffd5b61358b888289016134be565b909650945050602086013561359f81613502565b925060408601356001600160401b038111156135b9575f5ffd5b6135c588828901613516565b969995985093965092949392505050565b6001600160a01b03831681526040602082018190525f90611b96908301846133c7565b634e487b7160e01b5f52604160045260245ffd5b604081018181106001600160401b038211171561362c5761362c6135f9565b60405250565b608081018181106001600160401b038211171561362c5761362c6135f9565b60a081018181106001600160401b038211171561362c5761362c6135f9565b601f8201601f191681016001600160401b0381118282101715613695576136956135f9565b6040525050565b604051611a4360e082613670565b5f6001600160401b038211156136c2576136c26135f9565b50601f01601f191660200190565b5f6136da836136aa565b6040516136e78282613670565b8092508481528585850111156136fb575f5ffd5b848460208301375f6020868301015250509392505050565b5f60208284031215613723575f5ffd5b81356001600160401b03811115613738575f5ffd5b8201601f81018413613748575f5ffd5b611b96848235602084016136d0565b6020815260ff82511660208201525f6020830151604080840152611b966060840182613399565b602081525f6113a96020830184613399565b6020815260018060a01b03825116602082015262ffffff60208301511660408201525f6040830151608060608401526137cc60a0840182613399565b9050606084015160808401528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b60148110613806576138066137e2565b9052565b60208101610d9582846137f6565b5f60208284031215613828575f5ffd5b81356113a981613502565b60058110613806576138066137e2565b5f82825180855260208501945060208160051b830101602085015f5b8381101561341557848303601f19018852815183604081015f5b60028110156138a7578682038352613892828551613399565b60209485019493909301929150600101613879565b5060209a8b019a9095509390930192505060010161385f565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156139a557603f19878603018452815160ff815116865260208101516139126020880182613833565b50604081015161392560408801826137f6565b50606081015160e0606088015261393f60e0880182613399565b9050608082015187820360808901526139588282613399565b91505060a082015187820360a08901526139728282613843565b91505060c0820151915086810360c088015261398e8183613399565b9650505060209384019391909101906001016138e6565b50929695505050505050565b5f5f5f604084860312156139c3575f5ffd5b83356001600160401b038111156139d8575f5ffd5b6139e4868287016134be565b909790965060209590950135949350505050565b5f5f60208385031215613a09575f5ffd5b82356001600160401b03811115613a1e575f5ffd5b613a2a858286016134be565b90969095509350505050565b5f5f5f5f60408587031215613a49575f5ffd5b84356001600160401b03811115613a5e575f5ffd5b613a6a878288016134be565b90955093505060208501356001600160401b03811115613a88575f5ffd5b613a94878288016134be565b95989497509550505050565b5f60408284031215611d63575f5ffd5b5f5f60608385031215613ac1575f5ffd5b8235613acc81613369565b9150613adb8460208501613aa0565b90509250929050565b5f5f5f60408486031215613af6575f5ffd5b83356001600160401b03811115613b0b575f5ffd5b613b17868287016134be565b9094509250506020840135613b2b81613502565b809150509250925092565b61ffff81168114612079575f5ffd5b5f60208284031215613b55575f5ffd5b81356113a981613b36565b5f60208284031215613b70575f5ffd5b5035919050565b6001600160401b0381511682526001600160401b03602082015116602083015260408101516040830152606081015160048110613bb657613bb66137e2565b806060840152505050565b60808101610d958284613b77565b6020815260018060a01b0382511660208201526001600160401b036020830151166040820152604082015160608201525f606083015160a06080840152613c1960c0840182613399565b608094909401516001600160a01b031660a093909301929092525090919050565b6020810160078310613c4e57613c4e6137e2565b91905290565b5f5f60208385031215613c65575f5ffd5b82356001600160401b03811115613c7a575f5ffd5b613a2a85828601613516565b602080825282518282018190525f918401906040840190835b81811015613cc857613cb2838551613b77565b6020939093019260809290920191600101613c9f565b509095945050505050565b5f60408284031215613ce3575f5ffd5b6113a98383613aa0565b5f81518060208401855e5f93019283525090919050565b5f613d0f8285613ced565b6101d160f51b815261251b6002820185613ced565b5f6001600160401b03821115613d3c57613d3c6135f9565b5060051b60200190565b5f82601f830112613d55575f5ffd5b8151602083015f613d65836136aa565b604051613d728282613670565b809250848152878585011115613d86575f5ffd5b8484602083015e5f60208683010152809550505050505092915050565b5f82601f830112613db2575f5ffd5b8151613dbd81613d24565b604051613dca8282613670565b80915082815260208101915060208360051b860101925085831115613ded575f5ffd5b602085015b83811015613e2d5780516001600160401b03811115613e0f575f5ffd5b613e1e886020838a0101613d46565b84525060209283019201613df2565b5095945050505050565b5f82601f830112613e46575f5ffd5b8151613e5181613d24565b604051613e5e8282613670565b80915082815260208101915060208360051b860101925085831115613e81575f5ffd5b602085015b83811015613e2d578051835260209283019201613e86565b5f5f5f60608486031215613eb0575f5ffd5b83516001600160401b03811115613ec5575f5ffd5b8401601f81018613613ed5575f5ffd5b8051613ee081613d24565b604051613eed8282613670565b80915082815260208101915060208360051b850101925088831115613f10575f5ffd5b6020840193505b82841015613f3b578351613f2a81613369565b825260209384019390910190613f17565b8096505050505060208401516001600160401b03811115613f5a575f5ffd5b613f6686828701613da3565b92505060408401516001600160401b03811115613f81575f5ffd5b613f8d86828701613e37565b9150509250925092565b80356001600160d01b03198116906006841015612360576001600160d01b031960069490940360031b84901b1690921692915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f5f8335601e1984360301811261400a575f5ffd5b83016020810192503590506001600160401b03811115614028575f5ffd5b8036038213156134fb575f5ffd5b606081525f614049606083018789613fcd565b6001600160a01b038616602084810191909152838203604085015284825281810190600586901b830101865f5b878110156140b457848303601f19018452614091828a613ff5565b61409c858284613fcd565b60209687019690955093909301925050600101614076565b50909a9950505050505050505050565b5f60033d1115611a435760045f5f3e505f5160e01c90565b5f60443d10156140e95790565b6040513d600319016004823e80513d60248201116001600160401b038211171561411257505090565b80820180516001600160401b0381111561412d575050505090565b3d8401600319018282016020011115614147575050505090565b61415660208285010185613670565b509392505050565b5f5f6040838503121561416f575f5ffd5b825161417a81613502565b60208401519092506001600160401b03811115614195575f5ffd5b6141a185828601613d46565b9150509250929050565b60ff81168114612079575f5ffd5b8051611da2816141ab565b5f602082840312156141d4575f5ffd5b81516001600160401b038111156141e9575f5ffd5b8201604081850312156141fa575f5ffd5b6040516142068161360d565b8151614211816141ab565b815260208201516001600160401b0381111561422b575f5ffd5b61423786828501613d46565b602083015250949350505050565b5f60208284031215614255575f5ffd5b81516001600160401b0381111561426a575f5ffd5b611b9684828501613d46565b5f60208284031215614286575f5ffd5b81516001600160401b0381111561429b575f5ffd5b8201608081850312156142ac575f5ffd5b6040516142b881613632565b81516142c381613502565b8152602082015162ffffff811681146142da575f5ffd5b602082015260408201516001600160401b038111156142f7575f5ffd5b61430386828501613d46565b604083015250606091820151918101919091529392505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821602908116908181146123605761236061431d565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b0383168061437f5761437f614353565b806001600160401b0384160491505092915050565b805160058110611da2575f5ffd5b805160148110611da2575f5ffd5b5f82601f8301126143bf575f5ffd5b81516143ca81613d24565b6040516143d78282613670565b80915082815260208101915060208360051b8601019250858311156143fa575f5ffd5b602085015b83811015613e2d5780516001600160401b0381111561441c575f5ffd5b8601603f8101881361442c575f5ffd5b6040516144388161360d565b80606083018a811115614449575f5ffd5b602084015b818110156144895780516001600160401b0381111561446b575f5ffd5b61447a8d602083890101613d46565b8452506020928301920161444e565b505050845250602092830192016143ff565b5f602082840312156144ab575f5ffd5b81516001600160401b038111156144c0575f5ffd5b8201601f810184136144d0575f5ffd5b80516144db81613d24565b6040516144e88282613670565b80915082815260208101915060208360051b85010192508683111561450b575f5ffd5b602084015b8381101561463d5780516001600160401b0381111561452d575f5ffd5b850160e0818a03601f19011215614542575f5ffd5b61454a61369c565b614556602083016141b9565b815261456460408301614394565b6020820152614575606083016143a2565b604082015260808201516001600160401b03811115614592575f5ffd5b6145a18b602083860101613d46565b60608301525060a08201516001600160401b038111156145bf575f5ffd5b6145ce8b602083860101613d46565b60808301525060c08201516001600160401b038111156145ec575f5ffd5b6145fb8b6020838601016143b0565b60a08301525060e08201516001600160401b03811115614619575f5ffd5b6146288b602083860101613d46565b60c08301525084525060209283019201614510565b509695505050505050565b5f60208284031215614658575f5ffd5b6113a9826143a2565b604081525f614674604083018587613fcd565b9050826020830152949350505050565b602081525f611b96602083018486613fcd565b634e487b7160e01b5f52603260045260245ffd5b604081525f6146be604083018688613fcd565b82810360208401526146d1818587613fcd565b979650505050505050565b5f602082840312156146ec575f5ffd5b81516113a981613502565b60018060a01b0385168152836020820152606060408201525f61471e606083018486613fcd565b9695505050505050565b6001600160401b0381168114612079575f5ffd5b5f604082840312801561474d575f5ffd5b5060405161475a8161360d565b8235614765816141ab565b8152602083013561477581614728565b60208201529392505050565b5f60208284031215614791575f5ffd5b5051919050565b5f60808284031280156147a9575f5ffd5b506040516147b681613632565b82516147c181614728565b815260208301516147d181614728565b6020820152604083810151908201526060830151600481106147f1575f5ffd5b60608201529392505050565b600181811c9082168061481157607f821691505b602082108103611d6357634e487b7160e01b5f52602260045260245ffd5b5f6020828403121561483f575f5ffd5b81516001600160401b03811115614854575f5ffd5b820160a08185031215614865575f5ffd5b60405161487181613651565b815161487c81613502565b8152602082015161488c81614728565b60208201526040828101519082015260608201516001600160401b038111156148b3575f5ffd5b6148bf86828501613d46565b606083015250608082015191506148d582613502565b60808101919091529392505050565b5f602082840312156148f4575f5ffd5b8151600781106113a9575f5ffd5b5f60208284031215614912575f5ffd5b81356113a9816141ab565b5f6020828403121561492d575f5ffd5b81356113a981614728565b5f8383855260208501945060208460051b820101835f5b8681101561341557838303601f1901885261496a8287613ff5565b614975858284613fcd565b60209a8b019a9095509390930192505060010161494f565b602080825281018290525f6040600584901b830181019083018583601e1936839003015b87821015614a2157868503603f1901845282358181126149cf575f5ffd5b89016020810190356001600160401b038111156149ea575f5ffd5b8060051b36038213156149fb575f5ffd5b614a06878284614938565b965050506020830192506020840193506001820191506149b1565b5092979650505050505050565b5f60208284031215614a3e575f5ffd5b815161010081106113a9575f5ffd5b5f5f60408385031215614a5e575f5ffd5b505080516020909101519092909150565b81810381811115610d9557610d9561431d565b5f5f8284036080811215614a94575f5ffd5b8351614a9f81613b36565b92506060601f1982011215614ab2575f5ffd5b50604051606081018181106001600160401b0382111715614ad557614ad56135f9565b6040526020840151614ae681613b36565b81526040840151614af681613b36565b60208201526060840151614b0981614728565b6040820152919491935090915050565b61ffff8181168382160190811115610d9557610d9561431d565b8082028115828204841417610d9557610d9561431d565b5f82614b5857614b58614353565b500490565b5f614b688284613ced565b741d103ab73430b7323632b21030b9b9b2b93a34b7b760591b81526015019392505050565b80820180821115610d9557610d9561431d56fea264697066735822122023b0f08cbec12bb0db06fb1b0218498ee6638b309de7c701f6a549cf6688fafc64736f6c634300081e003300000000000000000000000077703ae126b971c9946d562f41dd47071da00777322e322e382d666462376631652d6232396439303500000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x60806040526004361061034f575f3560e01c80638da5cb5b116101c5578063d3471e34116100f6578063f14cb81211610094578063f9f34bb61161006e578063f9f34bb614610c21578063fae91a5114610c4d578063ff24fb4f14610c6c578063ff75890f14610c8b5761034f565b8063f14cb81214610b9c578063f2fde38b14610bc8578063f78eea8314610be75761034f565b8063e1c9e3c0116100d0578063e1c9e3c014610b33578063e30c397814610b47578063eb92b29b14610b5b578063ef1dff2b14610b7d5761034f565b8063d3471e3414610aae578063d5f3948814610acd578063d6a3614f14610b005761034f565b8063b411ee9411610163578063c064d3721161013d578063c064d37214610a18578063c3d98ea814610a37578063c5010d1714610a63578063cfae692914610a825761034f565b8063b411ee9414610995578063b8d38c96146109b4578063bff852fa146109d35761034f565b8063a9e954b91161019f578063a9e954b914610917578063abc86c6e1461094a578063ac82c6081461095d578063adb7c3f71461097c5761034f565b80638da5cb5b146108bd5780638df3fdfd146108d9578063a55b471c146108f85761034f565b806354fd4d501161029f578063715018a61161023d578063806d7e8f11610217578063806d7e8f1461082657806384292f071461085257806386ac03e0146108715780638a416ea9146108905761034f565b8063715018a6146107ea57806375dadb32146107fe57806379ba5097146108125761034f565b80636175ff00116102795780636175ff00146106e45780636ab221f8146107245780636b58960a146107555780636d1178e5146107745761034f565b806354fd4d50146106855780635be93984146106995780635c0d9d80146106b85761034f565b8063439fab911161030c5780634efef9c0116102e65780634efef9c0146105b65780635001f3b5146105e257806352d1902d146106145780635479d940146106475761034f565b8063439fab911461053957806346d1d21a1461055857806349492ef11461058a5761034f565b8063029db9581461043a5780630306732e1461046c57806303f3813d1461048f5780631014d375146104ae578063384ac938146104f95780633e088e1214610526575b34801561035a575f5ffd5b505f356001600160e01b03191663e0d20f7360e01b14801561037b57503330145b15610408575f6103a160206103903684613333565b6001600160c01b031916901b610caa565b6006015460408051808201909152601081526f3ab739b2ba3a3632b21039b7b63b32b960811b60208201526001600160a01b0390911691506103e69082151590610ce3565b604051365f82375f5f3683855af43d805f843e818015610404578184f35b8184fd5b6104386040518060400160405280600f81526020016e1b9bdd081a5b5c1b195b595b9d1959608a1b815250610cf5565b005b348015610445575f5ffd5b5061045961045436600461337e565b610d6a565b6040519081526020015b60405180910390f35b348015610477575f5ffd5b50610480610d9b565b60405161046393929190613421565b34801561049a575f5ffd5b506104386104a9366004613556565b610e18565b3480156104b9575f5ffd5b506104e17f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077781565b6040516001600160a01b039091168152602001610463565b348015610504575f5ffd5b5061051861051336600461337e565b610fb1565b6040516104639291906135d6565b61045961053436600461337e565b610fc6565b348015610544575f5ffd5b50610438610553366004613713565b61100c565b348015610563575f5ffd5b507f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776104e1565b348015610595575f5ffd5b506105a96105a436600461337e565b611240565b6040516104639190613757565b3480156105c1575f5ffd5b506105d56105d036600461337e565b6112eb565b604051610463919061377e565b3480156105ed575f5ffd5b507f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84806104e1565b34801561061f575f5ffd5b506104597f688a557b3c9b52d2ba2301577897f3d892372d2d9be386db46c3ca9048c47f0b81565b348015610652575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000015b6040519015158152602001610463565b348015610690575f5ffd5b506105d56113b0565b3480156106a4575f5ffd5b506104596106b336600461337e565b6113e0565b3480156106c3575f5ffd5b506106d76106d236600461337e565b6113f4565b6040516104639190613790565b3480156106ef575f5ffd5b506107177f000000000000000000000000000000000000000000000000000000000000000481565b604051610463919061380a565b34801561072f575f5ffd5b5061074361073e36600461337e565b6114ca565b60405160ff9091168152602001610463565b348015610760575f5ffd5b5061067561076f366004613818565b6114e1565b34801561077f575f5ffd5b5061078861153a565b60405161046391905f60a08201905060ff835116825260ff60208401511660208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526001600160401b03608084015116608083015292915050565b3480156107f5575f5ffd5b506104386115de565b348015610809575f5ffd5b506105d56115f1565b34801561081d575f5ffd5b5061043861161c565b348015610831575f5ffd5b5061084561084036600461337e565b611624565b60405161046391906138c0565b34801561085d575f5ffd5b5061043861086c3660046139b1565b6116a4565b34801561087c575f5ffd5b5061043861088b3660046139f8565b611873565b34801561089b575f5ffd5b506108a4611948565b6040516001600160e01b03199091168152602001610463565b3480156108c8575f5ffd5b505f546001600160a01b03166104e1565b3480156108e4575f5ffd5b506104596108f336600461337e565b611a46565b348015610903575f5ffd5b506104e1610912366004613a36565b611a5a565b348015610922575f5ffd5b507f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84803f610459565b610459610958366004613ab0565b611b9e565b348015610968575f5ffd5b50610438610977366004613ae4565b611bbf565b348015610987575f5ffd5b506331f74adb60e11b6108a4565b3480156109a0575f5ffd5b506108a46109af366004613713565b611c2c565b3480156109bf575f5ffd5b506104386109ce366004613b45565b611c3a565b3480156109de575f5ffd5b5060408051808201909152601d81527f576974507269636546656564734c656761637955706772616461626c6500000060208201526105d5565b348015610a23575f5ffd5b50610459610a32366004613b60565b611c5a565b348015610a42575f5ffd5b50610a56610a5136600461337e565b611c64565b6040516104639190613bc1565b348015610a6e575f5ffd5b50610675610a7d3660046139f8565b611da7565b348015610a8d575f5ffd5b50610aa1610a9c36600461337e565b611e9f565b6040516104639190613bcf565b348015610ab9575f5ffd5b50610aa1610ac836600461337e565b611f89565b348015610ad8575f5ffd5b506104e17f00000000000000000000000003232abe800d1638b30432feef300581de323a4e81565b348015610b0b575f5ffd5b507fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20054610459565b348015610b3e575f5ffd5b50610438611fea565b348015610b52575f5ffd5b506104e16120b5565b348015610b66575f5ffd5b5060045460405161ffff9091168152602001610463565b348015610b88575f5ffd5b506105d5610b9736600461337e565b6120c8565b348015610ba7575f5ffd5b50610bbb610bb636600461337e565b612161565b6040516104639190613c3a565b348015610bd3575f5ffd5b50610438610be2366004613818565b6121f7565b348015610bf2575f5ffd5b50610c06610c01366004613b60565b612208565b60408051938452602084019290925290820152606001610463565b348015610c2c575f5ffd5b50610c40610c3b366004613c54565b612292565b6040516104639190613c86565b348015610c58575f5ffd5b50610438610c67366004613cd3565b612367565b348015610c77575f5ffd5b50610438610c86366004613556565b612443565b348015610c96575f5ffd5b506104e1610ca5366004613a36565b61249a565b6001600160e01b0319165f9081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d2016020526040902090565b81610cf157610cf181610cf5565b5050565b60408051808201909152601d81527f576974507269636546656564734c656761637955706772616461626c65000000602082015281604051602001610d3b929190613d04565b60408051601f198184030181529082905262461bcd60e51b8252610d619160040161377e565b60405180910390fd5b5f610d957f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077783612524565b92915050565b606080606073bffa2ec6225390c517a1beb83b27a171c6734294630306732e6040518163ffffffff1660e01b81526004015f60405180830381865af4158015610de6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e0d9190810190613e9e565b925092509250909192565b610e206125d1565b610e936001600160d01b03197f50726963652d000000000000000000000000000000000000000000000000000016610e588688613f97565b6001600160d01b03191614604051806040016040528060128152602001710c4c2c840c6c2e0e8d2dedc40e0e4caccd2f60731b815250610ce3565b6040805180820190915260118152706e6f20736f6c766572206164647265737360781b6020820152610ed1906001600160a01b038516151590610ce3565b6040516303f3813d60e01b815273bffa2ec6225390c517a1beb83b27a171c6734294906303f3813d90610f109088908890889088908890600401614036565b5f6040518083038186803b158015610f26575f5ffd5b505af4925050508015610f37575060015b610faa57610f436140c4565b806308c379a003610f715750610f576140dc565b80610f625750610f73565b610f6b81610cf5565b50610faa565b505b3d808015610f9c576040519150601f19603f3d011682016040523d82523d5f602084013e610fa1565b606091505b50610f6b6125fd565b5050505050565b5f6060610fbd8361260d565b91509150915091565b6040805160608101825260035461ffff808216835262010000820416602083015264010000000090046001600160401b0316918101919091525f90610d95908390612763565b5f546001600160a01b0316806110425781806020019051810190611030919061415e565b9250905061103d816129e6565b61108a565b336001600160a01b0382161461108a5760405162461bcd60e51b815260206004820152600d60248201526c3737ba103a34329037bbb732b960991b6044820152606401610d61565b611093826129ff565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe541580159061110457507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe547f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84803f145b156111515760405162461bcd60e51b815260206004820152601c60248201527f616c726561647920696e697469616c697a656420636f646568617368000000006044820152606401610d61565b7f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84803f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600201557f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84803f7f000000000000000000000000e7a932b4d8f62d9e11e785062f0bfecad54f84806001600160a01b03166111f55f546001600160a01b031690565b6001600160a01b03167fe73e754121f0bad1327816970101955bfffdf53d270ac509d777c25be070d7f66112276113b0565b604051611234919061377e565b60405180910390a45050565b604080518082019091525f8152606060208201527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663a77fc1a461128c846113e0565b6040518263ffffffff1660e01b81526004016112aa91815260200190565b5f60405180830381865afa1580156112c4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d9591908101906141c4565b60605f6112f783610caa565b905061132f81600501545f5f1b14156040518060400160405280600b81526020016a0dcde40a4828840d0c2e6d60ab1b815250610ce3565b611337612b8c565b6001600160a01b0316638a22776482600501546040518263ffffffff1660e01b815260040161136891815260200190565b5f60405180830381865afa158015611382573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526113a99190810190614245565b9392505050565b60606113db7f322e322e382d666462376631652d623239643930350000000000000000000000612c0d565b905090565b5f6113ea82610caa565b6004015492915050565b61142a60405180608001604052805f6001600160a01b031681526020015f62ffffff168152602001606081526020015f81525090565b7f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663a667533f611462846113e0565b6040516001600160e01b031960e084901b1681526001600160401b0390911660048201526024015f60405180830381865afa1580156114a3573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d959190810190614276565b5f6114d482610caa565b6001015460ff1692915050565b5f5f6114f45f546001600160a01b031690565b90507f000000000000000000000000000000000000000000000000000000000000000180156113a95750826001600160a01b0316816001600160a01b0316149392505050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091526003546040805160a08101825262010000830460ff8116808352603360208401526401000000009094046001600160401b031692820183905261ffff169260608201906115b19084614331565b6001600160401b031681526020016115cc60ff851684614367565b6001600160401b031690529392505050565b6115e66125d1565b6115ef5f6129e6565b565b60606113db7f50726963652d0000000000000000000000000000000000000000000000000000612cae565b6115ef612d4f565b606061162e612b8c565b6001600160a01b03166377c1125961164584611a46565b6040518263ffffffff1660e01b815260040161166391815260200190565b5f60405180830381865afa15801561167d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d95919081019061449b565b6116ac6125d1565b6117997f000000000000000000000000000000000000000000000000000000000000000460138111156116e1576116e16137e2565b6116e9612b8c565b6001600160a01b0316634c729104846040518263ffffffff1660e01b815260040161171691815260200190565b602060405180830381865afa158015611731573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117559190614648565b6013811115611766576117666137e2565b146040518060400160405280601481526020017362616420726573756c742064617461207479706560601b815250610ce3565b6040516384292f0760e01b815273bffa2ec6225390c517a1beb83b27a171c6734294906384292f07906117d490869086908690600401614661565b5f6040518083038186803b1580156117ea575f5ffd5b505af49250505080156117fb575060015b61186e576118076140c4565b806308c379a003611835575061181b6140dc565b806118265750611837565b61182f81610cf5565b50505050565b505b3d808015611860576040519150601f19603f3d011682016040523d82523d5f602084013e611865565b606091505b5061182f6125fd565b505050565b61187b6125d1565b604051630435601f60e51b815273bffa2ec6225390c517a1beb83b27a171c6734294906386ac03e0906118b49085908590600401614684565b5f6040518083038186803b1580156118ca575f5ffd5b505af49250505080156118db575060015b610cf1576118e76140c4565b806308c379a00361190f57506118fb6140dc565b806119065750611911565b61186e81610cf5565b505b3d80801561193a576040519150601f19603f3d011682016040523d82523d5f602084013e61193f565b606091505b5061186e6125fd565b7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d200545f9015611a43576119cf7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff6001015f815481106119a9576119a9614697565b905f5260205f2090600891828204019190066004029054906101000a900460e01b612dca565b905060015b7fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20054811015611a4157611a357fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff60010182815481106119a9576119a9614697565b909118906001016119d4565b505b90565b5f611a5082610caa565b6005015492915050565b5f611a636125d1565b604051632956d1c760e21b815273bffa2ec6225390c517a1beb83b27a171c67342949063a55b471c90611aa09088908890889088906004016146ab565b602060405180830381865af4925050508015611ad9575060408051601f3d908101601f19168201909252611ad6918101906146dc565b60015b611b4c57611ae56140c4565b806308c379a003611b135750611af96140dc565b80611b045750611b15565b611b0d81610cf5565b50611b96565b505b3d808015611b3e576040519150601f19603f3d011682016040523d82523d5f602084013e611b43565b606091505b50611b0d6125fd565b7f18678abae9a91a452648053bebd7d23122fb9204cddc206fa8193750abb8940f81826001600160a01b03163f8686604051611b8b94939291906146f7565b60405180910390a190505b949350505050565b5f6113a983611bba611bb53686900386018661473c565b612e53565b612763565b611bc76125d1565b61186e8383836001600160a01b0316631eef90526040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c08573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086c9190614781565b805160208201205f90610d95565b611c426125d1565b6004805461ffff191661ffff92909216919091179055565b5f610d9582612f26565b611c8b604080516080810182525f8082526020820181905291810182905290606082015290565b6040516384ee241160e01b81526001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771660048201526001600160e01b03198316602482015273bffa2ec6225390c517a1beb83b27a171c6734294906384ee241190604401608060405180830381865af4925050508015611d2f575060408051601f3d908101601f19168201909252611d2c91810190614798565b60015b610d9557611d3b6140c4565b806308c379a003611d695750611d4f6140dc565b80611d5a5750611d6b565b611d6381610cf5565b50919050565b505b3d808015611d94576040519150601f19603f3d011682016040523d82523d5f602084013e611d99565b606091505b50611d636125fd565b919050565b5f5f611de784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611c2c92505050565b90506001600160e01b03198116611e8c611e0083610caa565b8054611e0b906147fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611e37906147fd565b8015611e825780601f10611e5957610100808354040283529160200191611e82565b820191905f5260205f20905b815481529060010190602001808311611e6557829003601f168201915b5050505050611c2c565b6001600160e01b03191614949350505050565b6040805160a0810182525f8082526020820181905291810182905260608082015260808101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663ca7da98b611f217f00000000000000000000000077703ae126b971c9946d562f41dd47071da0077785612524565b6040516001600160e01b031960e084901b1681526001600160401b0390911660048201526024015f60405180830381865afa158015611f62573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d95919081019061482f565b6040805160a0810182525f8082526020820181905291810182905260608082015260808101919091527f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663ca7da98b611f21846113e0565b611ff26125d1565b73bffa2ec6225390c517a1beb83b27a171c673429463e1c9e3c06040518163ffffffff1660e01b81526004015f6040518083038186803b158015612034575f5ffd5b505af4925050508015612045575060015b6115ef576120516140c4565b806308c379a00361207c57506120656140dc565b80612070575061207e565b61207981610cf5565b50565b505b3d8080156120a7576040519150601f19603f3d011682016040523d82523d5f602084013e6120ac565b606091505b506120796125fd565b5f6113db6001546001600160a01b031690565b60606120d382610caa565b80546120de906147fd565b80601f016020809104026020016040519081016040528092919081815260200182805461210a906147fd565b80156121555780601f1061212c57610100808354040283529160200191612155565b820191905f5260205f20905b81548152906001019060200180831161213857829003601f168201915b50505050509050919050565b5f7f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b031663234fe6e361219a846113e0565b6040518263ffffffff1660e01b81526004016121b891815260200190565b602060405180830381865afa1580156121d3573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9591906148e4565b6121ff6125d1565b61207981612fe1565b5f5f5f5f61221585611c64565b805160208201519192506001600160401b031690600283606001516003811115612241576122416137e2565b146122735760018360600151600381111561225e5761225e6137e2565b1461226b57610190612276565b610194612276565b60c85b9195506001600160401b0316935061ffff169150509193909250565b6060816001600160401b038111156122ac576122ac6135f9565b60405190808252806020026020018201604052801561230457816020015b6122f1604080516080810182525f8082526020820181905291810182905290606082015290565b8152602001906001900390816122ca5790505b5090505f5b828110156123605761233b84848381811061232657612326614697565b9050602002016020810190610a51919061337e565b82828151811061234d5761234d614697565b6020908102919091010152600101612309565b5092915050565b61236f6125d1565b61237c6020820182614902565b6003805463ffff0000191660ff9290921662010000029190911790556123a8604082016020830161491d565b600380546001600160401b039283166401000000009081026bffffffffffffffff000000001983168117938490556040805160608101825261ffff92831694831694909417845262010000850490911660208401529204909216908201526120799061241390613012565b60405180604001604052806012815260200171696e76616c69642075706461746520534c4160701b815250610ce3565b61244b6125d1565b610faa8585856001600160a01b031663bf7a0bd386866040518363ffffffff1660e01b815260040161247e92919061498d565b6020604051808303815f875af1158015611c08573d5f5f3e3d5ffd5b6040516001628a76f160e01b031981525f9073bffa2ec6225390c517a1beb83b27a171c67342949063ff75890f906124dc9088908890889088906004016146ab565b602060405180830381865af41580156124f7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061251b91906146dc565b95945050505050565b5f61252e82610caa565b6004015490508015806125b857505f604051634cddf61560e01b8152600481018390526001600160a01b03851690634cddf61590602401602060405180830381865afa158015612580573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a49190614a2e565b60ff8111156125b5576125b56137e2565b14155b15610d95576125c682610caa565b600301549392505050565b5f546001600160a01b031633146115ef5760405163118cdaa760e01b8152336004820152602401610d61565b6115ef61260861304d565b610cf5565b5f606061261983610caa565b600601546001600160a01b031691505f612632846130a9565b905080516001600160401b0381111561264d5761264d6135f9565b60405190808252806020026020018201604052801561268057816020015b606081526020019060019003908161266b5790505b5091505f5b815181101561275c576126b08282815181106126a3576126a3614697565b6020026020010151610caa565b80546126bb906147fd565b80601f01602080910402602001604051908101604052809291908181526020018280546126e7906147fd565b80156127325780601f1061270957610100808354040283529160200191612732565b820191905f5260205f20905b81548152906001019060200180831161271557829003601f168201915b505050505083828151811061274957612749614697565b6020908102919091010152600101612685565b5050915091565b5f61276d83610caa565b600501541561295c57604080516303f8890160e11b81526001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771660048201526001600160e01b031985166024820152835161ffff90811660448301526020850151166064820152908301516001600160401b031660848201523460a482018190529073bffa2ec6225390c517a1beb83b27a171c6734294906307f112029060c4016040805180830381865af492505050801561284d575060408051601f3d908101601f1916820190925261284a91810190614a4d565b60015b6128c0576128596140c4565b806308c379a003612887575061286d6140dc565b806128785750612889565b61288181610cf5565b50612956565b505b3d8080156128b2576040519150601f19603f3d011682016040523d82523d5f602084013e6128b7565b606091505b506128816125fd565b348110156128fd57336108fc6128d68334614a6f565b6040518115909202915f818181858888f193505050501580156128fb573d5f5f3e3d5ffd5b505b604080513281523360208201526001600160e01b03198816818301526060810184905290517f0bd652a116bb5006c2e07594e8a3fe9b5ba51acf6cd9572568913fda51ad26c49181900360800190a19250610d95915050565b50610d95565b5f61296684610caa565b600601546001600160a01b0316146129b9576129b2612984846130a9565b6040518060400160405280856020015160ff16815260200185604001516001600160401b0316815250613191565b9050610d95565b610d956040518060400160405280600c81526020016b1d5b9adb9bdddb881999595960a21b815250610cf5565b600180546001600160a01b031916905561207981613274565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbe54612a76576040805160608101825260108152600360208201819052630bebc20091909201528054670bebc200000300106bffffffffffffffffffffffff199091161790556004805461ffff1916600a17905550565b805115612b05575f5f82806020019051810190612a939190614a82565b6004805461ffff93841661ffff1990911617905580516003805460208401516040909401516001600160401b0316640100000000026bffffffffffffffff0000000019948616620100000263ffffffff1990921693909516929092179190911791909116919091179055506120799050565b6040805160608101825260035461ffff808216835262010000820416602083015264010000000090046001600160401b031691810191909152612b4790613012565b61207957506040805160608101825260108152600360208201819052630bebc200919092015280546bffffffffffffffffffffffff1916670bebc20000030010179055565b5f7f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612be9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113db91906146dc565b60605f612c19836132c3565b6001600160401b03811115612c3057612c306135f9565b6040519080825280601f01601f191660200182016040528015612c5a576020820181803683370190505b5090505f5b815181101561236057838160208110612c7a57612c7a614697565b1a60f81b828281518110612c9057612c90614697565b60200101906001600160f81b03191690815f1a905350600101612c5f565b60605f612cba836132fb565b6001600160401b03811115612cd157612cd16135f9565b6040519080825280601f01601f191660200182016040528015612cfb576020820181803683370190505b5090505f5b815181101561236057838160208110612d1b57612d1b614697565b1a60f81b828281518110612d3157612d31614697565b60200101906001600160f81b03191690815f1a905350600101612d00565b3380612d596120b5565b6001600160a01b031614612dc15760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610d61565b612079816129e6565b5f80612dd583610caa565b6005015414612e255781612de883610caa565b60050154604080516001600160e01b031990931660208401528201526060015b604051602081830303815290604052805190602001209050919050565b81612e2f83610caa565b60080154604080516001600160e01b03199093166020840152820152606001612e08565b604080516060810182525f808252602082018190529181019190915260035482516201000090910461ffff1660ff90911610801590612ead575060035460208301516001600160401b036401000000009092048216911610155b15612ee857506040805160608101825260035461ffff168152825160ff16602080830191909152909201516001600160401b03169082015290565b611da26040518060400160405280601781526020017f756e736563757265207570646174652072657175657374000000000000000000815250610cf5565b6004545f90606490612f3c9061ffff1682614b19565b61ffff167f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03166339a8653e856040518263ffffffff1660e01b8152600401612f8e91815260200190565b602060405180830381865afa158015612fa9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fcd9190614781565b612fd79190614b33565b610d959190614b4a565b612fe96125d1565b6001600160a01b038116612dc157604051631e4fbdf760e01b81525f6004820152602401610d61565b5f5f826020015161ffff161180156130335750607f826020015161ffff1611155b8015610d95575050604001516001600160401b0316151590565b606060405180604001604052601a8152806020017f576974507269636546656564734c6567616379446174614c69620000000000008152506040516020016130959190614b5d565b604051602081830303815290604052905090565b6001600160e01b031981165f9081527fe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d20160209081526040918290206008908101548351828152610120810190945260609390929091908201610100803683370190505091505f5b6008811015613189578183828151811061312c5761312c614697565b60200260200101906001600160e01b03191690816001600160e01b0319168152505082818151811061316057613160614697565b60209081029190910101516001600160e01b0319161561318957602082901b9150600101613110565b825250919050565b5f5f8351346131a09190614b4a565b90505f5b845181101561326c57306001600160a01b031663abc86c6e838784815181106131cf576131cf614697565b6020908102919091018101516040516001600160e01b031960e086901b811682529091166004820152885160ff166024820152908801516001600160401b0316604482015260640160206040518083038185885af1158015613233573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906132589190614781565b6132629084614b8d565b92506001016131a4565b505092915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f5b6020811015611da2578181602081106132e0576132e0614697565b1a60f81b6001600160f81b03191615611da2576001016132c5565b5f5b6020811015611da25781816020811061331857613318614697565b1a60f81b6001600160f81b03191615611da2576001016132fd565b80356001600160c01b03198116906008841015612360576001600160c01b031960089490940360031b84901b1690921692915050565b6001600160e01b031981168114612079575f5ffd5b5f6020828403121561338e575f5ffd5b81356113a981613369565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561341557601f198584030188526133ff838351613399565b60209889019890935091909101906001016133e3565b50909695505050505050565b606080825284519082018190525f9060208601906080840190835b818110156134645783516001600160e01b03191683526020938401939092019160010161343c565b5050838103602085015261347881876133c7565b848103604086015285518082526020808801945090910191505f5b818110156134b1578351835260209384019390920191600101613493565b5090979650505050505050565b5f5f83601f8401126134ce575f5ffd5b5081356001600160401b038111156134e4575f5ffd5b6020830191508360208285010111156134fb575f5ffd5b9250929050565b6001600160a01b0381168114612079575f5ffd5b5f5f83601f840112613526575f5ffd5b5081356001600160401b0381111561353c575f5ffd5b6020830191508360208260051b85010111156134fb575f5ffd5b5f5f5f5f5f6060868803121561356a575f5ffd5b85356001600160401b0381111561357f575f5ffd5b61358b888289016134be565b909650945050602086013561359f81613502565b925060408601356001600160401b038111156135b9575f5ffd5b6135c588828901613516565b969995985093965092949392505050565b6001600160a01b03831681526040602082018190525f90611b96908301846133c7565b634e487b7160e01b5f52604160045260245ffd5b604081018181106001600160401b038211171561362c5761362c6135f9565b60405250565b608081018181106001600160401b038211171561362c5761362c6135f9565b60a081018181106001600160401b038211171561362c5761362c6135f9565b601f8201601f191681016001600160401b0381118282101715613695576136956135f9565b6040525050565b604051611a4360e082613670565b5f6001600160401b038211156136c2576136c26135f9565b50601f01601f191660200190565b5f6136da836136aa565b6040516136e78282613670565b8092508481528585850111156136fb575f5ffd5b848460208301375f6020868301015250509392505050565b5f60208284031215613723575f5ffd5b81356001600160401b03811115613738575f5ffd5b8201601f81018413613748575f5ffd5b611b96848235602084016136d0565b6020815260ff82511660208201525f6020830151604080840152611b966060840182613399565b602081525f6113a96020830184613399565b6020815260018060a01b03825116602082015262ffffff60208301511660408201525f6040830151608060608401526137cc60a0840182613399565b9050606084015160808401528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b60148110613806576138066137e2565b9052565b60208101610d9582846137f6565b5f60208284031215613828575f5ffd5b81356113a981613502565b60058110613806576138066137e2565b5f82825180855260208501945060208160051b830101602085015f5b8381101561341557848303601f19018852815183604081015f5b60028110156138a7578682038352613892828551613399565b60209485019493909301929150600101613879565b5060209a8b019a9095509390930192505060010161385f565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156139a557603f19878603018452815160ff815116865260208101516139126020880182613833565b50604081015161392560408801826137f6565b50606081015160e0606088015261393f60e0880182613399565b9050608082015187820360808901526139588282613399565b91505060a082015187820360a08901526139728282613843565b91505060c0820151915086810360c088015261398e8183613399565b9650505060209384019391909101906001016138e6565b50929695505050505050565b5f5f5f604084860312156139c3575f5ffd5b83356001600160401b038111156139d8575f5ffd5b6139e4868287016134be565b909790965060209590950135949350505050565b5f5f60208385031215613a09575f5ffd5b82356001600160401b03811115613a1e575f5ffd5b613a2a858286016134be565b90969095509350505050565b5f5f5f5f60408587031215613a49575f5ffd5b84356001600160401b03811115613a5e575f5ffd5b613a6a878288016134be565b90955093505060208501356001600160401b03811115613a88575f5ffd5b613a94878288016134be565b95989497509550505050565b5f60408284031215611d63575f5ffd5b5f5f60608385031215613ac1575f5ffd5b8235613acc81613369565b9150613adb8460208501613aa0565b90509250929050565b5f5f5f60408486031215613af6575f5ffd5b83356001600160401b03811115613b0b575f5ffd5b613b17868287016134be565b9094509250506020840135613b2b81613502565b809150509250925092565b61ffff81168114612079575f5ffd5b5f60208284031215613b55575f5ffd5b81356113a981613b36565b5f60208284031215613b70575f5ffd5b5035919050565b6001600160401b0381511682526001600160401b03602082015116602083015260408101516040830152606081015160048110613bb657613bb66137e2565b806060840152505050565b60808101610d958284613b77565b6020815260018060a01b0382511660208201526001600160401b036020830151166040820152604082015160608201525f606083015160a06080840152613c1960c0840182613399565b608094909401516001600160a01b031660a093909301929092525090919050565b6020810160078310613c4e57613c4e6137e2565b91905290565b5f5f60208385031215613c65575f5ffd5b82356001600160401b03811115613c7a575f5ffd5b613a2a85828601613516565b602080825282518282018190525f918401906040840190835b81811015613cc857613cb2838551613b77565b6020939093019260809290920191600101613c9f565b509095945050505050565b5f60408284031215613ce3575f5ffd5b6113a98383613aa0565b5f81518060208401855e5f93019283525090919050565b5f613d0f8285613ced565b6101d160f51b815261251b6002820185613ced565b5f6001600160401b03821115613d3c57613d3c6135f9565b5060051b60200190565b5f82601f830112613d55575f5ffd5b8151602083015f613d65836136aa565b604051613d728282613670565b809250848152878585011115613d86575f5ffd5b8484602083015e5f60208683010152809550505050505092915050565b5f82601f830112613db2575f5ffd5b8151613dbd81613d24565b604051613dca8282613670565b80915082815260208101915060208360051b860101925085831115613ded575f5ffd5b602085015b83811015613e2d5780516001600160401b03811115613e0f575f5ffd5b613e1e886020838a0101613d46565b84525060209283019201613df2565b5095945050505050565b5f82601f830112613e46575f5ffd5b8151613e5181613d24565b604051613e5e8282613670565b80915082815260208101915060208360051b860101925085831115613e81575f5ffd5b602085015b83811015613e2d578051835260209283019201613e86565b5f5f5f60608486031215613eb0575f5ffd5b83516001600160401b03811115613ec5575f5ffd5b8401601f81018613613ed5575f5ffd5b8051613ee081613d24565b604051613eed8282613670565b80915082815260208101915060208360051b850101925088831115613f10575f5ffd5b6020840193505b82841015613f3b578351613f2a81613369565b825260209384019390910190613f17565b8096505050505060208401516001600160401b03811115613f5a575f5ffd5b613f6686828701613da3565b92505060408401516001600160401b03811115613f81575f5ffd5b613f8d86828701613e37565b9150509250925092565b80356001600160d01b03198116906006841015612360576001600160d01b031960069490940360031b84901b1690921692915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f5f8335601e1984360301811261400a575f5ffd5b83016020810192503590506001600160401b03811115614028575f5ffd5b8036038213156134fb575f5ffd5b606081525f614049606083018789613fcd565b6001600160a01b038616602084810191909152838203604085015284825281810190600586901b830101865f5b878110156140b457848303601f19018452614091828a613ff5565b61409c858284613fcd565b60209687019690955093909301925050600101614076565b50909a9950505050505050505050565b5f60033d1115611a435760045f5f3e505f5160e01c90565b5f60443d10156140e95790565b6040513d600319016004823e80513d60248201116001600160401b038211171561411257505090565b80820180516001600160401b0381111561412d575050505090565b3d8401600319018282016020011115614147575050505090565b61415660208285010185613670565b509392505050565b5f5f6040838503121561416f575f5ffd5b825161417a81613502565b60208401519092506001600160401b03811115614195575f5ffd5b6141a185828601613d46565b9150509250929050565b60ff81168114612079575f5ffd5b8051611da2816141ab565b5f602082840312156141d4575f5ffd5b81516001600160401b038111156141e9575f5ffd5b8201604081850312156141fa575f5ffd5b6040516142068161360d565b8151614211816141ab565b815260208201516001600160401b0381111561422b575f5ffd5b61423786828501613d46565b602083015250949350505050565b5f60208284031215614255575f5ffd5b81516001600160401b0381111561426a575f5ffd5b611b9684828501613d46565b5f60208284031215614286575f5ffd5b81516001600160401b0381111561429b575f5ffd5b8201608081850312156142ac575f5ffd5b6040516142b881613632565b81516142c381613502565b8152602082015162ffffff811681146142da575f5ffd5b602082015260408201516001600160401b038111156142f7575f5ffd5b61430386828501613d46565b604083015250606091820151918101919091529392505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821602908116908181146123605761236061431d565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b0383168061437f5761437f614353565b806001600160401b0384160491505092915050565b805160058110611da2575f5ffd5b805160148110611da2575f5ffd5b5f82601f8301126143bf575f5ffd5b81516143ca81613d24565b6040516143d78282613670565b80915082815260208101915060208360051b8601019250858311156143fa575f5ffd5b602085015b83811015613e2d5780516001600160401b0381111561441c575f5ffd5b8601603f8101881361442c575f5ffd5b6040516144388161360d565b80606083018a811115614449575f5ffd5b602084015b818110156144895780516001600160401b0381111561446b575f5ffd5b61447a8d602083890101613d46565b8452506020928301920161444e565b505050845250602092830192016143ff565b5f602082840312156144ab575f5ffd5b81516001600160401b038111156144c0575f5ffd5b8201601f810184136144d0575f5ffd5b80516144db81613d24565b6040516144e88282613670565b80915082815260208101915060208360051b85010192508683111561450b575f5ffd5b602084015b8381101561463d5780516001600160401b0381111561452d575f5ffd5b850160e0818a03601f19011215614542575f5ffd5b61454a61369c565b614556602083016141b9565b815261456460408301614394565b6020820152614575606083016143a2565b604082015260808201516001600160401b03811115614592575f5ffd5b6145a18b602083860101613d46565b60608301525060a08201516001600160401b038111156145bf575f5ffd5b6145ce8b602083860101613d46565b60808301525060c08201516001600160401b038111156145ec575f5ffd5b6145fb8b6020838601016143b0565b60a08301525060e08201516001600160401b03811115614619575f5ffd5b6146288b602083860101613d46565b60c08301525084525060209283019201614510565b509695505050505050565b5f60208284031215614658575f5ffd5b6113a9826143a2565b604081525f614674604083018587613fcd565b9050826020830152949350505050565b602081525f611b96602083018486613fcd565b634e487b7160e01b5f52603260045260245ffd5b604081525f6146be604083018688613fcd565b82810360208401526146d1818587613fcd565b979650505050505050565b5f602082840312156146ec575f5ffd5b81516113a981613502565b60018060a01b0385168152836020820152606060408201525f61471e606083018486613fcd565b9695505050505050565b6001600160401b0381168114612079575f5ffd5b5f604082840312801561474d575f5ffd5b5060405161475a8161360d565b8235614765816141ab565b8152602083013561477581614728565b60208201529392505050565b5f60208284031215614791575f5ffd5b5051919050565b5f60808284031280156147a9575f5ffd5b506040516147b681613632565b82516147c181614728565b815260208301516147d181614728565b6020820152604083810151908201526060830151600481106147f1575f5ffd5b60608201529392505050565b600181811c9082168061481157607f821691505b602082108103611d6357634e487b7160e01b5f52602260045260245ffd5b5f6020828403121561483f575f5ffd5b81516001600160401b03811115614854575f5ffd5b820160a08185031215614865575f5ffd5b60405161487181613651565b815161487c81613502565b8152602082015161488c81614728565b60208201526040828101519082015260608201516001600160401b038111156148b3575f5ffd5b6148bf86828501613d46565b606083015250608082015191506148d582613502565b60808101919091529392505050565b5f602082840312156148f4575f5ffd5b8151600781106113a9575f5ffd5b5f60208284031215614912575f5ffd5b81356113a9816141ab565b5f6020828403121561492d575f5ffd5b81356113a981614728565b5f8383855260208501945060208460051b820101835f5b8681101561341557838303601f1901885261496a8287613ff5565b614975858284613fcd565b60209a8b019a9095509390930192505060010161494f565b602080825281018290525f6040600584901b830181019083018583601e1936839003015b87821015614a2157868503603f1901845282358181126149cf575f5ffd5b89016020810190356001600160401b038111156149ea575f5ffd5b8060051b36038213156149fb575f5ffd5b614a06878284614938565b965050506020830192506020840193506001820191506149b1565b5092979650505050505050565b5f60208284031215614a3e575f5ffd5b815161010081106113a9575f5ffd5b5f5f60408385031215614a5e575f5ffd5b505080516020909101519092909150565b81810381811115610d9557610d9561431d565b5f5f8284036080811215614a94575f5ffd5b8351614a9f81613b36565b92506060601f1982011215614ab2575f5ffd5b50604051606081018181106001600160401b0382111715614ad557614ad56135f9565b6040526020840151614ae681613b36565b81526040840151614af681613b36565b60208201526060840151614b0981614728565b6040820152919491935090915050565b61ffff8181168382160190811115610d9557610d9561431d565b8082028115828204841417610d9557610d9561431d565b5f82614b5857614b58614353565b500490565b5f614b688284613ced565b741d103ab73430b7323632b21030b9b9b2b93a34b7b760591b81526015019392505050565b80820180821115610d9557610d9561431d56fea264697066735822122023b0f08cbec12bb0db06fb1b0218498ee6638b309de7c701f6a549cf6688fafc64736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000077703ae126b971c9946d562f41dd47071da00777322e322e382d666462376631652d6232396439303500000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _witOracle (address): 0x77703aE126B971c9946d562F41Dd47071dA00777
Arg [1] : _versionTag (bytes32): 0x322e322e382d666462376631652d623239643930350000000000000000000000
Arg [2] : _upgradable (bool): True
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000077703ae126b971c9946d562f41dd47071da00777
Arg [1] : 322e322e382d666462376631652d623239643930350000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.