Source Code
Latest 25 from a total of 2,638 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Randomize | 28705303 | 46 mins ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28702453 | 1 hr ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28699683 | 2 hrs ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28696910 | 3 hrs ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28694116 | 4 hrs ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28691280 | 5 hrs ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28688367 | 6 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28685422 | 7 hrs ago | IN | 0.00000003 ETH | 0.00000004 | ||||
| Randomize | 28682908 | 8 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28680616 | 9 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28678370 | 10 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28676246 | 11 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28674234 | 12 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28671876 | 13 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28669463 | 14 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28666765 | 15 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28663491 | 16 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28660784 | 17 hrs ago | IN | 0.00000003 ETH | 0.00000009 | ||||
| Randomize | 28657757 | 18 hrs ago | IN | 0.00000003 ETH | 0.00000009 | ||||
| Randomize | 28654748 | 19 hrs ago | IN | 0.00000003 ETH | 0.00000012 | ||||
| Randomize | 28651518 | 20 hrs ago | IN | 0.00000003 ETH | 0.00000011 | ||||
| Randomize | 28648223 | 21 hrs ago | IN | 0.00000003 ETH | 0.00000006 | ||||
| Randomize | 28645507 | 22 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28642614 | 23 hrs ago | IN | 0.00000003 ETH | 0.00000005 | ||||
| Randomize | 28639805 | 24 hrs ago | IN | 0.00000003 ETH | 0.00000005 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28705303 | 46 mins ago | 0.00000003 ETH | ||||
| 28702453 | 1 hr ago | 0.00000003 ETH | ||||
| 28699683 | 2 hrs ago | 0.00000003 ETH | ||||
| 28696910 | 3 hrs ago | 0.00000003 ETH | ||||
| 28694116 | 4 hrs ago | 0.00000003 ETH | ||||
| 28691280 | 5 hrs ago | 0.00000003 ETH | ||||
| 28688367 | 6 hrs ago | 0.00000003 ETH | ||||
| 28685422 | 7 hrs ago | 0.00000003 ETH | ||||
| 28682908 | 8 hrs ago | 0.00000003 ETH | ||||
| 28680616 | 9 hrs ago | 0.00000003 ETH | ||||
| 28678370 | 10 hrs ago | 0.00000003 ETH | ||||
| 28676246 | 11 hrs ago | 0.00000003 ETH | ||||
| 28674234 | 12 hrs ago | 0.00000003 ETH | ||||
| 28671876 | 13 hrs ago | 0.00000003 ETH | ||||
| 28669463 | 14 hrs ago | 0.00000003 ETH | ||||
| 28666765 | 15 hrs ago | 0.00000003 ETH | ||||
| 28663491 | 16 hrs ago | 0.00000003 ETH | ||||
| 28660784 | 17 hrs ago | 0.00000003 ETH | ||||
| 28657757 | 18 hrs ago | 0.00000003 ETH | ||||
| 28654748 | 19 hrs ago | 0.00000003 ETH | ||||
| 28651518 | 20 hrs ago | 0.00000003 ETH | ||||
| 28648223 | 21 hrs ago | 0.00000003 ETH | ||||
| 28645507 | 22 hrs ago | 0.00000003 ETH | ||||
| 28642614 | 23 hrs ago | 0.00000003 ETH | ||||
| 28639805 | 24 hrs ago | 0.00000003 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
WitnetRandomnessV2
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../WitnetRandomness.sol";
import "../apps/UsingWitnet.sol";
import "../interfaces/IWitnetRandomnessAdmin.sol";
import "../patterns/Ownable2Step.sol";
/// @title WitnetRandomnessV2: Unmalleable and provably-fair randomness generation based on the Witnet Oracle v2.*.
/// @author The Witnet Foundation.
contract WitnetRandomnessV2
is
Ownable2Step,
UsingWitnet,
WitnetRandomness,
IWitnetRandomnessAdmin
{
using Witnet for bytes;
using Witnet for Witnet.Result;
using WitnetV2 for WitnetV2.RadonSLA;
struct Randomize {
uint256 witnetQueryId;
uint256 prevBlock;
uint256 nextBlock;
}
struct Storage {
uint256 lastRandomizeBlock;
mapping (uint256 => Randomize) randomize_;
}
/// @notice Unique identifier of the RNG data request used on the Witnet Oracle blockchain for solving randomness.
/// @dev Can be used to track all randomness requests solved so far on the Witnet Oracle blockchain.
bytes32 immutable public override witnetRadHash;
constructor(
WitnetOracle _witnet,
address _operator
)
Ownable(_operator)
UsingWitnet(_witnet)
{
_require(
address(_witnet) == address(0)
|| _witnet.specs() == type(IWitnetOracle).interfaceId,
"uncompliant WitnetOracle"
);
WitnetRequestBytecodes _registry = witnet().registry();
{
// Build own Witnet Randomness Request:
bytes32[] memory _retrievals = new bytes32[](1);
_retrievals[0] = _registry.verifyRadonRetrieval(
Witnet.RadonDataRequestMethods.RNG,
"", // no request url
"", // no request body
new string[2][](0), // no request headers
hex"80" // no request Radon script
);
Witnet.RadonFilter[] memory _filters;
bytes32 _aggregator = _registry.verifyRadonReducer(Witnet.RadonReducer({
opcode: Witnet.RadonReducerOpcodes.Mode,
filters: _filters // no filters
}));
bytes32 _tally = _registry.verifyRadonReducer(Witnet.RadonReducer({
opcode: Witnet.RadonReducerOpcodes.ConcatenateAndHash,
filters: _filters // no filters
}));
witnetRadHash = _registry.verifyRadonRequest(
_retrievals,
_aggregator,
_tally,
32, // 256 bits of pure entropy ;-)
new string[][](_retrievals.length)
);
}
}
receive() virtual external payable {
_revert("no transfers accepted");
}
fallback() virtual external payable {
_revert(string(abi.encodePacked(
"not implemented: 0x",
Witnet.toHexString(uint8(bytes1(msg.sig))),
Witnet.toHexString(uint8(bytes1(msg.sig << 8))),
Witnet.toHexString(uint8(bytes1(msg.sig << 16))),
Witnet.toHexString(uint8(bytes1(msg.sig << 24)))
)));
}
function class() virtual override public pure returns (string memory) {
return type(WitnetRandomnessV2).name;
}
function specs() virtual override external pure returns (bytes4) {
return type(WitnetRandomness).interfaceId;
}
function witnet() override (IWitnetRandomness, UsingWitnet)
public view returns (WitnetOracle)
{
return UsingWitnet.witnet();
}
/// ===============================================================================================================
/// --- 'IWitnetRandomness' implementation ------------------------------------------------------------------------
/// Returns amount of wei required to be paid as a fee when requesting randomization with a
/// transaction gas price as the one given.
function estimateRandomizeFee(uint256 _evmGasPrice)
public view
virtual override
returns (uint256)
{
return (
(100 + __witnetBaseFeeOverheadPercentage)
* __witnet.estimateBaseFee(
_evmGasPrice,
uint16(34)
)
) / 100;
}
/// @notice Retrieves the result of keccak256-hashing the given block number with the randomness value
/// @notice generated by the Witnet Oracle blockchain in response to the first non-errored randomize request solved
/// @notice after such block number.
/// @dev Reverts if:
/// @dev i. no `randomize()` was requested on neither the given block, nor afterwards.
/// @dev ii. the first non-errored `randomize()` request found on or after the given block is not solved yet.
/// @dev iii. all `randomize()` requests that took place on or after the given block were solved with errors.
/// @param _blockNumber Block number from which the search will start
function fetchRandomnessAfter(uint256 _blockNumber)
public view
virtual override
returns (bytes32)
{
return keccak256(
abi.encode(
_blockNumber,
_fetchRandomnessAfter(_blockNumber)
)
);
}
function _fetchRandomnessAfter(uint256 _blockNumber)
virtual internal view
returns (bytes32)
{
if (__storage().randomize_[_blockNumber].witnetQueryId == 0) {
_blockNumber = getRandomizeNextBlock(_blockNumber);
}
Randomize storage __randomize = __storage().randomize_[_blockNumber];
uint256 _witnetQueryId = __randomize.witnetQueryId;
_require(
_witnetQueryId != 0,
"not randomized"
);
WitnetV2.ResponseStatus _status = __witnet.getQueryResponseStatus(_witnetQueryId);
if (_status == WitnetV2.ResponseStatus.Ready) {
return (
__witnet.getQueryResultCborBytes(_witnetQueryId)
.toWitnetResult()
.asBytes32()
);
} else if (_status == WitnetV2.ResponseStatus.Error) {
uint256 _nextRandomizeBlock = __randomize.nextBlock;
_require(
_nextRandomizeBlock != 0,
"faulty randomize"
);
return _fetchRandomnessAfter(_nextRandomizeBlock);
} else {
_revert("pending randomize");
}
}
/// @notice Retrieves the actual random value, unique hash and timestamp of the witnessing commit/reveal act that took
/// @notice place in the Witnet Oracle blockchain in response to the first non-errored randomize request
/// @notice solved after the given block number.
/// @dev Reverts if:
/// @dev i. no `randomize()` was requested on neither the given block, nor afterwards.
/// @dev ii. the first non-errored `randomize()` request found on or after the given block is not solved yet.
/// @dev iii. all `randomize()` requests that took place on or after the given block were solved with errors.
/// @param _blockNumber Block number from which the search will start.
/// @return _witnetResultRandomness Random value provided by the Witnet blockchain and used for solving randomness after given block.
/// @return _witnetResultTimestamp Timestamp at which the randomness value was generated by the Witnet blockchain.
/// @return _witnetResultTallyHash Hash of the witnessing commit/reveal act that took place on the Witnet blockchain.
/// @return _witnetResultFinalityBlock EVM block number from which the provided randomness can be considered to be final.
function fetchRandomnessAfterProof(uint256 _blockNumber)
virtual override
public view
returns (
bytes32 _witnetResultRandomness,
uint64 _witnetResultTimestamp,
bytes32 _witnetResultTallyHash,
uint256 _witnetResultFinalityBlock
)
{
if (__storage().randomize_[_blockNumber].witnetQueryId == 0) {
_blockNumber = getRandomizeNextBlock(_blockNumber);
}
Randomize storage __randomize = __storage().randomize_[_blockNumber];
uint256 _witnetQueryId = __randomize.witnetQueryId;
_require(
_witnetQueryId != 0,
"not randomized"
);
WitnetV2.ResponseStatus _status = __witnet.getQueryResponseStatus(_witnetQueryId);
if (_status == WitnetV2.ResponseStatus.Ready) {
WitnetV2.Response memory _witnetQueryResponse = __witnet.getQueryResponse(_witnetQueryId);
_witnetResultTimestamp = _witnetQueryResponse.resultTimestamp;
_witnetResultTallyHash = _witnetQueryResponse.resultTallyHash;
_witnetResultFinalityBlock = _witnetQueryResponse.finality;
_witnetResultRandomness = _witnetQueryResponse.resultCborBytes.toWitnetResult().asBytes32();
} else if (_status == WitnetV2.ResponseStatus.Error) {
uint256 _nextRandomizeBlock = __randomize.nextBlock;
_require(
_nextRandomizeBlock != 0,
"faulty randomize"
);
return fetchRandomnessAfterProof(_nextRandomizeBlock);
} else {
_revert("pending randomize");
}
}
/// @notice Returns last block number on which a randomize was requested.
function getLastRandomizeBlock()
virtual override
external view
returns (uint256)
{
return __storage().lastRandomizeBlock;
}
/// @notice Retrieves metadata related to the randomize request that got posted to the
/// @notice Witnet Oracle contract on the given block number.
/// @dev Returns zero values if no randomize request was actually posted on the given block.
/// @return _witnetQueryId Identifier of the underlying Witnet query created on the given block number.
/// @return _prevRandomizeBlock Block number in which a randomize request got posted just before this one. 0 if none.
/// @return _nextRandomizeBlock Block number in which a randomize request got posted just after this one, 0 if none.
function getRandomizeData(uint256 _blockNumber)
external view
virtual override
returns (
uint256 _witnetQueryId,
uint256 _prevRandomizeBlock,
uint256 _nextRandomizeBlock
)
{
Randomize storage __randomize = __storage().randomize_[_blockNumber];
_witnetQueryId = __randomize.witnetQueryId;
_prevRandomizeBlock = __randomize.prevBlock;
_nextRandomizeBlock = __randomize.nextBlock;
}
/// @notice Returns the number of the next block in which a randomize request was posted after the given one.
/// @param _blockNumber Block number from which the search will start.
/// @return Number of the first block found after the given one, or `0` otherwise.
function getRandomizeNextBlock(uint256 _blockNumber)
public view
virtual override
returns (uint256)
{
return ((__storage().randomize_[_blockNumber].witnetQueryId != 0)
? __storage().randomize_[_blockNumber].nextBlock
// start search from the latest block
: _searchNextBlock(_blockNumber, __storage().lastRandomizeBlock)
);
}
/// @notice Returns the number of the previous block in which a randomize request was posted before the given one.
/// @param _blockNumber Block number from which the search will start. Cannot be zero.
/// @return First block found before the given one, or `0` otherwise.
function getRandomizePrevBlock(uint256 _blockNumber)
public view
virtual override
returns (uint256)
{
assert(_blockNumber > 0);
uint256 _latest = __storage().lastRandomizeBlock;
return ((_blockNumber > _latest)
? _latest
// start search from the latest block
: _searchPrevBlock(_blockNumber, __storage().randomize_[_latest].prevBlock)
);
}
/// @notice Returns status of the first non-errored randomize request posted on or after the given block number.
/// @dev Possible values:
/// @dev - 0 -> Void: no randomize request was actually posted on or after the given block number.
/// @dev - 1 -> Awaiting: a randomize request was found but it's not yet solved by the Witnet blockchain.
/// @dev - 2 -> Ready: a successfull randomize value was reported and ready to be read.
/// @dev - 3 -> Error: all randomize requests after the given block were solved with errors.
/// @dev - 4 -> Finalizing: a randomize resolution has been reported from the Witnet blockchain, but it's not yet final.
function getRandomizeStatus(uint256 _blockNumber)
virtual override
public view
returns (WitnetV2.ResponseStatus)
{
if (__storage().randomize_[_blockNumber].witnetQueryId == 0) {
_blockNumber = getRandomizeNextBlock(_blockNumber);
}
uint256 _witnetQueryId = __storage().randomize_[_blockNumber].witnetQueryId;
if (_witnetQueryId == 0) {
return WitnetV2.ResponseStatus.Void;
} else {
WitnetV2.ResponseStatus _status = __witnet.getQueryResponseStatus(_witnetQueryId);
if (_status == WitnetV2.ResponseStatus.Error) {
uint256 _nextRandomizeBlock = __storage().randomize_[_blockNumber].nextBlock;
if (_nextRandomizeBlock != 0) {
return getRandomizeStatus(_nextRandomizeBlock);
} else {
return WitnetV2.ResponseStatus.Error;
}
} else {
return _status;
}
}
}
/// @notice Returns `true` only if a successfull resolution from the Witnet blockchain is found for the first
/// @notice non-errored randomize request posted on or after the given block number.
function isRandomized(uint256 _blockNumber)
public view
virtual override
returns (bool)
{
return (
getRandomizeStatus(_blockNumber) == WitnetV2.ResponseStatus.Ready
);
}
/// @notice Generates a pseudo-random number uniformly distributed within the range [0 .. _range), by using
/// @notice the given `nonce` and the randomness returned by `getRandomnessAfter(blockNumber)`.
/// @dev Fails under same conditions as `getRandomnessAfter(uint256)` does.
/// @param _range Range within which the uniformly-distributed random number will be generated.
/// @param _nonce Nonce value enabling multiple random numbers from the same randomness value.
/// @param _blockNumber Block number from which the search for the first randomize request solved aftewards will start.
function random(uint32 _range, uint256 _nonce, uint256 _blockNumber)
external view
virtual override
returns (uint32)
{
return WitnetV2.randomUniformUint32(
_range,
_nonce,
keccak256(
abi.encode(
msg.sender,
fetchRandomnessAfter(_blockNumber)
)
)
);
}
/// @notice Requests the Witnet oracle to generate an EVM-agnostic and trustless source of randomness.
/// @dev Only one randomness request per block will be actually posted to the Witnet Oracle.
/// @return _evmRandomizeFee Funds actually paid as randomize fee.
function randomize()
external payable
virtual override
returns (uint256 _evmRandomizeFee)
{
if (__storage().lastRandomizeBlock < block.number) {
_evmRandomizeFee = msg.value;
// Post the Witnet Randomness request:
uint _witnetQueryId = __witnet.postRequest{
value: _evmRandomizeFee
}(
witnetRadHash,
__witnetDefaultSLA
);
// Keep Randomize data in storage:
Randomize storage __randomize = __storage().randomize_[block.number];
__randomize.witnetQueryId = _witnetQueryId;
// Update block links:
uint256 _prevBlock = __storage().lastRandomizeBlock;
__randomize.prevBlock = _prevBlock;
__storage().randomize_[_prevBlock].nextBlock = block.number;
__storage().lastRandomizeBlock = block.number;
// Throw event:
emit Randomizing(
block.number,
tx.gasprice,
_evmRandomizeFee,
_witnetQueryId,
__witnetDefaultSLA
);
}
// Transfer back unused funds:
if (_evmRandomizeFee < msg.value) {
payable(msg.sender).transfer(msg.value - _evmRandomizeFee);
}
}
/// @notice Returns the SLA parameters required for the Witnet Oracle blockchain to fulfill
/// @notice when solving randomness requests:
/// @notice - number of witnessing nodes contributing to randomness generation
/// @notice - reward in $nanoWIT received by every contributing node in the Witnet blockchain
function witnetQuerySLA()
virtual override
external view
returns (WitnetV2.RadonSLA memory)
{
return __witnetDefaultSLA;
}
/// ===============================================================================================================
/// --- 'IWitnetRandomnessAdmin' implementation -------------------------------------------------------------------
function acceptOwnership()
virtual override (IWitnetRandomnessAdmin, Ownable2Step)
public
{
Ownable2Step.acceptOwnership();
}
function baseFeeOverheadPercentage()
virtual override
external view
returns (uint16)
{
return __witnetBaseFeeOverheadPercentage;
}
function owner()
virtual override (IWitnetRandomnessAdmin, Ownable)
public view
returns (address)
{
return Ownable.owner();
}
function pendingOwner()
virtual override (IWitnetRandomnessAdmin, Ownable2Step)
public view
returns (address)
{
return Ownable2Step.pendingOwner();
}
function transferOwnership(address _newOwner)
virtual override (IWitnetRandomnessAdmin, Ownable2Step)
public
onlyOwner
{
Ownable.transferOwnership(_newOwner);
}
function settleBaseFeeOverheadPercentage(uint16 _baseFeeOverheadPercentage)
virtual override
external
onlyOwner
{
__witnetBaseFeeOverheadPercentage = _baseFeeOverheadPercentage;
}
function settleWitnetQuerySLA(WitnetV2.RadonSLA calldata _witnetQuerySLA)
virtual override
external
onlyOwner
{
_require(
_witnetQuerySLA.isValid(),
"invalid SLA"
);
__witnetDefaultSLA = _witnetQuerySLA;
}
// ================================================================================================================
// --- Internal methods -------------------------------------------------------------------------------------------
function _require(
bool _condition,
string memory _message
)
internal pure
{
if (!_condition) {
_revert(_message);
}
}
function _revert(string memory _message)
internal pure
{
revert(
string(abi.encodePacked(
class(),
": ",
_message
))
);
}
/// @dev Recursively searches for the number of the first block after the given one in which a Witnet
/// @dev randomness request was posted. Returns 0 if none found.
function _searchNextBlock(uint256 _target, uint256 _latest) internal view returns (uint256) {
return ((_target >= _latest)
? __storage().randomize_[_latest].nextBlock
: _searchNextBlock(_target, __storage().randomize_[_latest].prevBlock)
);
}
/// @dev Recursively searches for the number of the first block before the given one in which a Witnet
/// @dev randomness request was posted. Returns 0 if none found.
function _searchPrevBlock(uint256 _target, uint256 _latest) internal view returns (uint256) {
return ((_target > _latest)
? _latest
: _searchPrevBlock(_target, __storage().randomize_[_latest].prevBlock)
);
}
bytes32 private constant _STORAGE_SLOT =
// keccak256("io.witnet.apps.randomness.v20")
0x643778935c57df947f6944f6a5242a3e91445f6337f4b2ec670c8642153b614f;
function __storage() internal pure returns (Storage storage _ptr) {
assembly {
_ptr.slot := _STORAGE_SLOT
}
}
}// 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 "./Witnet.sol";
library WitnetV2 {
/// Struct containing both request and response data related to every query posted to the Witnet Request Board
struct Query {
Request request;
Response response;
}
/// Possible status of a Witnet query.
enum QueryStatus {
Unknown,
Posted,
Reported,
Finalized
}
/// Data kept in EVM-storage for every Request posted to the Witnet Request Board.
struct Request {
address requester; // EVM address from which the request was posted.
uint24 gasCallback; // Max callback gas limit upon response, if a callback is required.
uint72 evmReward; // EVM amount in wei eventually to be paid to the legit result reporter.
bytes witnetBytecode; // Optional: Witnet Data Request bytecode to be solved by the Witnet blockchain.
bytes32 witnetRAD; // Optional: Previously verified hash of the Witnet Data Request to be solved.
WitnetV2.RadonSLA witnetSLA; // Minimum Service-Level parameters to be committed by the Witnet blockchain.
}
/// Response metadata and result as resolved by the Witnet blockchain.
struct Response {
address reporter; // EVM address from which the Data Request result was reported.
uint64 finality; // EVM block number at which the reported data will be considered to be finalized.
uint32 resultTimestamp; // Unix timestamp (seconds) at which the data request was resolved in the Witnet blockchain.
bytes32 resultTallyHash; // Unique hash of the commit/reveal act in the Witnet blockchain that resolved the data request.
bytes resultCborBytes; // CBOR-encode result to the request, as resolved in the Witnet blockchain.
}
/// Response status from a requester's point of view.
enum ResponseStatus {
Void,
Awaiting,
Ready,
Error,
Finalizing,
Delivered
}
struct RadonSLA {
/// @notice Number of nodes in the Witnet blockchain that will take part in solving the data request.
uint8 committeeSize;
/// @notice Fee in $nanoWIT paid to every node in the Witnet blockchain involved in solving the data request.
/// @dev Witnet nodes participating as witnesses will have to stake as collateral 100x this amount.
uint64 witnessingFeeNanoWit;
}
/// ===============================================================================================================
/// --- 'WitnetV2.RadonSLA' helper methods ------------------------------------------------------------------------
function equalOrGreaterThan(RadonSLA memory a, RadonSLA memory b)
internal pure returns (bool)
{
return (a.committeeSize >= b.committeeSize);
}
function isValid(RadonSLA calldata sla) internal pure returns (bool) {
return (
sla.witnessingFeeNanoWit > 0
&& sla.committeeSize > 0 && sla.committeeSize <= 127
// v1.7.x requires witnessing collateral to be greater or equal to 20 WIT:
&& sla.witnessingFeeNanoWit * 100 >= 20 * 10 ** 9
);
}
function toV1(RadonSLA memory self) internal pure returns (Witnet.RadonSLA memory) {
return Witnet.RadonSLA({
numWitnesses: self.committeeSize,
minConsensusPercentage: 51,
witnessReward: self.witnessingFeeNanoWit,
witnessCollateral: self.witnessingFeeNanoWit * 100,
minerCommitRevealFee: self.witnessingFeeNanoWit / self.committeeSize
});
}
function nanoWitTotalFee(RadonSLA storage self) internal view returns (uint64) {
return self.witnessingFeeNanoWit * (self.committeeSize + 3);
}
/// ===============================================================================================================
/// --- P-RNG generators ------------------------------------------------------------------------------------------
/// Generates a pseudo-random uint32 number uniformly distributed within the range `[0 .. range)`, based on
/// the given `nonce` and `seed` values.
function randomUniformUint32(uint32 range, uint256 nonce, bytes32 seed)
internal pure
returns (uint32)
{
uint256 _number = uint256(
keccak256(
abi.encode(seed, nonce)
)
) & uint256(2 ** 224 - 1);
return uint32((_number * range) >> 224);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./WitnetBuffer.sol";
/// @title A minimalistic implementation of “RFC 7049 Concise Binary Object Representation”
/// @notice This library leverages a buffer-like structure for step-by-step decoding of bytes so as to minimize
/// the gas cost of decoding them into a useful native type.
/// @dev Most of the logic has been borrowed from Patrick Gansterer’s cbor.js library: https://github.com/paroga/cbor-js
/// @author The Witnet Foundation.
library WitnetCBOR {
using WitnetBuffer for WitnetBuffer.Buffer;
using WitnetCBOR for WitnetCBOR.CBOR;
/// Data struct following the RFC-7049 standard: Concise Binary Object Representation.
struct CBOR {
WitnetBuffer.Buffer buffer;
uint8 initialByte;
uint8 majorType;
uint8 additionalInformation;
uint64 len;
uint64 tag;
}
uint8 internal constant MAJOR_TYPE_INT = 0;
uint8 internal constant MAJOR_TYPE_NEGATIVE_INT = 1;
uint8 internal constant MAJOR_TYPE_BYTES = 2;
uint8 internal constant MAJOR_TYPE_STRING = 3;
uint8 internal constant MAJOR_TYPE_ARRAY = 4;
uint8 internal constant MAJOR_TYPE_MAP = 5;
uint8 internal constant MAJOR_TYPE_TAG = 6;
uint8 internal constant MAJOR_TYPE_CONTENT_FREE = 7;
uint32 internal constant UINT32_MAX = type(uint32).max;
uint64 internal constant UINT64_MAX = type(uint64).max;
error EmptyArray();
error InvalidLengthEncoding(uint length);
error UnexpectedMajorType(uint read, uint expected);
error UnsupportedPrimitive(uint primitive);
error UnsupportedMajorType(uint unexpected);
modifier isMajorType(
WitnetCBOR.CBOR memory cbor,
uint8 expected
) {
if (cbor.majorType != expected) {
revert UnexpectedMajorType(cbor.majorType, expected);
}
_;
}
modifier notEmpty(WitnetBuffer.Buffer memory buffer) {
if (buffer.data.length == 0) {
revert WitnetBuffer.EmptyBuffer();
}
_;
}
function eof(CBOR memory cbor)
internal pure
returns (bool)
{
return cbor.buffer.cursor >= cbor.buffer.data.length;
}
/// @notice Decode a CBOR structure from raw bytes.
/// @dev This is the main factory for CBOR instances, which can be later decoded into native EVM types.
/// @param bytecode Raw bytes representing a CBOR-encoded value.
/// @return A `CBOR` instance containing a partially decoded value.
function fromBytes(bytes memory bytecode)
internal pure
returns (CBOR memory)
{
WitnetBuffer.Buffer memory buffer = WitnetBuffer.Buffer(bytecode, 0);
return fromBuffer(buffer);
}
/// @notice Decode a CBOR structure from raw bytes.
/// @dev This is an alternate factory for CBOR instances, which can be later decoded into native EVM types.
/// @param buffer A Buffer structure representing a CBOR-encoded value.
/// @return A `CBOR` instance containing a partially decoded value.
function fromBuffer(WitnetBuffer.Buffer memory buffer)
internal pure
notEmpty(buffer)
returns (CBOR memory)
{
uint8 initialByte;
uint8 majorType = 255;
uint8 additionalInformation;
uint64 tag = UINT64_MAX;
uint256 len;
bool isTagged = true;
while (isTagged) {
// Extract basic CBOR properties from input bytes
initialByte = buffer.readUint8();
len ++;
majorType = initialByte >> 5;
additionalInformation = initialByte & 0x1f;
// Early CBOR tag parsing.
if (majorType == MAJOR_TYPE_TAG) {
uint _cursor = buffer.cursor;
tag = readLength(buffer, additionalInformation);
len += buffer.cursor - _cursor;
} else {
isTagged = false;
}
}
if (majorType > MAJOR_TYPE_CONTENT_FREE) {
revert UnsupportedMajorType(majorType);
}
return CBOR(
buffer,
initialByte,
majorType,
additionalInformation,
uint64(len),
tag
);
}
function fork(WitnetCBOR.CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
return CBOR({
buffer: self.buffer.fork(),
initialByte: self.initialByte,
majorType: self.majorType,
additionalInformation: self.additionalInformation,
len: self.len,
tag: self.tag
});
}
function settle(CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
if (!self.eof()) {
return fromBuffer(self.buffer);
} else {
return self;
}
}
function skip(CBOR memory self)
internal pure
returns (WitnetCBOR.CBOR memory)
{
if (
self.majorType == MAJOR_TYPE_INT
|| self.majorType == MAJOR_TYPE_NEGATIVE_INT
|| (
self.majorType == MAJOR_TYPE_CONTENT_FREE
&& self.additionalInformation >= 25
&& self.additionalInformation <= 27
)
) {
self.buffer.cursor += self.peekLength();
} else if (
self.majorType == MAJOR_TYPE_STRING
|| self.majorType == MAJOR_TYPE_BYTES
) {
uint64 len = readLength(self.buffer, self.additionalInformation);
self.buffer.cursor += len;
} else if (
self.majorType == MAJOR_TYPE_ARRAY
|| self.majorType == MAJOR_TYPE_MAP
) {
self.len = readLength(self.buffer, self.additionalInformation);
} else if (
self.majorType != MAJOR_TYPE_CONTENT_FREE
|| (
self.additionalInformation != 20
&& self.additionalInformation != 21
)
) {
revert("WitnetCBOR.skip: unsupported major type");
}
return self;
}
function peekLength(CBOR memory self)
internal pure
returns (uint64)
{
if (self.additionalInformation < 24) {
return 0;
} else if (self.additionalInformation < 28) {
return uint64(1 << (self.additionalInformation - 24));
} else {
revert InvalidLengthEncoding(self.additionalInformation);
}
}
function readArray(CBOR memory self)
internal pure
isMajorType(self, MAJOR_TYPE_ARRAY)
returns (CBOR[] memory items)
{
// read array's length and move self cursor forward to the first array element:
uint64 len = readLength(self.buffer, self.additionalInformation);
items = new CBOR[](len + 1);
for (uint ix = 0; ix < len; ix ++) {
// settle next element in the array:
self = self.settle();
// fork it and added to the list of items to be returned:
items[ix] = self.fork();
if (self.majorType == MAJOR_TYPE_ARRAY) {
CBOR[] memory _subitems = self.readArray();
// move forward to the first element after inner array:
self = _subitems[_subitems.length - 1];
} else if (self.majorType == MAJOR_TYPE_MAP) {
CBOR[] memory _subitems = self.readMap();
// move forward to the first element after inner map:
self = _subitems[_subitems.length - 1];
} else {
// move forward to the next element:
self.skip();
}
}
// return self cursor as extra item at the end of the list,
// as to optimize recursion when jumping over nested arrays:
items[len] = self;
}
function readMap(CBOR memory self)
internal pure
isMajorType(self, MAJOR_TYPE_MAP)
returns (CBOR[] memory items)
{
// read number of items within the map and move self cursor forward to the first inner element:
uint64 len = readLength(self.buffer, self.additionalInformation) * 2;
items = new CBOR[](len + 1);
for (uint ix = 0; ix < len; ix ++) {
// settle next element in the array:
self = self.settle();
// fork it and added to the list of items to be returned:
items[ix] = self.fork();
if (ix % 2 == 0 && self.majorType != MAJOR_TYPE_STRING) {
revert UnexpectedMajorType(self.majorType, MAJOR_TYPE_STRING);
} else if (self.majorType == MAJOR_TYPE_ARRAY || self.majorType == MAJOR_TYPE_MAP) {
CBOR[] memory _subitems = (self.majorType == MAJOR_TYPE_ARRAY
? self.readArray()
: self.readMap()
);
// move forward to the first element after inner array or map:
self = _subitems[_subitems.length - 1];
} else {
// move forward to the next element:
self.skip();
}
}
// return self cursor as extra item at the end of the list,
// as to optimize recursion when jumping over nested arrays:
items[len] = self;
}
/// Reads the length of the settle CBOR item from a buffer, consuming a different number of bytes depending on the
/// value of the `additionalInformation` argument.
function readLength(
WitnetBuffer.Buffer memory buffer,
uint8 additionalInformation
)
internal pure
returns (uint64)
{
if (additionalInformation < 24) {
return additionalInformation;
}
if (additionalInformation == 24) {
return buffer.readUint8();
}
if (additionalInformation == 25) {
return buffer.readUint16();
}
if (additionalInformation == 26) {
return buffer.readUint32();
}
if (additionalInformation == 27) {
return buffer.readUint64();
}
if (additionalInformation == 31) {
return UINT64_MAX;
}
revert InvalidLengthEncoding(additionalInformation);
}
/// @notice Read a `CBOR` structure into a native `bool` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as a `bool` value.
function readBool(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (bool)
{
if (cbor.additionalInformation == 20) {
return false;
} else if (cbor.additionalInformation == 21) {
return true;
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a native `bytes` value.
/// @param cbor An instance of `CBOR`.
/// @return output The value represented by the input, as a `bytes` value.
function readBytes(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_BYTES)
returns (bytes memory output)
{
cbor.len = readLength(
cbor.buffer,
cbor.additionalInformation
);
if (cbor.len == UINT32_MAX) {
// These checks look repetitive but the equivalent loop would be more expensive.
uint32 length = uint32(_readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
));
if (length < UINT32_MAX) {
output = abi.encodePacked(cbor.buffer.read(length));
length = uint32(_readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
));
if (length < UINT32_MAX) {
output = abi.encodePacked(
output,
cbor.buffer.read(length)
);
}
}
} else {
return cbor.buffer.read(uint32(cbor.len));
}
}
/// @notice Decode a `CBOR` structure into a `fixed16` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`
/// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int128` value.
function readFloat16(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int32)
{
if (cbor.additionalInformation == 25) {
return cbor.buffer.readFloat16();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a `fixed32` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `fixed64`
/// use cases. In other words, the output of this method is 10^9 times the actual value, encoded into an `int`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int` value.
function readFloat32(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int)
{
if (cbor.additionalInformation == 26) {
return cbor.buffer.readFloat32();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a `fixed64` value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `fixed64`
/// use cases. In other words, the output of this method is 10^15 times the actual value, encoded into an `int`.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int` value.
function readFloat64(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
returns (int)
{
if (cbor.additionalInformation == 27) {
return cbor.buffer.readFloat64();
} else {
revert UnsupportedPrimitive(cbor.additionalInformation);
}
}
/// @notice Decode a `CBOR` structure into a native `int128[]` value whose inner values follow the same convention
/// @notice as explained in `decodeFixed16`.
/// @param cbor An instance of `CBOR`.
function readFloat16Array(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (int32[] memory values)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
values = new int32[](length);
for (uint64 i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
values[i] = readFloat16(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `int128` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `int128` value.
function readInt(CBOR memory cbor)
internal pure
returns (int)
{
if (cbor.majorType == 1) {
uint64 _value = readLength(
cbor.buffer,
cbor.additionalInformation
);
return int(-1) - int(uint(_value));
} else if (cbor.majorType == 0) {
// Any `uint64` can be safely casted to `int128`, so this method supports majorType 1 as well so as to have offer
// a uniform API for positive and negative numbers
return int(readUint(cbor));
}
else {
revert UnexpectedMajorType(cbor.majorType, 1);
}
}
/// @notice Decode a `CBOR` structure into a native `int[]` value.
/// @param cbor instance of `CBOR`.
/// @return array The value represented by the input, as an `int[]` value.
function readIntArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (int[] memory array)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
array = new int[](length);
for (uint i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
array[i] = readInt(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `string` value.
/// @param cbor An instance of `CBOR`.
/// @return text The value represented by the input, as a `string` value.
function readString(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_STRING)
returns (string memory text)
{
cbor.len = readLength(cbor.buffer, cbor.additionalInformation);
if (cbor.len == UINT64_MAX) {
bool _done;
while (!_done) {
uint64 length = _readIndefiniteStringLength(
cbor.buffer,
cbor.majorType
);
if (length < UINT64_MAX) {
text = string(abi.encodePacked(
text,
cbor.buffer.readText(length / 4)
));
} else {
_done = true;
}
}
} else {
return string(cbor.buffer.readText(cbor.len));
}
}
/// @notice Decode a `CBOR` structure into a native `string[]` value.
/// @param cbor An instance of `CBOR`.
/// @return strings The value represented by the input, as an `string[]` value.
function readStringArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (string[] memory strings)
{
uint length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
strings = new string[](length);
for (uint i = 0; i < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
strings[i] = readString(item);
unchecked {
i ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// @notice Decode a `CBOR` structure into a native `uint64` value.
/// @param cbor An instance of `CBOR`.
/// @return The value represented by the input, as an `uint64` value.
function readUint(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_INT)
returns (uint)
{
return readLength(
cbor.buffer,
cbor.additionalInformation
);
}
/// @notice Decode a `CBOR` structure into a native `uint64[]` value.
/// @param cbor An instance of `CBOR`.
/// @return values The value represented by the input, as an `uint64[]` value.
function readUintArray(CBOR memory cbor)
internal pure
isMajorType(cbor, MAJOR_TYPE_ARRAY)
returns (uint[] memory values)
{
uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
if (length < UINT64_MAX) {
values = new uint[](length);
for (uint ix = 0; ix < length; ) {
CBOR memory item = fromBuffer(cbor.buffer);
values[ix] = readUint(item);
unchecked {
ix ++;
}
}
} else {
revert InvalidLengthEncoding(length);
}
}
/// Read the length of a CBOR indifinite-length item (arrays, maps, byte strings and text) from a buffer, consuming
/// as many bytes as specified by the first byte.
function _readIndefiniteStringLength(
WitnetBuffer.Buffer memory buffer,
uint8 majorType
)
private pure
returns (uint64 len)
{
uint8 initialByte = buffer.readUint8();
if (initialByte == 0xff) {
return UINT64_MAX;
}
len = readLength(
buffer,
initialByte & 0x1f
);
if (len >= UINT64_MAX) {
revert InvalidLengthEncoding(len);
} else if (majorType != (initialByte >> 5)) {
revert UnexpectedMajorType((initialByte >> 5), majorType);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/// @title A convenient wrapper around the `bytes memory` type that exposes a buffer-like interface
/// @notice The buffer has an inner cursor that tracks the final offset of every read, i.e. any subsequent read will
/// start with the byte that goes right after the last one in the previous read.
/// @dev `uint32` is used here for `cursor` because `uint16` would only enable seeking up to 8KB, which could in some
/// theoretical use cases be exceeded. Conversely, `uint32` supports up to 512MB, which cannot credibly be exceeded.
/// @author The Witnet Foundation.
library WitnetBuffer {
error EmptyBuffer();
error IndexOutOfBounds(uint index, uint range);
error MissingArgs(uint expected, uint given);
/// Iterable bytes buffer.
struct Buffer {
bytes data;
uint cursor;
}
// Ensures we access an existing index in an array
modifier withinRange(uint index, uint _range) {
if (index > _range) {
revert IndexOutOfBounds(index, _range);
}
_;
}
/// @notice Concatenate undefinite number of bytes chunks.
/// @dev Faster than looping on `abi.encodePacked(output, _buffs[ix])`.
function concat(bytes[] memory _buffs)
internal pure
returns (bytes memory output)
{
unchecked {
uint destinationPointer;
uint destinationLength;
assembly {
// get safe scratch location
output := mload(0x40)
// set starting destination pointer
destinationPointer := add(output, 32)
}
for (uint ix = 1; ix <= _buffs.length; ix ++) {
uint source;
uint sourceLength;
uint sourcePointer;
assembly {
// load source length pointer
source := mload(add(_buffs, mul(ix, 32)))
// load source length
sourceLength := mload(source)
// sets source memory pointer
sourcePointer := add(source, 32)
}
memcpy(
destinationPointer,
sourcePointer,
sourceLength
);
assembly {
// increase total destination length
destinationLength := add(destinationLength, sourceLength)
// sets destination memory pointer
destinationPointer := add(destinationPointer, sourceLength)
}
}
assembly {
// protect output bytes
mstore(output, destinationLength)
// set final output length
mstore(0x40, add(mload(0x40), add(destinationLength, 32)))
}
}
}
function fork(WitnetBuffer.Buffer memory buffer)
internal pure
returns (WitnetBuffer.Buffer memory)
{
return Buffer(
buffer.data,
buffer.cursor
);
}
function mutate(
WitnetBuffer.Buffer memory buffer,
uint length,
bytes memory pokes
)
internal pure
withinRange(length, buffer.data.length - buffer.cursor + 1)
{
bytes[] memory parts = new bytes[](3);
parts[0] = peek(
buffer,
0,
buffer.cursor
);
parts[1] = pokes;
parts[2] = peek(
buffer,
buffer.cursor + length,
buffer.data.length - buffer.cursor - length
);
buffer.data = concat(parts);
}
/// @notice Read and consume the next byte from the buffer.
/// @param buffer An instance of `Buffer`.
/// @return The next byte in the buffer counting from the cursor position.
function next(Buffer memory buffer)
internal pure
withinRange(buffer.cursor, buffer.data.length)
returns (bytes1)
{
// Return the byte at the position marked by the cursor and advance the cursor all at once
return buffer.data[buffer.cursor ++];
}
function peek(
WitnetBuffer.Buffer memory buffer,
uint offset,
uint length
)
internal pure
withinRange(offset + length, buffer.data.length)
returns (bytes memory)
{
bytes memory data = buffer.data;
bytes memory peeks = new bytes(length);
uint destinationPointer;
uint sourcePointer;
assembly {
destinationPointer := add(peeks, 32)
sourcePointer := add(add(data, 32), offset)
}
memcpy(
destinationPointer,
sourcePointer,
length
);
return peeks;
}
// @notice Extract bytes array from buffer starting from current cursor.
/// @param buffer An instance of `Buffer`.
/// @param length How many bytes to peek from the Buffer.
// solium-disable-next-line security/no-assign-params
function peek(
WitnetBuffer.Buffer memory buffer,
uint length
)
internal pure
withinRange(length, buffer.data.length - buffer.cursor)
returns (bytes memory)
{
return peek(
buffer,
buffer.cursor,
length
);
}
/// @notice Read and consume a certain amount of bytes from the buffer.
/// @param buffer An instance of `Buffer`.
/// @param length How many bytes to read and consume from the buffer.
/// @return output A `bytes memory` containing the first `length` bytes from the buffer, counting from the cursor position.
function read(Buffer memory buffer, uint length)
internal pure
withinRange(buffer.cursor + length, buffer.data.length)
returns (bytes memory output)
{
// Create a new `bytes memory destination` value
output = new bytes(length);
// Early return in case that bytes length is 0
if (length > 0) {
bytes memory input = buffer.data;
uint offset = buffer.cursor;
// Get raw pointers for source and destination
uint sourcePointer;
uint destinationPointer;
assembly {
sourcePointer := add(add(input, 32), offset)
destinationPointer := add(output, 32)
}
// Copy `length` bytes from source to destination
memcpy(
destinationPointer,
sourcePointer,
length
);
// Move the cursor forward by `length` bytes
seek(
buffer,
length,
true
);
}
}
/// @notice Read and consume the next 2 bytes from the buffer as an IEEE 754-2008 floating point number enclosed in an
/// `int32`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `float16`
/// use cases. In other words, the integer output of this method is 10,000 times the actual value. The input bytes are
/// expected to follow the 16-bit base-2 format (a.k.a. `binary16`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int32` value of the next 4 bytes in the buffer counting from the cursor position.
function readFloat16(Buffer memory buffer)
internal pure
returns (int32 result)
{
uint32 value = readUint16(buffer);
// Get bit at position 0
uint32 sign = value & 0x8000;
// Get bits 1 to 5, then normalize to the [-15, 16] range so as to counterweight the IEEE 754 exponent bias
int32 exponent = (int32(value & 0x7c00) >> 10) - 15;
// Get bits 6 to 15
int32 fraction = int32(value & 0x03ff);
// Add 2^10 to the fraction if exponent is not -15
if (exponent != -15) {
fraction |= 0x400;
} else if (exponent == 16) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat16: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 1024)`
if (exponent >= 0) {
result = int32(int(
int(1 << uint256(int256(exponent)))
* 10000
* fraction
) >> 10);
} else {
result = int32(int(
int(fraction)
* 10000
/ int(1 << uint(int(- exponent)))
) >> 10);
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
/// @notice Consume the next 4 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be OK for most `float32`
/// use cases. In other words, the integer output of this method is 10^9 times the actual value. The input bytes are
/// expected to follow the 64-bit base-2 format (a.k.a. `binary32`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
function readFloat32(Buffer memory buffer)
internal pure
returns (int result)
{
uint value = readUint32(buffer);
// Get bit at position 0
uint sign = value & 0x80000000;
// Get bits 1 to 8, then normalize to the [-127, 128] range so as to counterweight the IEEE 754 exponent bias
int exponent = (int(value & 0x7f800000) >> 23) - 127;
// Get bits 9 to 31
int fraction = int(value & 0x007fffff);
// Add 2^23 to the fraction if exponent is not -127
if (exponent != -127) {
fraction |= 0x800000;
} else if (exponent == 128) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat32: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 2^23)`
if (exponent >= 0) {
result = (
int(1 << uint(exponent))
* (10 ** 9)
* fraction
) >> 23;
} else {
result = (
fraction
* (10 ** 9)
/ int(1 << uint(-exponent))
) >> 23;
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
/// @notice Consume the next 8 bytes from the buffer as an IEEE 754-2008 floating point number enclosed into an `int`.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values
/// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be OK for most `float64`
/// use cases. In other words, the integer output of this method is 10^15 times the actual value. The input bytes are
/// expected to follow the 64-bit base-2 format (a.k.a. `binary64`) in the IEEE 754-2008 standard.
/// @param buffer An instance of `Buffer`.
/// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor position.
function readFloat64(Buffer memory buffer)
internal pure
returns (int result)
{
uint value = readUint64(buffer);
// Get bit at position 0
uint sign = value & 0x8000000000000000;
// Get bits 1 to 12, then normalize to the [-1023, 1024] range so as to counterweight the IEEE 754 exponent bias
int exponent = (int(value & 0x7ff0000000000000) >> 52) - 1023;
// Get bits 6 to 15
int fraction = int(value & 0x000fffffffffffff);
// Add 2^52 to the fraction if exponent is not -1023
if (exponent != -1023) {
fraction |= 0x10000000000000;
} else if (exponent == 1024) {
revert(
string(abi.encodePacked(
"WitnetBuffer.readFloat64: ",
sign != 0 ? "negative" : hex"",
" infinity"
))
);
}
// Compute `2 ^ exponent · (1 + fraction / 1024)`
if (exponent >= 0) {
result = (
int(1 << uint(exponent))
* (10 ** 15)
* fraction
) >> 52;
} else {
result = (
fraction
* (10 ** 15)
/ int(1 << uint(-exponent))
) >> 52;
}
// Make the result negative if the sign bit is not 0
if (sign != 0) {
result *= -1;
}
}
// Read a text string of a given length from a buffer. Returns a `bytes memory` value for the sake of genericness,
/// but it can be easily casted into a string with `string(result)`.
// solium-disable-next-line security/no-assign-params
function readText(
WitnetBuffer.Buffer memory buffer,
uint64 length
)
internal pure
returns (bytes memory text)
{
text = new bytes(length);
unchecked {
for (uint64 index = 0; index < length; index ++) {
uint8 char = readUint8(buffer);
if (char & 0x80 != 0) {
if (char < 0xe0) {
char = (char & 0x1f) << 6
| (readUint8(buffer) & 0x3f);
length -= 1;
} else if (char < 0xf0) {
char = (char & 0x0f) << 12
| (readUint8(buffer) & 0x3f) << 6
| (readUint8(buffer) & 0x3f);
length -= 2;
} else {
char = (char & 0x0f) << 18
| (readUint8(buffer) & 0x3f) << 12
| (readUint8(buffer) & 0x3f) << 6
| (readUint8(buffer) & 0x3f);
length -= 3;
}
}
text[index] = bytes1(char);
}
// Adjust text to actual length:
assembly {
mstore(text, length)
}
}
}
/// @notice Read and consume the next byte from the buffer as an `uint8`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint8` value of the next byte in the buffer counting from the cursor position.
function readUint8(Buffer memory buffer)
internal pure
withinRange(buffer.cursor, buffer.data.length)
returns (uint8 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 1), offset))
}
buffer.cursor ++;
}
/// @notice Read and consume the next 2 bytes from the buffer as an `uint16`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint16` value of the next 2 bytes in the buffer counting from the cursor position.
function readUint16(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 2, buffer.data.length)
returns (uint16 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 2), offset))
}
buffer.cursor += 2;
}
/// @notice Read and consume the next 4 bytes from the buffer as an `uint32`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint32` value of the next 4 bytes in the buffer counting from the cursor position.
function readUint32(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 4, buffer.data.length)
returns (uint32 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 4), offset))
}
buffer.cursor += 4;
}
/// @notice Read and consume the next 8 bytes from the buffer as an `uint64`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint64` value of the next 8 bytes in the buffer counting from the cursor position.
function readUint64(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 8, buffer.data.length)
returns (uint64 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 8), offset))
}
buffer.cursor += 8;
}
/// @notice Read and consume the next 16 bytes from the buffer as an `uint128`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint128` value of the next 16 bytes in the buffer counting from the cursor position.
function readUint128(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 16, buffer.data.length)
returns (uint128 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 16), offset))
}
buffer.cursor += 16;
}
/// @notice Read and consume the next 32 bytes from the buffer as an `uint256`.
/// @param buffer An instance of `Buffer`.
/// @return value The `uint256` value of the next 32 bytes in the buffer counting from the cursor position.
function readUint256(Buffer memory buffer)
internal pure
withinRange(buffer.cursor + 32, buffer.data.length)
returns (uint256 value)
{
bytes memory data = buffer.data;
uint offset = buffer.cursor;
assembly {
value := mload(add(add(data, 32), offset))
}
buffer.cursor += 32;
}
/// @notice Count number of required parameters for given bytes arrays
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input Bytes array containing strings.
/// @param count Highest wildcard index found, plus 1.
function argsCountOf(bytes memory input)
internal pure
returns (uint8 count)
{
if (input.length < 3) {
return 0;
}
unchecked {
uint ix = 0;
uint length = input.length - 2;
for (; ix < length; ) {
if (
input[ix] == bytes1("\\")
&& input[ix + 2] == bytes1("\\")
&& input[ix + 1] >= bytes1("0")
&& input[ix + 1] <= bytes1("9")
) {
uint8 ax = uint8(uint8(input[ix + 1]) - uint8(bytes1("0")) + 1);
if (ax > count) {
count = ax;
}
ix += 3;
} else {
ix ++;
}
}
}
}
/// @notice Replace bytecode indexed wildcards by correspondent substrings.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input Bytes array containing strings.
/// @param args Array of substring values for replacing indexed wildcards.
/// @return output Resulting bytes array after replacing all wildcards.
/// @return hits Total number of replaced wildcards.
function replace(bytes memory input, string[] memory args)
internal pure
returns (bytes memory output, uint hits)
{
uint ix = 0; uint lix = 0;
uint inputLength;
uint inputPointer;
uint outputLength;
uint outputPointer;
uint source;
uint sourceLength;
uint sourcePointer;
if (input.length < 3) {
return (input, 0);
}
assembly {
// set starting input pointer
inputPointer := add(input, 32)
// get safe output location
output := mload(0x40)
// set starting output pointer
outputPointer := add(output, 32)
}
unchecked {
uint length = input.length - 2;
for (; ix < length; ) {
if (
input[ix] == bytes1("\\")
&& input[ix + 2] == bytes1("\\")
&& input[ix + 1] >= bytes1("0")
&& input[ix + 1] <= bytes1("9")
) {
inputLength = (ix - lix);
if (ix > lix) {
memcpy(
outputPointer,
inputPointer,
inputLength
);
inputPointer += inputLength + 3;
outputPointer += inputLength;
} else {
inputPointer += 3;
}
uint ax = uint(uint8(input[ix + 1]) - uint8(bytes1("0")));
if (ax >= args.length) {
revert MissingArgs(ax + 1, args.length);
}
assembly {
source := mload(add(args, mul(32, add(ax, 1))))
sourceLength := mload(source)
sourcePointer := add(source, 32)
}
memcpy(
outputPointer,
sourcePointer,
sourceLength
);
outputLength += inputLength + sourceLength;
outputPointer += sourceLength;
ix += 3;
lix = ix;
hits ++;
} else {
ix ++;
}
}
ix = input.length;
}
if (outputLength > 0) {
if (ix > lix ) {
memcpy(
outputPointer,
inputPointer,
ix - lix
);
outputLength += (ix - lix);
}
assembly {
// set final output length
mstore(output, outputLength)
// protect output bytes
mstore(0x40, add(mload(0x40), add(outputLength, 32)))
}
}
else {
return (input, 0);
}
}
/// @notice Replace string indexed wildcards by correspondent substrings.
/// @dev Wildcard format: "\#\", with # in ["0".."9"].
/// @param input String potentially containing wildcards.
/// @param args Array of substring values for replacing indexed wildcards.
/// @return output Resulting string after replacing all wildcards.
function replace(string memory input, string[] memory args)
internal pure
returns (string memory)
{
(bytes memory _outputBytes, ) = replace(bytes(input), args);
return string(_outputBytes);
}
/// @notice Move the inner cursor of the buffer to a relative or absolute position.
/// @param buffer An instance of `Buffer`.
/// @param offset How many bytes to move the cursor forward.
/// @param relative Whether to count `offset` from the last position of the cursor (`true`) or the beginning of the
/// buffer (`true`).
/// @return The final position of the cursor (will equal `offset` if `relative` is `false`).
// solium-disable-next-line security/no-assign-params
function seek(
Buffer memory buffer,
uint offset,
bool relative
)
internal pure
withinRange(offset, buffer.data.length)
returns (uint)
{
// Deal with relative offsets
if (relative) {
offset += buffer.cursor;
}
buffer.cursor = offset;
return offset;
}
/// @notice Move the inner cursor a number of bytes forward.
/// @dev This is a simple wrapper around the relative offset case of `seek()`.
/// @param buffer An instance of `Buffer`.
/// @param relativeOffset How many bytes to move the cursor forward.
/// @return The final position of the cursor.
function seek(
Buffer memory buffer,
uint relativeOffset
)
internal pure
returns (uint)
{
return seek(
buffer,
relativeOffset,
true
);
}
/// @notice Copy bytes from one memory address into another.
/// @dev This function was borrowed from Nick Johnson's `solidity-stringutils` lib, and reproduced here under the terms
/// of [Apache License 2.0](https://github.com/Arachnid/solidity-stringutils/blob/master/LICENSE).
/// @param dest Address of the destination memory.
/// @param src Address to the source memory.
/// @param len How many bytes to copy.
// solium-disable-next-line security/no-assign-params
function memcpy(
uint dest,
uint src,
uint len
)
private pure
{
unchecked {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
if (len > 0) {
// Copy remaining bytes
uint _mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(_mask))
let destpart := and(mload(dest), _mask)
mstore(dest, or(destpart, srcpart))
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./WitnetCBOR.sol";
library Witnet {
using WitnetBuffer for WitnetBuffer.Buffer;
using WitnetCBOR for WitnetCBOR.CBOR;
using WitnetCBOR for WitnetCBOR.CBOR[];
/// Struct containing both request and response data related to every query posted to the Witnet Request Board
struct Query {
Request request;
Response response;
address from; // Address from which the request was posted.
}
/// Possible status of a Witnet query.
enum QueryStatus {
Unknown,
Posted,
Reported,
Deleted
}
/// Data kept in EVM-storage for every Request posted to the Witnet Request Board.
struct Request {
address addr; // Address of the (deprecated) IWitnetRequest contract containing Witnet data request raw bytecode.
bytes32 slaHash; // Radon SLA hash of the Witnet data request.
bytes32 radHash; // Radon radHash of the Witnet data request.
uint256 gasprice; // Minimum gas price the DR resolver should pay on the solving tx.
uint256 reward; // Escrowed reward to be paid to the DR resolver.
}
/// Data kept in EVM-storage containing the Witnet-provided response metadata and CBOR-encoded result.
struct Response {
address reporter; // Address from which the result was reported.
uint256 timestamp; // Timestamp of the Witnet-provided result.
bytes32 drTxHash; // Hash of the Witnet transaction that solved the queried Data Request.
bytes cborBytes; // Witnet-provided result CBOR-bytes to the queried Data Request.
}
/// Data struct containing the Witnet-provided result to a Data Request.
struct Result {
bool success; // Flag stating whether the request could get solved successfully, or not.
WitnetCBOR.CBOR value; // Resulting value, in CBOR-serialized bytes.
}
/// Final query's result status from a requester's point of view.
enum ResultStatus {
Void,
Awaiting,
Ready,
Error
}
/// Data struct describing an error when trying to fetch a Witnet-provided result to a Data Request.
struct ResultError {
ResultErrorCodes code;
string reason;
}
enum ResultErrorCodes {
/// 0x00: Unknown error. Something went really bad!
Unknown,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Source-specific format error sub-codes ============================================================================
/// 0x01: At least one of the source scripts is not a valid CBOR-encoded value.
SourceScriptNotCBOR,
/// 0x02: The CBOR value decoded from a source script is not an Array.
SourceScriptNotArray,
/// 0x03: The Array value decoded form a source script is not a valid Data Request.
SourceScriptNotRADON,
/// 0x04: The request body of at least one data source was not properly formated.
SourceRequestBody,
/// 0x05: The request headers of at least one data source was not properly formated.
SourceRequestHeaders,
/// 0x06: The request URL of at least one data source was not properly formated.
SourceRequestURL,
/// Unallocated
SourceFormat0x07, SourceFormat0x08, SourceFormat0x09, SourceFormat0x0A, SourceFormat0x0B, SourceFormat0x0C,
SourceFormat0x0D, SourceFormat0x0E, SourceFormat0x0F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Complexity error sub-codes ========================================================================================
/// 0x10: The request contains too many sources.
RequestTooManySources,
/// 0x11: The script contains too many calls.
ScriptTooManyCalls,
/// Unallocated
Complexity0x12, Complexity0x13, Complexity0x14, Complexity0x15, Complexity0x16, Complexity0x17, Complexity0x18,
Complexity0x19, Complexity0x1A, Complexity0x1B, Complexity0x1C, Complexity0x1D, Complexity0x1E, Complexity0x1F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Lack of support error sub-codes ===================================================================================
/// 0x20: Some Radon operator code was found that is not supported (1+ args).
UnsupportedOperator,
/// 0x21: Some Radon filter opcode is not currently supported (1+ args).
UnsupportedFilter,
/// 0x22: Some Radon request type is not currently supported (1+ args).
UnsupportedHashFunction,
/// 0x23: Some Radon reducer opcode is not currently supported (1+ args)
UnsupportedReducer,
/// 0x24: Some Radon hash function is not currently supported (1+ args).
UnsupportedRequestType,
/// 0x25: Some Radon encoding function is not currently supported (1+ args).
UnsupportedEncodingFunction,
/// Unallocated
Operator0x26, Operator0x27,
/// 0x28: Wrong number (or type) of arguments were passed to some Radon operator.
WrongArguments,
/// Unallocated
Operator0x29, Operator0x2A, Operator0x2B, Operator0x2C, Operator0x2D, Operator0x2E, Operator0x2F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Retrieve-specific circumstantial error sub-codes ================================================================================
/// 0x30: A majority of data sources returned an HTTP status code other than 200 (1+ args):
HttpErrors,
/// 0x31: A majority of data sources timed out:
RetrievalsTimeout,
/// Unallocated
RetrieveCircumstance0x32, RetrieveCircumstance0x33, RetrieveCircumstance0x34, RetrieveCircumstance0x35,
RetrieveCircumstance0x36, RetrieveCircumstance0x37, RetrieveCircumstance0x38, RetrieveCircumstance0x39,
RetrieveCircumstance0x3A, RetrieveCircumstance0x3B, RetrieveCircumstance0x3C, RetrieveCircumstance0x3D,
RetrieveCircumstance0x3E, RetrieveCircumstance0x3F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Scripting-specific runtime error sub-code =========================================================================
/// 0x40: Math operator caused an underflow.
MathUnderflow,
/// 0x41: Math operator caused an overflow.
MathOverflow,
/// 0x42: Math operator tried to divide by zero.
MathDivisionByZero,
/// 0x43:Wrong input to subscript call.
WrongSubscriptInput,
/// 0x44: Value cannot be extracted from input binary buffer.
BufferIsNotValue,
/// 0x45: Value cannot be decoded from expected type.
Decode,
/// 0x46: Unexpected empty array.
EmptyArray,
/// 0x47: Value cannot be encoded to expected type.
Encode,
/// 0x48: Failed to filter input values (1+ args).
Filter,
/// 0x49: Failed to hash input value.
Hash,
/// 0x4A: Mismatching array ranks.
MismatchingArrays,
/// 0x4B: Failed to process non-homogenous array.
NonHomegeneousArray,
/// 0x4C: Failed to parse syntax of some input value, or argument.
Parse,
/// 0x4E: Parsing logic limits were exceeded.
ParseOverflow,
/// 0x4F: Unallocated
ScriptError0x4F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Actual first-order result error codes =============================================================================
/// 0x50: Not enough reveals were received in due time:
InsufficientReveals,
/// 0x51: No actual reveal majority was reached on tally stage:
InsufficientMajority,
/// 0x52: Not enough commits were received before tally stage:
InsufficientCommits,
/// 0x53: Generic error during tally execution (to be deprecated after WIP #0028)
TallyExecution,
/// 0x54: A majority of data sources could either be temporarily unresponsive or failing to report the requested data:
CircumstantialFailure,
/// 0x55: At least one data source is inconsistent when queried through multiple transports at once:
InconsistentSources,
/// 0x56: Any one of the (multiple) Retrieve, Aggregate or Tally scripts were badly formated:
MalformedDataRequest,
/// 0x57: Values returned from a majority of data sources don't match the expected schema:
MalformedResponses,
/// Unallocated:
OtherError0x58, OtherError0x59, OtherError0x5A, OtherError0x5B, OtherError0x5C, OtherError0x5D, OtherError0x5E,
/// 0x5F: Size of serialized tally result exceeds allowance:
OversizedTallyResult,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Inter-stage runtime error sub-codes ===============================================================================
/// 0x60: Data aggregation reveals could not get decoded on the tally stage:
MalformedReveals,
/// 0x61: The result to data aggregation could not get encoded:
EncodeReveals,
/// 0x62: A mode tie ocurred when calculating some mode value on the aggregation or the tally stage:
ModeTie,
/// Unallocated:
OtherError0x63, OtherError0x64, OtherError0x65, OtherError0x66, OtherError0x67, OtherError0x68, OtherError0x69,
OtherError0x6A, OtherError0x6B, OtherError0x6C, OtherError0x6D, OtherError0x6E, OtherError0x6F,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Runtime access error sub-codes ====================================================================================
/// 0x70: Tried to access a value from an array using an index that is out of bounds (1+ args):
ArrayIndexOutOfBounds,
/// 0x71: Tried to access a value from a map using a key that does not exist (1+ args):
MapKeyNotFound,
/// 0X72: Tried to extract value from a map using a JSON Path that returns no values (+1 args):
JsonPathNotFound,
/// Unallocated:
OtherError0x73, OtherError0x74, OtherError0x75, OtherError0x76, OtherError0x77, OtherError0x78,
OtherError0x79, OtherError0x7A, OtherError0x7B, OtherError0x7C, OtherError0x7D, OtherError0x7E, OtherError0x7F,
OtherError0x80, OtherError0x81, OtherError0x82, OtherError0x83, OtherError0x84, OtherError0x85, OtherError0x86,
OtherError0x87, OtherError0x88, OtherError0x89, OtherError0x8A, OtherError0x8B, OtherError0x8C, OtherError0x8D,
OtherError0x8E, OtherError0x8F, OtherError0x90, OtherError0x91, OtherError0x92, OtherError0x93, OtherError0x94,
OtherError0x95, OtherError0x96, OtherError0x97, OtherError0x98, OtherError0x99, OtherError0x9A, OtherError0x9B,
OtherError0x9C, OtherError0x9D, OtherError0x9E, OtherError0x9F, OtherError0xA0, OtherError0xA1, OtherError0xA2,
OtherError0xA3, OtherError0xA4, OtherError0xA5, OtherError0xA6, OtherError0xA7, OtherError0xA8, OtherError0xA9,
OtherError0xAA, OtherError0xAB, OtherError0xAC, OtherError0xAD, OtherError0xAE, OtherError0xAF, OtherError0xB0,
OtherError0xB1, OtherError0xB2, OtherError0xB3, OtherError0xB4, OtherError0xB5, OtherError0xB6, OtherError0xB7,
OtherError0xB8, OtherError0xB9, OtherError0xBA, OtherError0xBB, OtherError0xBC, OtherError0xBD, OtherError0xBE,
OtherError0xBF, OtherError0xC0, OtherError0xC1, OtherError0xC2, OtherError0xC3, OtherError0xC4, OtherError0xC5,
OtherError0xC6, OtherError0xC7, OtherError0xC8, OtherError0xC9, OtherError0xCA, OtherError0xCB, OtherError0xCC,
OtherError0xCD, OtherError0xCE, OtherError0xCF, OtherError0xD0, OtherError0xD1, OtherError0xD2, OtherError0xD3,
OtherError0xD4, OtherError0xD5, OtherError0xD6, OtherError0xD7, OtherError0xD8, OtherError0xD9, OtherError0xDA,
OtherError0xDB, OtherError0xDC, OtherError0xDD, OtherError0xDE, OtherError0xDF,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Inter-client generic error codes ==================================================================================
/// Data requests that cannot be relayed into the Witnet blockchain should be reported
/// with one of these errors.
/// 0xE0: Requests that cannot be parsed must always get this error as their result.
BridgeMalformedDataRequest,
/// 0xE1: Witnesses exceeds 100
BridgePoorIncentives,
/// 0xE2: The request is rejected on the grounds that it may cause the submitter to spend or stake an
/// amount of value that is unjustifiably high when compared with the reward they will be getting
BridgeOversizedTallyResult,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Unallocated =======================================================================================================
OtherError0xE3, OtherError0xE4, OtherError0xE5, OtherError0xE6, OtherError0xE7, OtherError0xE8, OtherError0xE9,
OtherError0xEA, OtherError0xEB, OtherError0xEC, OtherError0xED, OtherError0xEE, OtherError0xEF, OtherError0xF0,
OtherError0xF1, OtherError0xF2, OtherError0xF3, OtherError0xF4, OtherError0xF5, OtherError0xF6, OtherError0xF7,
OtherError0xF8, OtherError0xF9, OtherError0xFA, OtherError0xFB, OtherError0xFC, OtherError0xFD, OtherError0xFE,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 0xFF: Some tally error is not intercepted but it should (0+ args)
UnhandledIntercept
}
function isCircumstantial(ResultErrorCodes self) internal pure returns (bool) {
return (self == ResultErrorCodes.CircumstantialFailure);
}
function lackOfConsensus(ResultErrorCodes self) internal pure returns (bool) {
return (
self == ResultErrorCodes.InsufficientCommits
|| self == ResultErrorCodes.InsufficientMajority
|| self == ResultErrorCodes.InsufficientReveals
);
}
function isRetriable(ResultErrorCodes self) internal pure returns (bool) {
return (
lackOfConsensus(self)
|| isCircumstantial(self)
|| poorIncentives(self)
);
}
function poorIncentives(ResultErrorCodes self) internal pure returns (bool) {
return (
self == ResultErrorCodes.OversizedTallyResult
|| self == ResultErrorCodes.InsufficientCommits
|| self == ResultErrorCodes.BridgePoorIncentives
|| self == ResultErrorCodes.BridgeOversizedTallyResult
);
}
/// Possible Radon data request methods that can be used within a Radon Retrieval.
enum RadonDataRequestMethods {
/* 0 */ Unknown,
/* 1 */ HttpGet,
/* 2 */ RNG,
/* 3 */ HttpPost,
/* 4 */ HttpHead
}
/// Possible types either processed by Witnet Radon Scripts or included within results to Witnet Data Requests.
enum RadonDataTypes {
/* 0x00 */ Any,
/* 0x01 */ Array,
/* 0x02 */ Bool,
/* 0x03 */ Bytes,
/* 0x04 */ Integer,
/* 0x05 */ Float,
/* 0x06 */ Map,
/* 0x07 */ String,
Unused0x08, Unused0x09, Unused0x0A, Unused0x0B,
Unused0x0C, Unused0x0D, Unused0x0E, Unused0x0F,
/* 0x10 */ Same,
/* 0x11 */ Inner,
/* 0x12 */ Match,
/* 0x13 */ Subscript
}
/// Structure defining some data filtering that can be applied at the Aggregation or the Tally stages
/// within a Witnet Data Request resolution workflow.
struct RadonFilter {
RadonFilterOpcodes opcode;
bytes args;
}
/// Filtering methods currently supported on the Witnet blockchain.
enum RadonFilterOpcodes {
/* 0x00 */ Reserved0x00, //GreaterThan,
/* 0x01 */ Reserved0x01, //LessThan,
/* 0x02 */ Reserved0x02, //Equals,
/* 0x03 */ Reserved0x03, //AbsoluteDeviation,
/* 0x04 */ Reserved0x04, //RelativeDeviation
/* 0x05 */ StandardDeviation,
/* 0x06 */ Reserved0x06, //Top,
/* 0x07 */ Reserved0x07, //Bottom,
/* 0x08 */ Mode,
/* 0x09 */ Reserved0x09 //LessOrEqualThan
}
/// Structure defining the array of filters and reducting function to be applied at either the Aggregation
/// or the Tally stages within a Witnet Data Request resolution workflow.
struct RadonReducer {
RadonReducerOpcodes opcode;
RadonFilter[] filters;
}
/// Reducting functions currently supported on the Witnet blockchain.
enum RadonReducerOpcodes {
/* 0x00 */ Reserved0x00, //Minimum,
/* 0x01 */ Reserved0x01, //Maximum,
/* 0x02 */ Mode,
/* 0x03 */ AverageMean,
/* 0x04 */ Reserved0x04, //AverageMeanWeighted,
/* 0x05 */ AverageMedian,
/* 0x06 */ Reserved0x06, //AverageMedianWeighted,
/* 0x07 */ StandardDeviation,
/* 0x08 */ Reserved0x08, //AverageDeviation,
/* 0x09 */ Reserved0x09, //MedianDeviation,
/* 0x0A */ Reserved0x10, //MaximumDeviation,
/* 0x0B */ ConcatenateAndHash
}
/// Structure containing all the parameters that fully describe a Witnet Radon Retrieval within a Witnet Data Request.
struct RadonRetrieval {
uint8 argsCount;
RadonDataRequestMethods method;
RadonDataTypes resultDataType;
string url;
string body;
string[2][] headers;
bytes script;
}
/// Structure containing the Retrieve-Attestation-Delivery parts of a Witnet Data Request.
struct RadonRAD {
RadonRetrieval[] retrieve;
RadonReducer aggregate;
RadonReducer tally;
}
/// Structure containing the Service Level Aggreement parameters of a Witnet Data Request.
struct RadonSLA {
uint8 numWitnesses;
uint8 minConsensusPercentage;
uint64 witnessReward;
uint64 witnessCollateral;
uint64 minerCommitRevealFee;
}
/// ===============================================================================================================
/// --- 'uint*' helper methods ------------------------------------------------------------------------------------
/// @notice Convert a `uint8` into a 2 characters long `string` representing its two less significant hexadecimal values.
function toHexString(uint8 _u)
internal pure
returns (string memory)
{
bytes memory b2 = new bytes(2);
uint8 d0 = uint8(_u / 16) + 48;
uint8 d1 = uint8(_u % 16) + 48;
if (d0 > 57)
d0 += 7;
if (d1 > 57)
d1 += 7;
b2[0] = bytes1(d0);
b2[1] = bytes1(d1);
return string(b2);
}
/// @notice Convert a `uint8` into a 1, 2 or 3 characters long `string` representing its.
/// three less significant decimal values.
function toString(uint8 _u)
internal pure
returns (string memory)
{
if (_u < 10) {
bytes memory b1 = new bytes(1);
b1[0] = bytes1(uint8(_u) + 48);
return string(b1);
} else if (_u < 100) {
bytes memory b2 = new bytes(2);
b2[0] = bytes1(uint8(_u / 10) + 48);
b2[1] = bytes1(uint8(_u % 10) + 48);
return string(b2);
} else {
bytes memory b3 = new bytes(3);
b3[0] = bytes1(uint8(_u / 100) + 48);
b3[1] = bytes1(uint8(_u % 100 / 10) + 48);
b3[2] = bytes1(uint8(_u % 10) + 48);
return string(b3);
}
}
/// @notice Convert a `uint` into a string` representing its value.
function toString(uint v)
internal pure
returns (string memory)
{
uint maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint i = 0;
do {
uint8 remainder = uint8(v % 10);
v = v / 10;
reversed[i ++] = bytes1(48 + remainder);
} while (v != 0);
bytes memory buf = new bytes(i);
for (uint j = 1; j <= i; j ++) {
buf[j - 1] = reversed[i - j];
}
return string(buf);
}
/// ===============================================================================================================
/// --- 'bytes' helper methods ------------------------------------------------------------------------------------
/// @dev Transform given bytes into a Witnet.Result instance.
/// @param cborBytes Raw bytes representing a CBOR-encoded value.
/// @return A `Witnet.Result` instance.
function toWitnetResult(bytes memory cborBytes)
internal pure
returns (Witnet.Result memory)
{
WitnetCBOR.CBOR memory cborValue = WitnetCBOR.fromBytes(cborBytes);
return _resultFromCborValue(cborValue);
}
function toAddress(bytes memory _value) internal pure returns (address) {
return address(toBytes20(_value));
}
function toBytes4(bytes memory _value) internal pure returns (bytes4) {
return bytes4(toFixedBytes(_value, 4));
}
function toBytes20(bytes memory _value) internal pure returns (bytes20) {
return bytes20(toFixedBytes(_value, 20));
}
function toBytes32(bytes memory _value) internal pure returns (bytes32) {
return toFixedBytes(_value, 32);
}
function toFixedBytes(bytes memory _value, uint8 _numBytes)
internal pure
returns (bytes32 _bytes32)
{
assert(_numBytes <= 32);
unchecked {
uint _len = _value.length > _numBytes ? _numBytes : _value.length;
for (uint _i = 0; _i < _len; _i ++) {
_bytes32 |= bytes32(_value[_i] & 0xff) >> (_i * 8);
}
}
}
/// ===============================================================================================================
/// --- 'string' helper methods -----------------------------------------------------------------------------------
function toLowerCase(string memory str)
internal pure
returns (string memory)
{
bytes memory lowered = new bytes(bytes(str).length);
unchecked {
for (uint i = 0; i < lowered.length; i ++) {
uint8 char = uint8(bytes(str)[i]);
if (char >= 65 && char <= 90) {
lowered[i] = bytes1(char + 32);
} else {
lowered[i] = bytes1(char);
}
}
}
return string(lowered);
}
/// @notice Converts bytes32 into string.
function toString(bytes32 _bytes32)
internal pure
returns (string memory)
{
bytes memory _bytes = new bytes(_toStringLength(_bytes32));
for (uint _i = 0; _i < _bytes.length;) {
_bytes[_i] = _bytes32[_i];
unchecked {
_i ++;
}
}
return string(_bytes);
}
function tryUint(string memory str)
internal pure
returns (uint res, bool)
{
unchecked {
for (uint256 i = 0; i < bytes(str).length; i++) {
if (
(uint8(bytes(str)[i]) - 48) < 0
|| (uint8(bytes(str)[i]) - 48) > 9
) {
return (0, false);
}
res += (uint8(bytes(str)[i]) - 48) * 10 ** (bytes(str).length - i - 1);
}
return (res, true);
}
}
/// ===============================================================================================================
/// --- 'Witnet.Result' helper methods ----------------------------------------------------------------------------
modifier _isReady(Result memory result) {
require(result.success, "Witnet: tried to decode value from errored result.");
_;
}
/// @dev Decode an address from the Witnet.Result's CBOR value.
function asAddress(Witnet.Result memory result)
internal pure
_isReady(result)
returns (address)
{
if (result.value.majorType == uint8(WitnetCBOR.MAJOR_TYPE_BYTES)) {
return toAddress(result.value.readBytes());
} else {
// TODO
revert("WitnetLib: reading address from string not yet supported.");
}
}
/// @dev Decode a `bool` value from the Witnet.Result's CBOR value.
function asBool(Witnet.Result memory result)
internal pure
_isReady(result)
returns (bool)
{
return result.value.readBool();
}
/// @dev Decode a `bytes` value from the Witnet.Result's CBOR value.
function asBytes(Witnet.Result memory result)
internal pure
_isReady(result)
returns(bytes memory)
{
return result.value.readBytes();
}
/// @dev Decode a `bytes4` value from the Witnet.Result's CBOR value.
function asBytes4(Witnet.Result memory result)
internal pure
_isReady(result)
returns (bytes4)
{
return toBytes4(asBytes(result));
}
/// @dev Decode a `bytes32` value from the Witnet.Result's CBOR value.
function asBytes32(Witnet.Result memory result)
internal pure
_isReady(result)
returns (bytes32)
{
return toBytes32(asBytes(result));
}
/// @notice Returns the Witnet.Result's unread CBOR value.
function asCborValue(Witnet.Result memory result)
internal pure
_isReady(result)
returns (WitnetCBOR.CBOR memory)
{
return result.value;
}
/// @notice Decode array of CBOR values from the Witnet.Result's CBOR value.
function asCborArray(Witnet.Result memory result)
internal pure
_isReady(result)
returns (WitnetCBOR.CBOR[] memory)
{
return result.value.readArray();
}
/// @dev Decode a fixed16 (half-precision) numeric value from the Witnet.Result's CBOR value.
/// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this method offsets all values.
/// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be OK for most `fixed16`.
/// use cases. In other words, the output of this method is 10,000 times the actual value, encoded into an `int32`.
function asFixed16(Witnet.Result memory result)
internal pure
_isReady(result)
returns (int32)
{
return result.value.readFloat16();
}
/// @dev Decode an array of fixed16 values from the Witnet.Result's CBOR value.
function asFixed16Array(Witnet.Result memory result)
internal pure
_isReady(result)
returns (int32[] memory)
{
return result.value.readFloat16Array();
}
/// @dev Decode an `int64` value from the Witnet.Result's CBOR value.
function asInt(Witnet.Result memory result)
internal pure
_isReady(result)
returns (int)
{
return result.value.readInt();
}
/// @dev Decode an array of integer numeric values from a Witnet.Result as an `int[]` array.
/// @param result An instance of Witnet.Result.
/// @return The `int[]` decoded from the Witnet.Result.
function asIntArray(Witnet.Result memory result)
internal pure
_isReady(result)
returns (int[] memory)
{
return result.value.readIntArray();
}
/// @dev Decode a `string` value from the Witnet.Result's CBOR value.
/// @param result An instance of Witnet.Result.
/// @return The `string` decoded from the Witnet.Result.
function asText(Witnet.Result memory result)
internal pure
_isReady(result)
returns(string memory)
{
return result.value.readString();
}
/// @dev Decode an array of strings from the Witnet.Result's CBOR value.
/// @param result An instance of Witnet.Result.
/// @return The `string[]` decoded from the Witnet.Result.
function asTextArray(Witnet.Result memory result)
internal pure
_isReady(result)
returns (string[] memory)
{
return result.value.readStringArray();
}
/// @dev Decode a `uint64` value from the Witnet.Result's CBOR value.
/// @param result An instance of Witnet.Result.
/// @return The `uint` decoded from the Witnet.Result.
function asUint(Witnet.Result memory result)
internal pure
_isReady(result)
returns (uint)
{
return result.value.readUint();
}
/// @dev Decode an array of `uint64` values from the Witnet.Result's CBOR value.
/// @param result An instance of Witnet.Result.
/// @return The `uint[]` decoded from the Witnet.Result.
function asUintArray(Witnet.Result memory result)
internal pure
returns (uint[] memory)
{
return result.value.readUintArray();
}
/// ===============================================================================================================
/// --- Witnet library private methods ----------------------------------------------------------------------------
/// @dev Decode a CBOR value into a Witnet.Result instance.
function _resultFromCborValue(WitnetCBOR.CBOR memory cbor)
private pure
returns (Witnet.Result memory)
{
// Witnet uses CBOR tag 39 to represent RADON error code identifiers.
// [CBOR tag 39] Identifiers for CBOR: https://github.com/lucas-clemente/cbor-specs/blob/master/id.md
bool success = cbor.tag != 39;
return Witnet.Result(success, cbor);
}
/// @dev Calculate length of string-equivalent to given bytes32.
function _toStringLength(bytes32 _bytes32)
private pure
returns (uint _length)
{
for (; _length < 32; ) {
if (_bytes32[_length] == 0) {
break;
}
unchecked {
_length ++;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface IWitnetRequestFactory {
event WitnetRequestTemplateBuilt(address template, bool parameterized);
function buildRequestTemplate(
bytes32[] memory sourcesIds,
bytes32 aggregatorId,
bytes32 tallyId,
uint16 resultDataMaxSize
) external returns (address template);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../libs/WitnetV2.sol";
interface IWitnetRequestBytecodes {
error UnknownRadonRetrieval(bytes32 hash);
error UnknownRadonReducer(bytes32 hash);
error UnknownRadonRequest(bytes32 hash);
event NewDataProvider(uint256 index);
event NewRadonRetrievalHash(bytes32 hash);
event NewRadonReducerHash(bytes32 hash);
event NewRadHash(bytes32 hash);
function bytecodeOf(bytes32 radHash) external view returns (bytes memory);
function bytecodeOf(bytes32 radHash, WitnetV2.RadonSLA calldata sla) external view returns (bytes memory);
function bytecodeOf(bytes calldata radBytecode, WitnetV2.RadonSLA calldata sla) external view returns (bytes memory);
function hashOf(bytes calldata) external view returns (bytes32);
function lookupDataProvider(uint256 index) external view returns (string memory, uint);
function lookupDataProviderIndex(string calldata authority) external view returns (uint);
function lookupDataProviderSources(uint256 index, uint256 offset, uint256 length) external view returns (bytes32[] memory);
function lookupRadonReducer(bytes32 hash) external view returns (Witnet.RadonReducer memory);
function lookupRadonRetrieval(bytes32 hash) external view returns (Witnet.RadonRetrieval memory);
function lookupRadonRetrievalArgsCount(bytes32 hash) external view returns (uint8);
function lookupRadonRetrievalResultDataType(bytes32 hash) external view returns (Witnet.RadonDataTypes);
function lookupRadonRequestAggregator(bytes32 radHash) external view returns (Witnet.RadonReducer memory);
function lookupRadonRequestResultMaxSize(bytes32 radHash) external view returns (uint16);
function lookupRadonRequestResultDataType(bytes32 radHash) external view returns (Witnet.RadonDataTypes);
function lookupRadonRequestSources(bytes32 radHash) external view returns (bytes32[] memory);
function lookupRadonRequestSourcesCount(bytes32 radHash) external view returns (uint);
function lookupRadonRequestTally(bytes32 radHash) external view returns (Witnet.RadonReducer memory);
function verifyRadonRetrieval(
Witnet.RadonDataRequestMethods requestMethod,
string calldata requestURL,
string calldata requestBody,
string[2][] calldata requestHeaders,
bytes calldata requestRadonScript
) external returns (bytes32 hash);
function verifyRadonReducer(Witnet.RadonReducer calldata reducer)
external returns (bytes32 hash);
function verifyRadonRequest(
bytes32[] calldata sources,
bytes32 aggregator,
bytes32 tally,
uint16 resultMaxSize,
string[][] calldata args
) external returns (bytes32 radHash);
function totalDataProviders() external view returns (uint);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../libs/WitnetV2.sol";
/// @title The Witnet Randomness generator interface.
/// @author Witnet Foundation.
interface IWitnetRandomnessEvents {
event Randomizing(
uint256 blockNumber,
uint256 evmTxGasPrice,
uint256 evmRandomizeFee,
uint256 witnetQueryId,
WitnetV2.RadonSLA witnetQuerySLA
);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "../libs/WitnetV2.sol";
interface IWitnetRandomnessAdmin {
function acceptOwnership() external;
function baseFeeOverheadPercentage() external view returns (uint16);
function owner() external view returns (address);
function pendingOwner() external returns (address);
function transferOwnership(address) external;
function settleBaseFeeOverheadPercentage(uint16) external;
function settleWitnetQuerySLA(WitnetV2.RadonSLA calldata) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../WitnetOracle.sol";
/// @title The Witnet Randomness generator interface.
/// @author Witnet Foundation.
interface IWitnetRandomness {
/// @notice Returns amount of wei required to be paid as a fee when requesting randomization with a
/// transaction gas price as the one given.
function estimateRandomizeFee(uint256 evmGasPrice) external view returns (uint256);
/// @notice Retrieves the result of keccak256-hashing the given block number with the randomness value
/// @notice generated by the Witnet Oracle blockchain in response to the first non-errored randomize request solved
/// @notice after such block number.
/// @dev Reverts if:
/// @dev i. no `randomize()` was requested on neither the given block, nor afterwards.
/// @dev ii. the first non-errored `randomize()` request found on or after the given block is not solved yet.
/// @dev iii. all `randomize()` requests that took place on or after the given block were solved with errors.
/// @param blockNumber Block number from which the search will start.
function fetchRandomnessAfter(uint256 blockNumber) external view returns (bytes32);
/// @notice Retrieves the actual random value, unique hash and timestamp of the witnessing commit/reveal act that took
/// @notice place in the Witnet Oracle blockchain in response to the first non-errored randomize request
/// @notice solved after the given block number.
/// @dev Reverts if:
/// @dev i. no `randomize()` was requested on neither the given block, nor afterwards.
/// @dev ii. the first non-errored `randomize()` request found on or after the given block is not solved yet.
/// @dev iii. all `randomize()` requests that took place on or after the given block were solved with errors.
/// @param blockNumber Block number from which the search will start.
/// @return witnetResultRandomness Random value provided by the Witnet blockchain and used for solving randomness after given block.
/// @return witnetResultTimestamp Timestamp at which the randomness value was generated by the Witnet blockchain.
/// @return witnetResultTallyHash Hash of the witnessing commit/reveal act that took place on the Witnet blockchain.
/// @return witnetResultFinalityBlock EVM block number from which the provided randomness can be considered to be final.
function fetchRandomnessAfterProof(uint256 blockNumber) external view returns (
bytes32 witnetResultRandomness,
uint64 witnetResultTimestamp,
bytes32 witnetResultTallyHash,
uint256 witnetResultFinalityBlock
);
/// @notice Returns last block number on which a randomize was requested.
function getLastRandomizeBlock() external view returns (uint256);
/// @notice Retrieves metadata related to the randomize request that got posted to the
/// @notice Witnet Oracle contract on the given block number.
/// @dev Returns zero values if no randomize request was actually posted on the given block.
/// @return witnetQueryId Identifier of the underlying Witnet query created on the given block number.
/// @return prevRandomizeBlock Block number in which a randomize request got posted just before this one. 0 if none.
/// @return nextRandomizeBlock Block number in which a randomize request got posted just after this one, 0 if none.
function getRandomizeData(uint256 blockNumber) external view returns (
uint256 witnetQueryId,
uint256 prevRandomizeBlock,
uint256 nextRandomizeBlock
);
/// @notice Returns the number of the next block in which a randomize request was posted after the given one.
/// @param blockNumber Block number from which the search will start.
/// @return Number of the first block found after the given one, or `0` otherwise.
function getRandomizeNextBlock(uint256 blockNumber) external view returns (uint256);
/// @notice Returns the number of the previous block in which a randomize request was posted before the given one.
/// @param blockNumber Block number from which the search will start.
/// @return First block found before the given one, or `0` otherwise.
function getRandomizePrevBlock(uint256 blockNumber) external view returns (uint256);
/// @notice Gets current status of the first non-errored randomize request posted on or after the given block number.
/// @dev Possible values:
/// @dev - 0 -> Void: no randomize request was actually posted on or after the given block number.
/// @dev - 1 -> Awaiting: a randomize request was found but it's not yet solved by the Witnet blockchain.
/// @dev - 2 -> Ready: a successfull randomize value was reported and ready to be read.
/// @dev - 3 -> Error: all randomize resolutions after the given block were solved with errors.
/// @dev - 4 -> Finalizing: a randomize resolution has been reported from the Witnet blockchain, but it's not yet final.
function getRandomizeStatus(uint256 blockNumber) external view returns (WitnetV2.ResponseStatus);
/// @notice Returns `true` only if a successfull resolution from the Witnet blockchain is found for the first
/// @notice non-errored randomize request posted on or after the given block number.
function isRandomized(uint256 blockNumber) external view returns (bool);
/// @notice Generates a pseudo-random number uniformly distributed within the range [0 .. _range), by using
/// @notice the given `nonce` and the randomness returned by `getRandomnessAfter(blockNumber)`.
/// @dev Fails under same conditions as `getRandomnessAfter(uint256)` does.
/// @param range Range within which the uniformly-distributed random number will be generated.
/// @param nonce Nonce value enabling multiple random numbers from the same randomness value.
/// @param blockNumber Block number from which the search for the first randomize request solved aftewards will start.
function random(uint32 range, uint256 nonce, uint256 blockNumber) external view returns (uint32);
/// @notice Requests the Witnet oracle to generate an EVM-agnostic and trustless source of randomness.
/// @dev Only one randomness request per block will be actually posted to the Witnet Oracle.
/// @dev Unused funds will be transfered back to the `msg.sender`.
/// @return Funds actually paid as randomize fee.
function randomize() external payable returns (uint256);
/// @notice Returns address of the Witnet Oracle bridging contract being used for solving randomness requests.
function witnet() external view returns (WitnetOracle);
/// @notice Returns the SLA parameters required for the Witnet Oracle blockchain to fulfill
/// @notice when solving randomness requests:
/// @notice - number of witnessing nodes contributing to randomness generation
/// @notice - reward in $nanoWIT received per witnessing node in the Witnet blockchain
function witnetQuerySLA() external view returns (WitnetV2.RadonSLA memory);
/// @notice Returns the unique identifier of the Witnet-compliant data request being used for solving randomness.
function witnetRadHash() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import "../libs/WitnetV2.sol";
interface IWitnetOracleEvents {
/// Emitted every time a new query containing some verified data request is posted to the WRB.
event WitnetQuery(
uint256 id,
uint256 evmReward,
WitnetV2.RadonSLA witnetSLA
);
/// Emitted when a query with no callback gets reported into the WRB.
event WitnetQueryResponse(
uint256 id,
uint256 evmGasPrice
);
/// Emitted when a query with a callback gets successfully reported into the WRB.
event WitnetQueryResponseDelivered(
uint256 id,
uint256 evmGasPrice,
uint256 evmCallbackGas
);
/// Emitted when a query with a callback cannot get reported into the WRB.
event WitnetQueryResponseDeliveryFailed(
uint256 id,
bytes resultCborBytes,
uint256 evmGasPrice,
uint256 evmCallbackActualGas,
string evmCallbackRevertReason
);
/// Emitted when the reward of some not-yet reported query is upgraded.
event WitnetQueryRewardUpgraded(
uint256 id,
uint256 evmReward
);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import "../libs/WitnetV2.sol";
interface IWitnetOracle {
/// @notice Estimate the minimum reward required for posting a data request.
/// @dev Underestimates if the size of returned data is greater than `resultMaxSize`.
/// @param gasPrice Expected gas price to pay upon posting the data request.
/// @param resultMaxSize Maximum expected size of returned data (in bytes).
function estimateBaseFee(uint256 gasPrice, uint16 resultMaxSize) external view returns (uint256);
/// @notice Estimate the minimum reward required for posting a data request.
/// @dev Fails if the RAD hash was not previously verified on the WitnetRequestBytecodes registry.
/// @param gasPrice Expected gas price to pay upon posting the data request.
/// @param radHash The RAD hash of the data request to be solved by Witnet.
function estimateBaseFee(uint256 gasPrice, bytes32 radHash) external view returns (uint256);
/// @notice Estimate the minimum reward required for posting a data request with a callback.
/// @param gasPrice Expected gas price to pay upon posting the data request.
/// @param callbackGasLimit Maximum gas to be spent when reporting the data request result.
function estimateBaseFeeWithCallback(uint256 gasPrice, uint24 callbackGasLimit) external view returns (uint256);
/// @notice Retrieves a copy of all Witnet-provable data related to a previously posted request,
/// removing the whole query from the WRB storage.
/// @dev Fails if the query was not in 'Reported' status, or called from an address different to
/// @dev the one that actually posted the given request.
/// @param queryId The unique query identifier.
function fetchQueryResponse(uint256 queryId) external returns (WitnetV2.Response memory);
/// @notice Gets the whole Query data contents, if any, no matter its current status.
function getQuery(uint256 queryId) external view returns (WitnetV2.Query memory);
/// @notice Gets the current EVM reward the report can claim, if not done yet.
function getQueryEvmReward(uint256 queryId) external view returns (uint256);
/// @notice Retrieves the RAD hash and SLA parameters of the given query.
/// @param queryId The unique query identifier.
function getQueryRequest(uint256 queryId) external view returns (WitnetV2.Request memory);
/// @notice Retrieves the whole `Witnet.Response` record referred to a previously posted Witnet Data Request.
/// @param queryId The unique query identifier.
function getQueryResponse(uint256 queryId) external view returns (WitnetV2.Response memory);
/// @notice Returns query's result current status from a requester's point of view:
/// @notice - 0 => Void: the query is either non-existent or deleted;
/// @notice - 1 => Awaiting: the query has not yet been reported;
/// @notice - 2 => Ready: the query response was finalized, and contains a result with no erros.
/// @notice - 3 => Error: the query response was finalized, and contains a result with errors.
/// @param queryId The unique query identifier.
function getQueryResponseStatus(uint256 queryId) external view returns (WitnetV2.ResponseStatus);
/// @notice Retrieves the CBOR-encoded buffer containing the Witnet-provided result to the given query.
/// @param queryId The unique query identifier.
function getQueryResultCborBytes(uint256 queryId) external view returns (bytes memory);
/// @notice Gets error code identifying some possible failure on the resolution of the given query.
/// @param queryId The unique query identifier.
function getQueryResultError(uint256 queryId) external view returns (Witnet.ResultError memory);
/// @notice Gets current status of given query.
function getQueryStatus(uint256 queryId) external view returns (WitnetV2.QueryStatus);
/// @notice Get current status of all given query ids.
function getQueryStatusBatch(uint256[] calldata queryIds) external view returns (WitnetV2.QueryStatus[] memory);
/// @notice Returns next query id to be generated by the Witnet Request Board.
function getNextQueryId() external view returns (uint256);
/// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and
/// @notice solved by the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be
/// @notice transferred to the reporter who relays back the Witnet-provable result to this request.
/// @dev Reasons to fail:
/// @dev - the RAD hash was not previously verified by the WitnetRequestBytecodes registry;
/// @dev - invalid SLA parameters were provided;
/// @dev - insufficient value is paid as reward.
/// @param queryRAD The RAD hash of the data request to be solved by Witnet.
/// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain.
/// @return queryId Unique query identifier.
function postRequest(
bytes32 queryRAD,
WitnetV2.RadonSLA calldata querySLA
) external payable returns (uint256 queryId);
/// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and solved by
/// @notice the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be transferred to the
/// @notice reporter who relays back the Witnet-provable result to this request. The Witnet-provable result will be reported
/// @notice directly to the requesting contract. If the report callback fails for any reason, an `WitnetQueryResponseDeliveryFailed`
/// @notice will be triggered, and the Witnet audit trail will be saved in storage, but not so the actual CBOR-encoded result.
/// @dev Reasons to fail:
/// @dev - the caller is not a contract implementing the IWitnetConsumer interface;
/// @dev - the RAD hash was not previously verified by the WitnetRequestBytecodes registry;
/// @dev - invalid SLA parameters were provided;
/// @dev - insufficient value is paid as reward.
/// @param queryRAD The RAD hash of the data request to be solved by Witnet.
/// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain.
/// @param queryCallbackGasLimit Maximum gas to be spent when reporting the data request result.
/// @return queryId Unique query identifier.
function postRequestWithCallback(
bytes32 queryRAD,
WitnetV2.RadonSLA calldata querySLA,
uint24 queryCallbackGasLimit
) external payable returns (uint256 queryId);
/// @notice Requests the execution of the given Witnet Data Request, in expectation that it will be relayed and solved by
/// @notice the Witnet blockchain. A reward amount is escrowed by the Witnet Request Board that will be transferred to the
/// @notice reporter who relays back the Witnet-provable result to this request. The Witnet-provable result will be reported
/// @notice directly to the requesting contract. If the report callback fails for any reason, a `WitnetQueryResponseDeliveryFailed`
/// @notice event will be triggered, and the Witnet audit trail will be saved in storage, but not so the CBOR-encoded result.
/// @dev Reasons to fail:
/// @dev - the caller is not a contract implementing the IWitnetConsumer interface;
/// @dev - the provided bytecode is empty;
/// @dev - invalid SLA parameters were provided;
/// @dev - insufficient value is paid as reward.
/// @param queryUnverifiedBytecode The (unverified) bytecode containing the actual data request to be solved by the Witnet blockchain.
/// @param querySLA The data query SLA to be fulfilled on the Witnet blockchain.
/// @param queryCallbackGasLimit Maximum gas to be spent when reporting the data request result.
/// @return queryId Unique query identifier.
function postRequestWithCallback(
bytes calldata queryUnverifiedBytecode,
WitnetV2.RadonSLA calldata querySLA,
uint24 queryCallbackGasLimit
) external payable returns (uint256 queryId);
/// @notice Increments the reward of a previously posted request by adding the transaction value to it.
/// @param queryId The unique query identifier.
function upgradeQueryEvmReward(uint256 queryId) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../WitnetOracle.sol";
/// @title The UsingWitnet contract
/// @dev Witnet-aware contracts can inherit from this contract in order to interact with Witnet.
/// @author The Witnet Foundation.
abstract contract UsingWitnet
is
IWitnetOracleEvents
{
/// @dev Immutable reference to the Witnet Request Board contract.
WitnetOracle internal immutable __witnet;
/// @dev Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain
/// @dev when solving a data request.
WitnetV2.RadonSLA internal __witnetDefaultSLA;
/// @dev Percentage over base fee to pay on every data request,
/// @dev as to deal with volatility of evmGasPrice and evmWitPrice during the live time of
/// @dev a data request (since being posted until a result gets reported back), at both the EVM and
/// @dev the Witnet blockchain levels, respectivelly.
uint16 internal __witnetBaseFeeOverheadPercentage;
/// @param _wrb Address of the WitnetOracle contract.
constructor(WitnetOracle _wrb) {
require(
_wrb.specs() == type(IWitnetOracle).interfaceId,
"UsingWitnet: uncompliant WitnetOracle"
);
__witnet = _wrb;
__witnetDefaultSLA = WitnetV2.RadonSLA({
// Number of nodes in the Witnet blockchain that will take part in solving the data request:
committeeSize: 10,
// Fee in $nanoWIT paid to every node in the Witnet blockchain involved in solving the data request:
witnessingFeeNanoWit: 2 * 10 ** 8 // defaults to 0.2 $WIT
});
__witnetBaseFeeOverheadPercentage = 33; // defaults to 33%
}
/// @dev Provides a convenient way for client contracts extending this to block the execution of the main logic of the
/// @dev contract until a particular request has been successfully solved and reported by Witnet,
/// @dev either with an error or successfully.
modifier witnetQuerySolved(uint256 _witnetQueryId) {
require(_witnetCheckQueryResultAvailability(_witnetQueryId), "UsingWitnet: unsolved query");
_;
}
function witnet() virtual public view returns (WitnetOracle) {
return __witnet;
}
/// @notice Check if given query was already reported back from the Witnet oracle.
/// @param _id The unique identifier of a previously posted data request.
function _witnetCheckQueryResultAvailability(uint256 _id)
internal view
returns (bool)
{
return __witnet.getQueryStatus(_id) == WitnetV2.QueryStatus.Reported;
}
/// @notice Estimate the minimum reward required for posting a data request, using `tx.gasprice` as a reference.
/// @dev Underestimates if the size of returned data is greater than `_resultMaxSize`.
/// @param _resultMaxSize Maximum expected size of returned data (in bytes).
function _witnetEstimateEvmReward(uint16 _resultMaxSize)
virtual internal view
returns (uint256)
{
return (
(100 + __witnetBaseFeeOverheadPercentage)
* __witnet.estimateBaseFee(tx.gasprice, _resultMaxSize)
) / 100;
}
function _witnetCheckQueryResponseStatus(uint256 _witnetQueryId)
internal view
returns (WitnetV2.ResponseStatus)
{
return __witnet.getQueryResponseStatus(_witnetQueryId);
}
function _witnetCheckQueryResultError(uint256 _witnetQueryId)
internal view
returns (Witnet.ResultError memory)
{
return __witnet.getQueryResultError(_witnetQueryId);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./WitnetRequestBytecodes.sol";
import "./WitnetOracle.sol";
import "./interfaces/IWitnetRequestFactory.sol";
abstract contract WitnetRequestFactory
is
IWitnetRequestFactory
{
function class() virtual external view returns (string memory);
function registry() virtual external view returns (WitnetRequestBytecodes);
function specs() virtual external view returns (bytes4);
function witnet() virtual external view returns (WitnetOracle);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./interfaces/IWitnetRequestBytecodes.sol";
abstract contract WitnetRequestBytecodes
is
IWitnetRequestBytecodes
{
function class() virtual external view returns (string memory) {
return type(WitnetRequestBytecodes).name;
}
function specs() virtual external view returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import "./interfaces/IWitnetOracleEvents.sol";
import "./interfaces/IWitnetRandomness.sol";
import "./interfaces/IWitnetRandomnessEvents.sol";
abstract contract WitnetRandomness
is
IWitnetOracleEvents,
IWitnetRandomness,
IWitnetRandomnessEvents
{
function class() virtual external view returns (string memory);
function specs() virtual external view returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import "./WitnetRequestBytecodes.sol";
import "./WitnetRequestFactory.sol";
import "./interfaces/IWitnetOracle.sol";
import "./interfaces/IWitnetOracleEvents.sol";
/// @title Witnet Request Board functionality base contract.
/// @author The Witnet Foundation.
abstract contract WitnetOracle
is
IWitnetOracle,
IWitnetOracleEvents
{
function class() virtual external view returns (string memory) {
return type(WitnetOracle).name;
}
function channel() virtual external view returns (bytes4);
function factory() virtual external view returns (WitnetRequestFactory);
function registry() virtual external view returns (WitnetRequestBytecodes);
function specs() virtual external view returns (bytes4);
}// SPDX-License-Identifier: MIT
// 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);
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract WitnetOracle","name":"_witnet","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyBuffer","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"IndexOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"InvalidLengthEncoding","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":[{"internalType":"uint256","name":"read","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"UnexpectedMajorType","type":"error"},{"inputs":[{"internalType":"uint256","name":"unexpected","type":"uint256"}],"name":"UnsupportedMajorType","type":"error"},{"anonymous":false,"inputs":[{"indexed":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":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmTxGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmRandomizeFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"witnetQueryId","type":"uint256"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"indexed":false,"internalType":"struct WitnetV2.RadonSLA","name":"witnetQuerySLA","type":"tuple"}],"name":"Randomizing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"},{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"indexed":false,"internalType":"struct WitnetV2.RadonSLA","name":"witnetSLA","type":"tuple"}],"name":"WitnetQuery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"}],"name":"WitnetQueryResponse","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackGas","type":"uint256"}],"name":"WitnetQueryResponseDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"resultCborBytes","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"evmGasPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmCallbackActualGas","type":"uint256"},{"indexed":false,"internalType":"string","name":"evmCallbackRevertReason","type":"string"}],"name":"WitnetQueryResponseDeliveryFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"evmReward","type":"uint256"}],"name":"WitnetQueryRewardUpgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","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":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_evmGasPrice","type":"uint256"}],"name":"estimateRandomizeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"fetchRandomnessAfter","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"fetchRandomnessAfterProof","outputs":[{"internalType":"bytes32","name":"_witnetResultRandomness","type":"bytes32"},{"internalType":"uint64","name":"_witnetResultTimestamp","type":"uint64"},{"internalType":"bytes32","name":"_witnetResultTallyHash","type":"bytes32"},{"internalType":"uint256","name":"_witnetResultFinalityBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRandomizeBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getRandomizeData","outputs":[{"internalType":"uint256","name":"_witnetQueryId","type":"uint256"},{"internalType":"uint256","name":"_prevRandomizeBlock","type":"uint256"},{"internalType":"uint256","name":"_nextRandomizeBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getRandomizeNextBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getRandomizePrevBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getRandomizeStatus","outputs":[{"internalType":"enum WitnetV2.ResponseStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"isRandomized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"uint32","name":"_range","type":"uint32"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"random","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randomize","outputs":[{"internalType":"uint256","name":"_evmRandomizeFee","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_baseFeeOverheadPercentage","type":"uint16"}],"name":"settleBaseFeeOverheadPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"_witnetQuerySLA","type":"tuple"}],"name":"settleWitnetQuerySLA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"specs","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"witnet","outputs":[{"internalType":"contract WitnetOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witnetQuerySLA","outputs":[{"components":[{"internalType":"uint8","name":"committeeSize","type":"uint8"},{"internalType":"uint64","name":"witnessingFeeNanoWit","type":"uint64"}],"internalType":"struct WitnetV2.RadonSLA","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"witnetRadHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405234801561001057600080fd5b5060405161306838038061306883398101604081905261002f916106de565b81816001600160a01b03811661006057604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610069816105b3565b5063baeca88b60e01b6001600160e01b031916816001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100de9190610718565b6001600160e01b031916146101435760405162461bcd60e51b815260206004820152602560248201527f5573696e675769746e65743a20756e636f6d706c69616e74205769746e65744f6044820152647261636c6560d81b6064820152608401610057565b6001600160a01b0390811660805260408051808201909152600a8152630bebc20060209091015260028054640bebc2000a6001600160481b03199091161790556003805461ffff19166021179055610257908316158061021e575063baeca88b60e01b6001600160e01b031916836001600160a01b031663adb7c3f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102129190610718565b6001600160e01b031916145b60408051808201909152601881527f756e636f6d706c69616e74205769746e65744f7261636c65000000000000000060208201526105cf565b60006102616105e1565b6001600160a01b0316637b1039996040518163ffffffff1660e01b8152600401602060405180830381865afa15801561029e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c29190610749565b60408051600180825281830190925291925060009190602080830190803683375050604080516000808252602082019092529293506001600160a01b03851692639eb3ab1f925060029161032c565b6103196106a2565b8152602001906001900390816103115790505b506040518363ffffffff1660e01b815260040161034a9291906107e2565b6020604051808303816000875af1158015610369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038d91906108c5565b816000815181106103a0576103a06108de565b60200260200101818152505060606000836001600160a01b0316637f412e2360405180604001604052806002600b8111156103dd576103dd61077c565b8152602001858152506040518263ffffffff1660e01b815260040161040291906108f4565b6020604051808303816000875af1158015610421573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044591906108c5565b90506000846001600160a01b0316637f412e236040518060400160405280600b808111156104755761047561077c565b8152602001868152506040518263ffffffff1660e01b815260040161049a91906108f4565b6020604051808303816000875af11580156104b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104dd91906108c5565b9050846001600160a01b031663a4a7cecd858484602089516001600160401b0381111561050c5761050c610766565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b506040518663ffffffff1660e01b815260040161056095949392919061099b565b6020604051808303816000875af115801561057f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a391906108c5565b60a05250610ae095505050505050565b600180546001600160a01b03191690556105cc816105f1565b50565b816105dd576105dd81610641565b5050565b60006105ec60805190565b905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805180820190915260128152712bb4ba3732ba2930b73237b6b732b9b9ab1960711b60208201528160405160200161067c929190610a90565b60408051601f198184030181529082905262461bcd60e51b825261005791600401610acd565b60405180604001604052806002905b60608152602001906001900390816106b15790505090565b6001600160a01b03811681146105cc57600080fd5b600080604083850312156106f157600080fd5b82516106fc816106c9565b602084015190925061070d816106c9565b809150509250929050565b60006020828403121561072a57600080fd5b81516001600160e01b03198116811461074257600080fd5b9392505050565b60006020828403121561075b57600080fd5b8151610742816106c9565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60005b838110156107ad578181015183820152602001610795565b50506000910152565b600081518084526107ce816020860160208601610792565b601f01601f19169290920160200192915050565b6000600584106107f4576107f461077c565b838252602060a08184015260008060a0850152604060c06040860152600060c086015260e0850160e0606087015280875180835261010092508288019150828160051b890101925085890160005b8281101561089b5789850360ff19018452815185878101895b60028110156108865788820383526108748285516107b6565b938c0193928c0192915060010161085b565b50965050509287019290870190600101610842565b50505050858103608087015260018152600160ff1b60208201526040810198975050505050505050565b6000602082840312156108d757600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020808352606083018451600c81106109115761091161077c565b828501528482015160408086018190528151928390526080600584901b8701810193928501929087019060005b8181101561098d57888603607f1901835284518051600a81106109635761096361077c565b875287015187870185905261097a858801826107b6565b965050938601939186019160010161093e565b509398975050505050505050565b60a0808252865190820181905260009060209060c0840190828a01845b828110156109d4578151845292840192908401906001016109b8565b505050878285015286604085015261ffff86166060850152838103608085015280855180835283830191506005848260051b85010185890160005b84811015610a7d57601f198784038101875282518051808652908a01908a86019080881b87018c0160005b82811015610a665785898303018452610a548286516107b6565b948e0194938e01939150600101610a3a565b50998c019996505050928901925050600101610a0f565b50909d9c50505050505050505050505050565b60008351610aa2818460208801610792565b6101d160f51b9083019081528351610ac1816002840160208801610792565b01600201949350505050565b60208152600061074260208301846107b6565b60805160a05161252b610b3d600039600081816102d20152610a84015260008181610288015281816107dc0152818161088301528181610a5401528181610c7701528181610e2e015281816112550152611309015261252b6000f3fe60806040526004361061014f5760003560e01c80639bc86fec116100b6578063c0248bf11161006f578063c0248bf11461051f578063d2bc459b1461053f578063de0958ac1461055f578063e30c39781461057f578063eb92b29b14610594578063f2fde38b146105b75761018c565b80639bc86fec14610411578063a3252f6814610441578063a60ee2681461047c578063adb7c3f71461049c578063b8d38c96146104be578063bff852fa146104de5761018c565b806376fa9d201161010857806376fa9d201461031f57806379ba50971461034c57806382b1c174146103615780638da5cb5b146103815780638f2616841461039f5780639353badd146103b45761018c565b806317f45487146101f757806324cbbfc11461024457806346d1d21a14610279578063613e9978146102c0578063699b328a14610302578063715018a61461030a5761018c565b3661018c5761018a604051806040016040528060158152602001741b9bc81d1c985b9cd9995c9cc81858d8d95c1d1959605a1b8152506105d7565b005b61018a61019d60003560f81c610641565b6101ae60ff60003560f01c16610641565b6101bf60ff60003560e81c16610641565b6101d060ff60003560e01c16610641565b6040516020016101e39493929190611e0c565b6040516020818303038152906040526105d7565b34801561020357600080fd5b50610217610212366004611e8b565b610733565b604080519485526001600160401b0390931660208501529183015260608201526080015b60405180910390f35b34801561025057600080fd5b5061026461025f366004611eb6565b6109e6565b60405163ffffffff909116815260200161023b565b34801561028557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b03909116815260200161023b565b3480156102cc57600080fd5b506102f47f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161023b565b6102f4610a3b565b34801561031657600080fd5b5061018a610bec565b34801561032b57600080fd5b5061033f61033a366004611e8b565b610c00565b60405161023b9190611f01565b34801561035857600080fd5b5061018a610d53565b34801561036d57600080fd5b506102f461037c366004611e8b565b610d5b565b34801561038d57600080fd5b506000546001600160a01b03166102a8565b3480156103ab57600080fd5b506102f4610d96565b3480156103c057600080fd5b5060408051808201825260008082526020918201528151808301835260025460ff81168083526001600160401b0361010090920482169284019283528451908152915116918101919091520161023b565b34801561041d57600080fd5b5061043161042c366004611e8b565b610da6565b604051901515815260200161023b565b34801561044d57600080fd5b5061046161045c366004611e8b565b610dcb565b6040805193845260208401929092529082015260600161023b565b34801561048857600080fd5b506102f4610497366004611e8b565b610e03565b3480156104a857600080fd5b5060405163124f910d60e01b815260200161023b565b3480156104ca57600080fd5b5061018a6104d9366004611f29565b610ec9565b3480156104ea57600080fd5b5060408051808201825260128152712bb4ba3732ba2930b73237b6b732b9b9ab1960711b6020820152905161023b9190611f4d565b34801561052b57600080fd5b506102f461053a366004611e8b565b610ee9565b34801561054b57600080fd5b5061018a61055a366004611f80565b610f37565b34801561056b57600080fd5b506102f461057a366004611e8b565b610f86565b34801561058b57600080fd5b506102a8610fdf565b3480156105a057600080fd5b5060035460405161ffff909116815260200161023b565b3480156105c357600080fd5b5061018a6105d2366004611fa7565b610ff3565b6040805180820190915260128152712bb4ba3732ba2930b73237b6b732b9b9ab1960711b602082015281604051602001610612929190611fc4565b60408051601f198184030181529082905262461bcd60e51b825261063891600401611f4d565b60405180910390fd5b604080516002808252818301909252606091600091906020820181803683370190505090506000610673601085612043565b61067e906030612065565b9050600061068d60108661207e565b610698906030612065565b905060398260ff1611156106b4576106b1600783612065565b91505b60398160ff1611156106ce576106cb600782612065565b90505b8160f81b836000815181106106e5576106e56120a0565b60200101906001600160f81b031916908160001a9053508060f81b83600181518110610713576107136120a0565b60200101906001600160f81b031916908160001a90535091949350505050565b600080600080610741611007565b6000868152600191909101602052604081205490036107665761076385610f86565b94505b6000610770611007565b600101600087815260200190815260200160002090506000816000015490506107c381600014156040518060400160405280600e81526020016d1b9bdd081c985b991bdb5a5e995960921b81525061102b565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063234fe6e390602401602060405180830381865afa15801561082b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084f91906120b6565b9050600281600581111561086557610865611eeb565b0361093d57604051637b0c90d960e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f61921b290602401600060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108fa9190810190612191565b9050806040015163ffffffff1696508060600151955080602001516001600160401b03169450610935610930826080015161103d565b61105b565b9750506109db565b600381600581111561095157610951611eeb565b036109a957600283015460408051808201909152601081526f6661756c74792072616e646f6d697a6560801b602082015261098f908215159061102b565b61099881610733565b9750975097509750505050506109df565b6109db6040518060400160405280601181526020017070656e64696e672072616e646f6d697a6560781b8152506105d7565b5050505b9193509193565b6000610a2c8484336109f786610d5b565b604080516001600160a01b03909316602084015282015260600160405160208183030381529060405280519060200120611090565b90505b9392505050565b905090565b600043610a46611007565b541015610ba95734905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633dc2b7a2837f000000000000000000000000000000000000000000000000000000000000000060026040518463ffffffff1660e01b8152600401610ac2929190612240565b60206040518083038185885af1158015610ae0573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610b05919061226a565b90506000610b11611007565b436000908152600191909101602052604081208381559150610b31611007565b5460018301819055905043610b44611007565b6000838152600191909101602052604090206002015543610b63611007565b556040517f8cb766b09215126141c41df86fd488fe4745f22f3c995c3ad9aaf4c07195b94690610b9d9043903a9088908890600290612283565b60405180910390a15050505b34811015610be957336108fc610bbf83346122c3565b6040518115909202916000818181858888f19350505050158015610be7573d6000803e3d6000fd5b505b90565b610bf46110ef565b610bfe600061111c565b565b6000610c0a611007565b600083815260019190910160205260408120549003610c2f57610c2c82610f86565b91505b6000610c39611007565b600084815260019190910160205260408120549150819003610c5e5750600092915050565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063234fe6e390602401602060405180830381865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea91906120b6565b90506003816005811115610d0057610d00611eeb565b03610a2f576000610d0f611007565b6000868152600191909101602052604090206002015490508015610d3f57610d3681610c00565b95945050505050565b506003949350505050565b505b5050919050565b610bfe611135565b600081610d67836111b0565b604080516020810193909352820152606001604051602081830303815290604052805190602001209050919050565b6000610da0611007565b54919050565b60006002610db383610c00565b6005811115610dc457610dc4611eeb565b1492915050565b600080600080610dd9611007565b60009586526001908101602052604090952080549581015460029091015495969095945092505050565b604051630f7b104360e31b815260048101829052602260248201526000906064906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637bd8821890604401602060405180830381865afa158015610e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e99919061226a565b600354610eab9061ffff1660646122d6565b61ffff16610eb991906122f1565b610ec39190612308565b92915050565b610ed16110ef565b6003805461ffff191661ffff92909216919091179055565b6000808211610efa57610efa61231c565b6000610f04611007565b549050808311610ec357610f3283610f1a611007565b60008481526001918201602052604090200154611414565b610a2f565b610f3f6110ef565b610f74610f4b82611447565b6040518060400160405280600b81526020016a696e76616c696420534c4160a81b81525061102b565b806002610f818282612341565b505050565b6000610f90611007565b600083815260019190910160205260408120549003610fc057610fbb82610fb5611007565b546114d4565b610ec3565b610fc8611007565b600092835260010160205250604090206002015490565b6000610a366001546001600160a01b031690565b610ffb6110ef565b61100481611523565b50565b7f643778935c57df947f6944f6a5242a3e91445f6337f4b2ec670c8642153b614f90565b8161103957611039816105d7565b5050565b611045611d80565b600061105083611555565b9050610a2f8161157a565b600081806000015161107f5760405162461bcd60e51b815260040161063890612393565b610a2f61108b846115ae565b6115df565b6000806001600160e01b0383856040516020016110b7929190918252602082015260400190565b60408051601f19818403018152919052805160209091012016905060e06110e463ffffffff8716836122f1565b901c95945050505050565b6000546001600160a01b03163314610bfe5760405163118cdaa760e01b8152336004820152602401610638565b600180546001600160a01b0319169055611004816115ec565b338061113f610fdf565b6001600160a01b0316146111a75760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610638565b6110048161111c565b60006111ba611007565b6000838152600191909101602052604081205490036111df576111dc82610f86565b91505b60006111e9611007565b6001016000848152602001908152602001600020905060008160000154905061123c81600014156040518060400160405280600e81526020016d1b9bdd081c985b991bdb5a5e995960921b81525061102b565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063234fe6e390602401602060405180830381865afa1580156112a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c891906120b6565b905060028160058111156112de576112de611eeb565b0361137d576040516311a7b16760e31b815260048101839052610d3690610930906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638d3d8b3890602401600060405180830381865afa158015611350573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261137891908101906123e5565b61103d565b600381600581111561139157611391611eeb565b036113e257600283015460408051808201909152601081526f6661756c74792072616e646f6d697a6560801b60208201526113cf908215159061102b565b6113d8816111b0565b9695505050505050565b610d4a6040518060400160405280601181526020017070656e64696e672072616e646f6d697a6560781b8152506105d7565b600081831161144157610f3283611429611007565b60008581526001918201602052604090200154611414565b50919050565b60008061145a6040840160208501612421565b6001600160401b031611801561147f5750600061147a602084018461243e565b60ff16115b801561149b5750607f611495602084018461243e565b60ff1611155b8015610ec357506404a817c8006114b86040840160208501612421565b6114c390606461245b565b6001600160401b0316101592915050565b60008183101561150257610f32836114ea611007565b600085815260019182016020526040902001546114d4565b61150a611007565b6000928352600101602052506040902060020154919050565b61152b6110ef565b6001600160a01b0381166111a757604051631e4fbdf760e01b815260006004820152602401610638565b61155d611da1565b6040805180820190915282815260006020820152610a2f8161163c565b611582611d80565b5060a0810151604080518082019091526001600160401b03909116602714158152602081019190915290565b60608180600001516115d25760405162461bcd60e51b815260040161063890612393565b610a2f836020015161175c565b6000610ec38260206118a5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611644611da1565b8151518290600003611669576040516309036d4760e21b815260040160405180910390fd5b600060ff816001600160401b038160015b80156116ec576116898961191d565b9550816116958161247e565b6007600589901c169650601f8816955092505060051985016116e45760208901516116c08a8661197f565b9350808a602001516116d291906122c3565b6116dc9084612497565b92505061167a565b50600061167a565b600760ff861611156117165760405163bd2ac87960e01b815260ff86166004820152602401610638565b506040805160c08101825298895260ff95861660208a015293851693880193909352921660608601526001600160401b0390811660808601521660a08401525090919050565b60608160028060ff16826040015160ff161461179c57604080830151905161800560e51b815260ff91821660048201529082166024820152604401610638565b6117ae8460000151856060015161197f565b6001600160401b03166080850181905263fffffffe19016118845760006117dd85600001518660400151611a47565b905063ffffffff8082161015610d4a5784516118029063ffffffff80841690611af416565b60405160200161181291906124aa565b604051602081830303815290604052935061183585600001518660400151611a47565b905063ffffffff8082161015610d4a578451849061185c9063ffffffff80851690611af416565b60405160200161186d9291906124c6565b604051602081830303815290604052935050610d4c565b6080840151845161189e9163ffffffff90811690611af416565b9250610d4c565b600060208260ff1611156118bb576118bb61231c565b60008260ff168451116118cf5783516118d4565b8260ff165b905060005b8181101561191557806008028582815181106118f7576118f76120a0565b01602001516001600160f81b031916901c92909217916001016118d9565b505092915050565b6000816020015182600001515180821115611955576040516363a056dd60e01b81526004810183905260248101829052604401610638565b83516020850180518083016001015195509081906119728261247e565b8152505050505050919050565b600060188260ff161015611997575060ff8116610ec3565b8160ff166018036119b5576119ab8361191d565b60ff169050610ec3565b8160ff166019036119d4576119c983611bb4565b61ffff169050610ec3565b8160ff16601a036119f5576119e883611c20565b63ffffffff169050610ec3565b8160ff16601b03611a1057611a0983611c7f565b9050610ec3565b8160ff16601f03611a2957506001600160401b03610ec3565b604051636d785b1360e01b815260ff83166004820152602401610638565b600080611a538461191d565b90508060ff1660ff03611a70576001600160401b03915050610ec3565b611a7d8482601f1661197f565b91506001600160401b0380831610611ab357604051636d785b1360e01b81526001600160401b0383166004820152602401610638565b60ff83166007600583901c1614611aed5760405161800560e51b81526007600583901c16600482015260ff84166024820152604401610638565b5092915050565b6060818360200151611b069190612497565b83515180821115611b34576040516363a056dd60e01b81526004810183905260248101829052604401610638565b836001600160401b03811115611b4c57611b4c612001565b6040519080825280601f01601f191660200182016040528015611b76576020820181803683370190505b5092508315611915578451602080870151908183018101908601611b9b81838a611cde565b611ba789896001611d24565b5050505050505092915050565b600081602001516002611bc79190612497565b82515180821115611bf5576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600281840181015196509091611c138284612497565b9052509395945050505050565b600081602001516004611c339190612497565b82515180821115611c61576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600481840181015196509091611c138284612497565b600081602001516008611c929190612497565b82515180821115611cc0576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600881840181015196509091611c138284612497565b5b60208110611cfe578151835260209283019290910190601f1901611cdf565b8015610f81578151835160208390036101000a6000190180199092169116178352505050565b60008284600001515180821115611d58576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8315611d70576020860151611d6d9086612497565b94505b5050505060209190910181905290565b6040518060400160405280600015158152602001611d9c611da1565b905290565b604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b60005b83811015611e03578181015183820152602001611deb565b50506000910152565b720dcdee840d2dae0d8cadacadce8cac8744060f606b1b815260008551611e3a816013850160208a01611de8565b855190830190611e51816013840160208a01611de8565b8551910190611e67816013840160208901611de8565b8451910190611e7d816013840160208801611de8565b016013019695505050505050565b600060208284031215611e9d57600080fd5b5035919050565b63ffffffff8116811461100457600080fd5b600080600060608486031215611ecb57600080fd5b8335611ed681611ea4565b95602085013595506040909401359392505050565b634e487b7160e01b600052602160045260246000fd5b6020810160068310611f2357634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215611f3b57600080fd5b813561ffff81168114610a2f57600080fd5b6020815260008251806020840152611f6c816040850160208701611de8565b601f01601f19169190910160400192915050565b60006040828403121561144157600080fd5b6001600160a01b038116811461100457600080fd5b600060208284031215611fb957600080fd5b8135610a2f81611f92565b60008351611fd6818460208801611de8565b6101d160f51b9083019081528351611ff5816002840160208801611de8565b01600201949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff83168061205657612056612017565b8060ff84160491505092915050565b60ff8181168382160190811115610ec357610ec361202d565b600060ff83168061209157612091612017565b8060ff84160691505092915050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156120c857600080fd5b815160068110610a2f57600080fd5b60405160a081016001600160401b03811182821017156120f9576120f9612001565b60405290565b6001600160401b038116811461100457600080fd5b600082601f83011261212557600080fd5b81516001600160401b038082111561213f5761213f612001565b604051601f8301601f19908116603f0116810190828211818310171561216757612167612001565b8160405283815286602085880101111561218057600080fd5b6113d8846020830160208901611de8565b6000602082840312156121a357600080fd5b81516001600160401b03808211156121ba57600080fd5b9083019060a082860312156121ce57600080fd5b6121d66120d7565b82516121e181611f92565b815260208301516121f1816120ff565b6020820152604083015161220481611ea4565b60408201526060838101519082015260808301518281111561222557600080fd5b61223187828601612114565b60808301525095945050505050565b82815260608101610a2f60208301845460ff8116825260081c6001600160401b0316602090910152565b60006020828403121561227c57600080fd5b5051919050565b600060c0820190508682528560208301528460408301528360608301526113d860808301845460ff8116825260081c6001600160401b0316602090910152565b81810381811115610ec357610ec361202d565b61ffff818116838216019080821115611aed57611aed61202d565b8082028115828204841417610ec357610ec361202d565b60008261231757612317612017565b500490565b634e487b7160e01b600052600160045260246000fd5b60ff8116811461100457600080fd5b813561234c81612332565b60ff8116905081548160ff198216178355602084013561236b816120ff565b68ffffffffffffffff008160081b168368ffffffffffffffffff198416171784555050505050565b60208082526032908201527f5769746e65743a20747269656420746f206465636f64652076616c756520667260408201527137b69032b93937b932b2103932b9bab63a1760711b606082015260800190565b6000602082840312156123f757600080fd5b81516001600160401b0381111561240d57600080fd5b61241984828501612114565b949350505050565b60006020828403121561243357600080fd5b8135610a2f816120ff565b60006020828403121561245057600080fd5b8135610a2f81612332565b6001600160401b038181168382160280821691908281146119155761191561202d565b6000600182016124905761249061202d565b5060010190565b80820180821115610ec357610ec361202d565b600082516124bc818460208701611de8565b9190910192915050565b600083516124d8818460208801611de8565b8351908301906124ec818360208801611de8565b0194935050505056fea2646970667358221220a7d132818b11585f7a3bfec2ecaa814d67803886db4209237c7caf9aaacd671564736f6c6343000819003300000000000000000000000077703ae126b971c9946d562f41dd47071da00777000000000000000000000000f121b71715e71dded592f1125a06d4ed06f0694d
Deployed Bytecode
0x60806040526004361061014f5760003560e01c80639bc86fec116100b6578063c0248bf11161006f578063c0248bf11461051f578063d2bc459b1461053f578063de0958ac1461055f578063e30c39781461057f578063eb92b29b14610594578063f2fde38b146105b75761018c565b80639bc86fec14610411578063a3252f6814610441578063a60ee2681461047c578063adb7c3f71461049c578063b8d38c96146104be578063bff852fa146104de5761018c565b806376fa9d201161010857806376fa9d201461031f57806379ba50971461034c57806382b1c174146103615780638da5cb5b146103815780638f2616841461039f5780639353badd146103b45761018c565b806317f45487146101f757806324cbbfc11461024457806346d1d21a14610279578063613e9978146102c0578063699b328a14610302578063715018a61461030a5761018c565b3661018c5761018a604051806040016040528060158152602001741b9bc81d1c985b9cd9995c9cc81858d8d95c1d1959605a1b8152506105d7565b005b61018a61019d60003560f81c610641565b6101ae60ff60003560f01c16610641565b6101bf60ff60003560e81c16610641565b6101d060ff60003560e01c16610641565b6040516020016101e39493929190611e0c565b6040516020818303038152906040526105d7565b34801561020357600080fd5b50610217610212366004611e8b565b610733565b604080519485526001600160401b0390931660208501529183015260608201526080015b60405180910390f35b34801561025057600080fd5b5061026461025f366004611eb6565b6109e6565b60405163ffffffff909116815260200161023b565b34801561028557600080fd5b507f00000000000000000000000077703ae126b971c9946d562f41dd47071da007775b6040516001600160a01b03909116815260200161023b565b3480156102cc57600080fd5b506102f47fa99a7820caf2ba70380e667614b4db0445c2176c012b458c9c6be28bf6d09c8581565b60405190815260200161023b565b6102f4610a3b565b34801561031657600080fd5b5061018a610bec565b34801561032b57600080fd5b5061033f61033a366004611e8b565b610c00565b60405161023b9190611f01565b34801561035857600080fd5b5061018a610d53565b34801561036d57600080fd5b506102f461037c366004611e8b565b610d5b565b34801561038d57600080fd5b506000546001600160a01b03166102a8565b3480156103ab57600080fd5b506102f4610d96565b3480156103c057600080fd5b5060408051808201825260008082526020918201528151808301835260025460ff81168083526001600160401b0361010090920482169284019283528451908152915116918101919091520161023b565b34801561041d57600080fd5b5061043161042c366004611e8b565b610da6565b604051901515815260200161023b565b34801561044d57600080fd5b5061046161045c366004611e8b565b610dcb565b6040805193845260208401929092529082015260600161023b565b34801561048857600080fd5b506102f4610497366004611e8b565b610e03565b3480156104a857600080fd5b5060405163124f910d60e01b815260200161023b565b3480156104ca57600080fd5b5061018a6104d9366004611f29565b610ec9565b3480156104ea57600080fd5b5060408051808201825260128152712bb4ba3732ba2930b73237b6b732b9b9ab1960711b6020820152905161023b9190611f4d565b34801561052b57600080fd5b506102f461053a366004611e8b565b610ee9565b34801561054b57600080fd5b5061018a61055a366004611f80565b610f37565b34801561056b57600080fd5b506102f461057a366004611e8b565b610f86565b34801561058b57600080fd5b506102a8610fdf565b3480156105a057600080fd5b5060035460405161ffff909116815260200161023b565b3480156105c357600080fd5b5061018a6105d2366004611fa7565b610ff3565b6040805180820190915260128152712bb4ba3732ba2930b73237b6b732b9b9ab1960711b602082015281604051602001610612929190611fc4565b60408051601f198184030181529082905262461bcd60e51b825261063891600401611f4d565b60405180910390fd5b604080516002808252818301909252606091600091906020820181803683370190505090506000610673601085612043565b61067e906030612065565b9050600061068d60108661207e565b610698906030612065565b905060398260ff1611156106b4576106b1600783612065565b91505b60398160ff1611156106ce576106cb600782612065565b90505b8160f81b836000815181106106e5576106e56120a0565b60200101906001600160f81b031916908160001a9053508060f81b83600181518110610713576107136120a0565b60200101906001600160f81b031916908160001a90535091949350505050565b600080600080610741611007565b6000868152600191909101602052604081205490036107665761076385610f86565b94505b6000610770611007565b600101600087815260200190815260200160002090506000816000015490506107c381600014156040518060400160405280600e81526020016d1b9bdd081c985b991bdb5a5e995960921b81525061102b565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063234fe6e390602401602060405180830381865afa15801561082b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084f91906120b6565b9050600281600581111561086557610865611eeb565b0361093d57604051637b0c90d960e11b8152600481018390526000907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063f61921b290602401600060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108fa9190810190612191565b9050806040015163ffffffff1696508060600151955080602001516001600160401b03169450610935610930826080015161103d565b61105b565b9750506109db565b600381600581111561095157610951611eeb565b036109a957600283015460408051808201909152601081526f6661756c74792072616e646f6d697a6560801b602082015261098f908215159061102b565b61099881610733565b9750975097509750505050506109df565b6109db6040518060400160405280601181526020017070656e64696e672072616e646f6d697a6560781b8152506105d7565b5050505b9193509193565b6000610a2c8484336109f786610d5b565b604080516001600160a01b03909316602084015282015260600160405160208183030381529060405280519060200120611090565b90505b9392505050565b905090565b600043610a46611007565b541015610ba95734905060007f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b0316633dc2b7a2837fa99a7820caf2ba70380e667614b4db0445c2176c012b458c9c6be28bf6d09c8560026040518463ffffffff1660e01b8152600401610ac2929190612240565b60206040518083038185885af1158015610ae0573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610b05919061226a565b90506000610b11611007565b436000908152600191909101602052604081208381559150610b31611007565b5460018301819055905043610b44611007565b6000838152600191909101602052604090206002015543610b63611007565b556040517f8cb766b09215126141c41df86fd488fe4745f22f3c995c3ad9aaf4c07195b94690610b9d9043903a9088908890600290612283565b60405180910390a15050505b34811015610be957336108fc610bbf83346122c3565b6040518115909202916000818181858888f19350505050158015610be7573d6000803e3d6000fd5b505b90565b610bf46110ef565b610bfe600061111c565b565b6000610c0a611007565b600083815260019190910160205260408120549003610c2f57610c2c82610f86565b91505b6000610c39611007565b600084815260019190910160205260408120549150819003610c5e5750600092915050565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063234fe6e390602401602060405180830381865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cea91906120b6565b90506003816005811115610d0057610d00611eeb565b03610a2f576000610d0f611007565b6000868152600191909101602052604090206002015490508015610d3f57610d3681610c00565b95945050505050565b506003949350505050565b505b5050919050565b610bfe611135565b600081610d67836111b0565b604080516020810193909352820152606001604051602081830303815290604052805190602001209050919050565b6000610da0611007565b54919050565b60006002610db383610c00565b6005811115610dc457610dc4611eeb565b1492915050565b600080600080610dd9611007565b60009586526001908101602052604090952080549581015460029091015495969095945092505050565b604051630f7b104360e31b815260048101829052602260248201526000906064906001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771690637bd8821890604401602060405180830381865afa158015610e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e99919061226a565b600354610eab9061ffff1660646122d6565b61ffff16610eb991906122f1565b610ec39190612308565b92915050565b610ed16110ef565b6003805461ffff191661ffff92909216919091179055565b6000808211610efa57610efa61231c565b6000610f04611007565b549050808311610ec357610f3283610f1a611007565b60008481526001918201602052604090200154611414565b610a2f565b610f3f6110ef565b610f74610f4b82611447565b6040518060400160405280600b81526020016a696e76616c696420534c4160a81b81525061102b565b806002610f818282612341565b505050565b6000610f90611007565b600083815260019190910160205260408120549003610fc057610fbb82610fb5611007565b546114d4565b610ec3565b610fc8611007565b600092835260010160205250604090206002015490565b6000610a366001546001600160a01b031690565b610ffb6110ef565b61100481611523565b50565b7f643778935c57df947f6944f6a5242a3e91445f6337f4b2ec670c8642153b614f90565b8161103957611039816105d7565b5050565b611045611d80565b600061105083611555565b9050610a2f8161157a565b600081806000015161107f5760405162461bcd60e51b815260040161063890612393565b610a2f61108b846115ae565b6115df565b6000806001600160e01b0383856040516020016110b7929190918252602082015260400190565b60408051601f19818403018152919052805160209091012016905060e06110e463ffffffff8716836122f1565b901c95945050505050565b6000546001600160a01b03163314610bfe5760405163118cdaa760e01b8152336004820152602401610638565b600180546001600160a01b0319169055611004816115ec565b338061113f610fdf565b6001600160a01b0316146111a75760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610638565b6110048161111c565b60006111ba611007565b6000838152600191909101602052604081205490036111df576111dc82610f86565b91505b60006111e9611007565b6001016000848152602001908152602001600020905060008160000154905061123c81600014156040518060400160405280600e81526020016d1b9bdd081c985b991bdb5a5e995960921b81525061102b565b60405163234fe6e360e01b8152600481018290526000907f00000000000000000000000077703ae126b971c9946d562f41dd47071da007776001600160a01b03169063234fe6e390602401602060405180830381865afa1580156112a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c891906120b6565b905060028160058111156112de576112de611eeb565b0361137d576040516311a7b16760e31b815260048101839052610d3690610930906001600160a01b037f00000000000000000000000077703ae126b971c9946d562f41dd47071da007771690638d3d8b3890602401600060405180830381865afa158015611350573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261137891908101906123e5565b61103d565b600381600581111561139157611391611eeb565b036113e257600283015460408051808201909152601081526f6661756c74792072616e646f6d697a6560801b60208201526113cf908215159061102b565b6113d8816111b0565b9695505050505050565b610d4a6040518060400160405280601181526020017070656e64696e672072616e646f6d697a6560781b8152506105d7565b600081831161144157610f3283611429611007565b60008581526001918201602052604090200154611414565b50919050565b60008061145a6040840160208501612421565b6001600160401b031611801561147f5750600061147a602084018461243e565b60ff16115b801561149b5750607f611495602084018461243e565b60ff1611155b8015610ec357506404a817c8006114b86040840160208501612421565b6114c390606461245b565b6001600160401b0316101592915050565b60008183101561150257610f32836114ea611007565b600085815260019182016020526040902001546114d4565b61150a611007565b6000928352600101602052506040902060020154919050565b61152b6110ef565b6001600160a01b0381166111a757604051631e4fbdf760e01b815260006004820152602401610638565b61155d611da1565b6040805180820190915282815260006020820152610a2f8161163c565b611582611d80565b5060a0810151604080518082019091526001600160401b03909116602714158152602081019190915290565b60608180600001516115d25760405162461bcd60e51b815260040161063890612393565b610a2f836020015161175c565b6000610ec38260206118a5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611644611da1565b8151518290600003611669576040516309036d4760e21b815260040160405180910390fd5b600060ff816001600160401b038160015b80156116ec576116898961191d565b9550816116958161247e565b6007600589901c169650601f8816955092505060051985016116e45760208901516116c08a8661197f565b9350808a602001516116d291906122c3565b6116dc9084612497565b92505061167a565b50600061167a565b600760ff861611156117165760405163bd2ac87960e01b815260ff86166004820152602401610638565b506040805160c08101825298895260ff95861660208a015293851693880193909352921660608601526001600160401b0390811660808601521660a08401525090919050565b60608160028060ff16826040015160ff161461179c57604080830151905161800560e51b815260ff91821660048201529082166024820152604401610638565b6117ae8460000151856060015161197f565b6001600160401b03166080850181905263fffffffe19016118845760006117dd85600001518660400151611a47565b905063ffffffff8082161015610d4a5784516118029063ffffffff80841690611af416565b60405160200161181291906124aa565b604051602081830303815290604052935061183585600001518660400151611a47565b905063ffffffff8082161015610d4a578451849061185c9063ffffffff80851690611af416565b60405160200161186d9291906124c6565b604051602081830303815290604052935050610d4c565b6080840151845161189e9163ffffffff90811690611af416565b9250610d4c565b600060208260ff1611156118bb576118bb61231c565b60008260ff168451116118cf5783516118d4565b8260ff165b905060005b8181101561191557806008028582815181106118f7576118f76120a0565b01602001516001600160f81b031916901c92909217916001016118d9565b505092915050565b6000816020015182600001515180821115611955576040516363a056dd60e01b81526004810183905260248101829052604401610638565b83516020850180518083016001015195509081906119728261247e565b8152505050505050919050565b600060188260ff161015611997575060ff8116610ec3565b8160ff166018036119b5576119ab8361191d565b60ff169050610ec3565b8160ff166019036119d4576119c983611bb4565b61ffff169050610ec3565b8160ff16601a036119f5576119e883611c20565b63ffffffff169050610ec3565b8160ff16601b03611a1057611a0983611c7f565b9050610ec3565b8160ff16601f03611a2957506001600160401b03610ec3565b604051636d785b1360e01b815260ff83166004820152602401610638565b600080611a538461191d565b90508060ff1660ff03611a70576001600160401b03915050610ec3565b611a7d8482601f1661197f565b91506001600160401b0380831610611ab357604051636d785b1360e01b81526001600160401b0383166004820152602401610638565b60ff83166007600583901c1614611aed5760405161800560e51b81526007600583901c16600482015260ff84166024820152604401610638565b5092915050565b6060818360200151611b069190612497565b83515180821115611b34576040516363a056dd60e01b81526004810183905260248101829052604401610638565b836001600160401b03811115611b4c57611b4c612001565b6040519080825280601f01601f191660200182016040528015611b76576020820181803683370190505b5092508315611915578451602080870151908183018101908601611b9b81838a611cde565b611ba789896001611d24565b5050505050505092915050565b600081602001516002611bc79190612497565b82515180821115611bf5576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600281840181015196509091611c138284612497565b9052509395945050505050565b600081602001516004611c339190612497565b82515180821115611c61576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600481840181015196509091611c138284612497565b600081602001516008611c929190612497565b82515180821115611cc0576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8351602085018051600881840181015196509091611c138284612497565b5b60208110611cfe578151835260209283019290910190601f1901611cdf565b8015610f81578151835160208390036101000a6000190180199092169116178352505050565b60008284600001515180821115611d58576040516363a056dd60e01b81526004810183905260248101829052604401610638565b8315611d70576020860151611d6d9086612497565b94505b5050505060209190910181905290565b6040518060400160405280600015158152602001611d9c611da1565b905290565b604080516101008101909152606060c08201908152600060e08301528190815260006020820181905260408201819052606082018190526080820181905260a09091015290565b60005b83811015611e03578181015183820152602001611deb565b50506000910152565b720dcdee840d2dae0d8cadacadce8cac8744060f606b1b815260008551611e3a816013850160208a01611de8565b855190830190611e51816013840160208a01611de8565b8551910190611e67816013840160208901611de8565b8451910190611e7d816013840160208801611de8565b016013019695505050505050565b600060208284031215611e9d57600080fd5b5035919050565b63ffffffff8116811461100457600080fd5b600080600060608486031215611ecb57600080fd5b8335611ed681611ea4565b95602085013595506040909401359392505050565b634e487b7160e01b600052602160045260246000fd5b6020810160068310611f2357634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215611f3b57600080fd5b813561ffff81168114610a2f57600080fd5b6020815260008251806020840152611f6c816040850160208701611de8565b601f01601f19169190910160400192915050565b60006040828403121561144157600080fd5b6001600160a01b038116811461100457600080fd5b600060208284031215611fb957600080fd5b8135610a2f81611f92565b60008351611fd6818460208801611de8565b6101d160f51b9083019081528351611ff5816002840160208801611de8565b01600201949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff83168061205657612056612017565b8060ff84160491505092915050565b60ff8181168382160190811115610ec357610ec361202d565b600060ff83168061209157612091612017565b8060ff84160691505092915050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156120c857600080fd5b815160068110610a2f57600080fd5b60405160a081016001600160401b03811182821017156120f9576120f9612001565b60405290565b6001600160401b038116811461100457600080fd5b600082601f83011261212557600080fd5b81516001600160401b038082111561213f5761213f612001565b604051601f8301601f19908116603f0116810190828211818310171561216757612167612001565b8160405283815286602085880101111561218057600080fd5b6113d8846020830160208901611de8565b6000602082840312156121a357600080fd5b81516001600160401b03808211156121ba57600080fd5b9083019060a082860312156121ce57600080fd5b6121d66120d7565b82516121e181611f92565b815260208301516121f1816120ff565b6020820152604083015161220481611ea4565b60408201526060838101519082015260808301518281111561222557600080fd5b61223187828601612114565b60808301525095945050505050565b82815260608101610a2f60208301845460ff8116825260081c6001600160401b0316602090910152565b60006020828403121561227c57600080fd5b5051919050565b600060c0820190508682528560208301528460408301528360608301526113d860808301845460ff8116825260081c6001600160401b0316602090910152565b81810381811115610ec357610ec361202d565b61ffff818116838216019080821115611aed57611aed61202d565b8082028115828204841417610ec357610ec361202d565b60008261231757612317612017565b500490565b634e487b7160e01b600052600160045260246000fd5b60ff8116811461100457600080fd5b813561234c81612332565b60ff8116905081548160ff198216178355602084013561236b816120ff565b68ffffffffffffffff008160081b168368ffffffffffffffffff198416171784555050505050565b60208082526032908201527f5769746e65743a20747269656420746f206465636f64652076616c756520667260408201527137b69032b93937b932b2103932b9bab63a1760711b606082015260800190565b6000602082840312156123f757600080fd5b81516001600160401b0381111561240d57600080fd5b61241984828501612114565b949350505050565b60006020828403121561243357600080fd5b8135610a2f816120ff565b60006020828403121561245057600080fd5b8135610a2f81612332565b6001600160401b038181168382160280821691908281146119155761191561202d565b6000600182016124905761249061202d565b5060010190565b80820180821115610ec357610ec361202d565b600082516124bc818460208701611de8565b9190910192915050565b600083516124d8818460208801611de8565b8351908301906124ec818360208801611de8565b0194935050505056fea2646970667358221220a7d132818b11585f7a3bfec2ecaa814d67803886db4209237c7caf9aaacd671564736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000077703ae126b971c9946d562f41dd47071da00777000000000000000000000000f121b71715e71dded592f1125a06d4ed06f0694d
-----Decoded View---------------
Arg [0] : _witnet (address): 0x77703aE126B971c9946d562F41Dd47071dA00777
Arg [1] : _operator (address): 0xF121b71715E71DDeD592F1125a06D4ED06F0694D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000077703ae126b971c9946d562f41dd47071da00777
Arg [1] : 000000000000000000000000f121b71715e71dded592f1125a06d4ed06f0694d
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.