diff --git a/.solhint.json b/.solhint.json index 7e8130457..0ad4ce74e 100644 --- a/.solhint.json +++ b/.solhint.json @@ -16,6 +16,7 @@ "modifier-name-mixedcase": "warn", "no-empty-blocks": "off", "no-inline-assembly": "off", + "no-global-import": "off", "var-name-mixedcase": "off", "reason-string": [ "warn", diff --git a/contracts/UsingWitnet.sol b/contracts/UsingWitnet.sol deleted file mode 100644 index de2ff6ceb..000000000 --- a/contracts/UsingWitnet.sol +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "./WitnetRequestBoard.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 { - - WitnetRequestBoard private immutable __witnet; - - /// @dev Include an address to specify the WitnetRequestBoard entry point address. - /// @param _wrb The WitnetRequestBoard entry point address. - constructor(WitnetRequestBoard _wrb) - { - require(address(_wrb) != address(0), "UsingWitnet: no WRB"); - __witnet = _wrb; - } - - /// @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 _id) { - require(_witnetCheckResultAvailability(_id), "UsingWitnet: unsolved query"); - _; - } - - function witnet() virtual public view returns (WitnetRequestBoard) { - 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 _witnetCheckResultAvailability(uint256 _id) - internal view - returns (bool) - { - return __witnet.getQueryStatus(_id) == Witnet.QueryStatus.Reported; - } - - /// @notice Estimate the reward amount. - /// @param _gasPrice The gas price for which we want to retrieve the estimation. - /// @return The reward to be included when either posting a new request, or upgrading the reward of a previously posted one. - function _witnetEstimateReward(uint256 _gasPrice) - internal view - returns (uint256) - { - return __witnet.estimateReward(_gasPrice); - } - - /// @notice Estimates the reward amount, considering current transaction gas price. - /// @return The reward to be included when either posting a new request, or upgrading the reward of a previously posted one. - function _witnetEstimateReward() - internal view - returns (uint256) - { - return __witnet.estimateReward(tx.gasprice); - } - - /// @notice Post some data request to be eventually solved by the Witnet decentralized oracle network. - /// @notice The EVM -> Witnet bridge will read the Witnet Data Request bytecode from the WitnetBytecodes - /// @notice registry based on given `_radHash` and `_slaHash` values. - /// @dev Enough ETH needs to be provided as to cover for the implicit fee. - /// @param _radHash Unique hash of some pre-validated Witnet Radon Request. - /// @param _slaHash Unique hash of some pre-validated Witnet Radon Service-Level Agreement. - /// @return _id The unique identifier of the just posted data request. - /// @return _reward Current reward amount escrowed by the WRB until a result gets reported. - function _witnetPostRequest(bytes32 _radHash, bytes32 _slaHash) - virtual internal - returns (uint256 _id, uint256 _reward) - { - _reward = _witnetEstimateReward(); - require( - _reward <= msg.value, - "UsingWitnet: reward too low" - ); - _id = __witnet.postRequest{value: _reward}(_radHash, _slaHash); - } - - /// @notice Post some data request to be eventually solved by the Witnet decentralized oracle network. - /// @notice The EVM -> Witnet bridge will read the Witnet Data Request bytecode from the WitnetBytecodes - /// @notice registry based on given `_radHash` and `_slaHash` values. - /// @dev Enough ETH needs to be provided as to cover for the implicit fee. - /// @param _radHash Unique hash of some pre-validated Witnet Radon Request. - /// @param _slaParams The SLA params upon which this data request will be solved by Witnet. - /// @return _id The unique identifier of the just posted data request. - /// @return _reward Current reward amount escrowed by the WRB until a result gets reported. - function _witnetPostRequest(bytes32 _radHash, WitnetV2.RadonSLA memory _slaParams) - virtual internal - returns (uint256 _id, uint256 _reward) - { - return _witnetPostRequest(_radHash, __witnet.registry().verifyRadonSLA(_slaParams)); - } - - /// @notice Read the Witnet-provided result to a previously posted request. - /// @dev Reverts if the data request was not yet solved. - /// @param _id The unique identifier of some previously posted data request. - /// @return The result of the request as an instance of `Witnet.Result`. - function _witnetReadResult(uint256 _id) - internal view - virtual - returns (Witnet.Result memory) - { - return __witnet.readResponseResult(_id); - } - - /// @notice Upgrade the reward of some previously posted data request. - /// @dev Reverts if the data request was already solved. - /// @param _id The unique identifier of some previously posted data request. - /// @return Amount in which the reward has been increased. - function _witnetUpgradeReward(uint256 _id) - virtual internal - returns (uint256) - { - uint256 _currentReward = __witnet.readRequestReward(_id); - uint256 _newReward = _witnetEstimateReward(); - uint256 _fundsToAdd = 0; - if (_newReward > _currentReward) { - _fundsToAdd = (_newReward - _currentReward); - } - __witnet.upgradeReward{value: _fundsToAdd}(_id); - return _fundsToAdd; - } -} \ No newline at end of file diff --git a/contracts/WitnetBytecodes.sol b/contracts/WitnetBytecodes.sol index 3752d0dbe..6a1235331 100644 --- a/contracts/WitnetBytecodes.sol +++ b/contracts/WitnetBytecodes.sol @@ -4,12 +4,13 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; import "./interfaces/V2/IWitnetBytecodes.sol"; -import "./interfaces/V2/IWitnetBytecodesErrors.sol"; -import "./interfaces/V2/IWitnetBytecodesEvents.sol"; abstract contract WitnetBytecodes is - IWitnetBytecodes, - IWitnetBytecodesErrors, - IWitnetBytecodesEvents -{} \ No newline at end of file + IWitnetBytecodes +{ + function class() virtual external view returns (string memory) { + return type(WitnetBytecodes).name; + } + function specs() virtual external view returns (bytes4); +} \ No newline at end of file diff --git a/contracts/WitnetFeeds.sol b/contracts/WitnetFeeds.sol deleted file mode 100644 index 616b25489..000000000 --- a/contracts/WitnetFeeds.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -import "./interfaces/V2/IFeeds.sol"; -import "./interfaces/V2/IWitnetFeeds.sol"; -import "./interfaces/V2/IWitnetFeedsAdmin.sol"; -import "./interfaces/V2/IWitnetFeedsEvents.sol"; - -abstract contract WitnetFeeds - is - IFeeds, - IWitnetFeeds, - IWitnetFeedsAdmin, - IWitnetFeedsEvents -{ - WitnetV2.RadonDataTypes immutable public override dataType; - WitnetBytecodes immutable public override registry; - WitnetRequestBoard immutable public override witnet; - - bytes32 immutable internal __prefix; - - constructor( - WitnetRequestBoard _wrb, - WitnetV2.RadonDataTypes _dataType, - string memory _prefix - ) - { - witnet = _wrb; - registry = witnet.registry(); - dataType = _dataType; - __prefix = Witnet.toBytes32(bytes(_prefix)); - } - - function prefix() override public view returns (string memory) { - return Witnet.toString(__prefix); - } -} \ No newline at end of file diff --git a/contracts/WitnetPriceFeeds.sol b/contracts/WitnetPriceFeeds.sol deleted file mode 100644 index 60fda9612..000000000 --- a/contracts/WitnetPriceFeeds.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -import "ado-contracts/contracts/interfaces/IERC2362.sol"; -import "./interfaces/V2/IWitnetPriceFeeds.sol"; -import "./interfaces/V2/IWitnetPriceSolverDeployer.sol"; -import "./WitnetFeeds.sol"; - -abstract contract WitnetPriceFeeds - is - IERC2362, - IWitnetPriceFeeds, - IWitnetPriceSolverDeployer, - WitnetFeeds -{ - constructor(WitnetRequestBoard _wrb) - WitnetFeeds( - _wrb, - WitnetV2.RadonDataTypes.Integer, - "Price-" - ) - {} -} \ No newline at end of file diff --git a/contracts/WitnetRandomness.sol b/contracts/WitnetRandomness.sol deleted file mode 100644 index 98fc8384b..000000000 --- a/contracts/WitnetRandomness.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "./interfaces/IWitnetRandomness.sol"; -import "./interfaces/IWitnetRandomnessAdmin.sol"; - -abstract contract WitnetRandomness - is - IWitnetRandomness, - IWitnetRandomnessAdmin -{ - /// Deploys a minimal-proxy clone in which the `witnetRandomnessRequest` is owned by the cloner, - /// @dev This function should always provide a new address, no matter how many times - /// @dev is actually called from the same `msg.sender`. - function clone() virtual external returns (WitnetRandomness); - - /// Deploys a minimal-proxy clone in which the `witnetRandomnessRequest` is owned by the cloner, - /// and whose address will be determined by the provided salt. - /// @dev This function uses the CREATE2 opcode and a `_salt` to deterministically deploy - /// @dev the clone. Using the same `_salt` multiple time will revert, since - /// @dev no contract can be deployed more than once at the same address. - function cloneDeterministic(bytes32 salt) virtual external returns (WitnetRandomness); -} \ No newline at end of file diff --git a/contracts/requests/WitnetRequest.sol b/contracts/WitnetRequest.sol similarity index 100% rename from contracts/requests/WitnetRequest.sol rename to contracts/WitnetRequest.sol diff --git a/contracts/WitnetRequestBoard.sol b/contracts/WitnetRequestBoard.sol index 315d15c78..93da562cd 100644 --- a/contracts/WitnetRequestBoard.sol +++ b/contracts/WitnetRequestBoard.sol @@ -1,35 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; import "./WitnetBytecodes.sol"; import "./WitnetRequestFactory.sol"; - -import "./interfaces/IWitnetRequestBoardEvents.sol"; -import "./interfaces/IWitnetRequestBoardReporter.sol"; -import "./interfaces/IWitnetRequestBoardRequestor.sol"; -import "./interfaces/IWitnetRequestBoardView.sol"; - -import "./interfaces/IWitnetRequestBoardDeprecating.sol"; +import "./interfaces/V2/IWitnetRequestBoard.sol"; +import "./interfaces/V2/IWitnetRequestBoardEvents.sol"; /// @title Witnet Request Board functionality base contract. /// @author The Witnet Foundation. -abstract contract WitnetRequestBoard is - IWitnetRequestBoardDeprecating, - IWitnetRequestBoardEvents, - IWitnetRequestBoardReporter, - IWitnetRequestBoardRequestor, - IWitnetRequestBoardView +abstract contract WitnetRequestBoard + is + IWitnetRequestBoard, + IWitnetRequestBoardEvents { - WitnetRequestFactory immutable public factory; - WitnetBytecodes immutable public registry; - constructor (WitnetRequestFactory _factory) { - require( - _factory.class() == type(WitnetRequestFactory).interfaceId, - "WitnetRequestBoard: uncompliant factory" - ); - factory = _factory; - registry = _factory.registry(); + function class() virtual external view returns (string memory) { + return type(WitnetRequestBoard).name; } + function channel() virtual external view returns (bytes4); + function factory() virtual external view returns (WitnetRequestFactory); + function registry() virtual external view returns (WitnetBytecodes); + function specs() virtual external view returns (bytes4); } \ No newline at end of file diff --git a/contracts/WitnetRequestFactory.sol b/contracts/WitnetRequestFactory.sol index 221e74134..b6cf5c61d 100644 --- a/contracts/WitnetRequestFactory.sol +++ b/contracts/WitnetRequestFactory.sol @@ -3,9 +3,16 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; +import "./WitnetBytecodes.sol"; +import "./WitnetRequestBoard.sol"; import "./interfaces/V2/IWitnetRequestFactory.sol"; abstract contract WitnetRequestFactory is IWitnetRequestFactory -{} \ No newline at end of file +{ + function class() virtual external view returns (string memory); + function registry() virtual external view returns (WitnetBytecodes); + function specs() virtual external view returns (bytes4); + function witnet() virtual external view returns (WitnetRequestBoard); +} \ No newline at end of file diff --git a/contracts/requests/WitnetRequestTemplate.sol b/contracts/WitnetRequestTemplate.sol similarity index 75% rename from contracts/requests/WitnetRequestTemplate.sol rename to contracts/WitnetRequestTemplate.sol index f180e5060..5a6b47930 100644 --- a/contracts/requests/WitnetRequestTemplate.sol +++ b/contracts/WitnetRequestTemplate.sol @@ -3,28 +3,32 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../WitnetRequestFactory.sol"; +import "./WitnetBytecodes.sol"; +import "./WitnetRequestBoard.sol"; +import "./WitnetRequestFactory.sol"; abstract contract WitnetRequestTemplate { event WitnetRequestBuilt(address indexed request, bytes32 indexed radHash, string[][] args); - function class() virtual external view returns (bytes4); + function class() virtual external view returns (string memory); function factory() virtual external view returns (WitnetRequestFactory); function registry() virtual external view returns (WitnetBytecodes); + function specs() virtual external view returns (bytes4); function version() virtual external view returns (string memory); + function witnet() virtual external view returns (WitnetRequestBoard); function aggregator() virtual external view returns (bytes32); function parameterized() virtual external view returns (bool); function resultDataMaxSize() virtual external view returns (uint16); - function resultDataType() virtual external view returns (WitnetV2.RadonDataTypes); + function resultDataType() virtual external view returns (Witnet.RadonDataTypes); function retrievals() virtual external view returns (bytes32[] memory); function tally() virtual external view returns (bytes32); - function getRadonAggregator() virtual external view returns (WitnetV2.RadonReducer memory); - function getRadonRetrievalByIndex(uint256) virtual external view returns (WitnetV2.RadonRetrieval memory); + function getRadonAggregator() virtual external view returns (Witnet.RadonReducer memory); + function getRadonRetrievalByIndex(uint256) virtual external view returns (Witnet.RadonRetrieval memory); function getRadonRetrievalsCount() virtual external view returns (uint256); - function getRadonTally() virtual external view returns (WitnetV2.RadonReducer memory); + function getRadonTally() virtual external view returns (Witnet.RadonReducer memory); function buildRequest(string[][] calldata args) virtual external returns (address); function verifyRadonRequest(string[][] calldata args) virtual external returns (bytes32); diff --git a/contracts/apps/UsingWitnet.sol b/contracts/apps/UsingWitnet.sol new file mode 100644 index 000000000..f267a67f8 --- /dev/null +++ b/contracts/apps/UsingWitnet.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../WitnetRequestBoard.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 + IWitnetRequestBoardEvents +{ + /// @dev Immutable reference to the Witnet Request Board contract. + WitnetRequestBoard internal immutable __witnet; + + /// @dev Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain + /// @dev when solving a data request. + bytes32 private __witnetDefaultPackedSLA; + + /// @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 private __witnetBaseFeeOverheadPercentage; + + /// @param _wrb Address of the WitnetRequestBoard contract. + constructor(WitnetRequestBoard _wrb) { + require( + _wrb.specs() == type(IWitnetRequestBoard).interfaceId, + "UsingWitnet: uncompliant WitnetRequestBoard" + ); + __witnet = _wrb; + __witnetDefaultPackedSLA = WitnetV2.toBytes32(WitnetV2.RadonSLA({ + witnessingCommitteeSize: 10, // up to 127 + witnessingWitTotalReward: 10 ** 9 // 1.0 $WIT + })); + + __witnetBaseFeeOverheadPercentage = 10; // defaults to 10% + } + + /// @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 (WitnetRequestBoard) { + 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 _witnetCheckQueryResultAuditTrail(uint256 _witnetQueryId) + internal view + returns ( + uint256 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + uint256 _witnetEvmFinalityBlock + ) + { + return __witnet.getQueryResultAuditTrail(_witnetQueryId); + } + + function _witnetCheckQueryResultStatus(uint256 _witnetQueryId) + internal view + returns (WitnetV2.ResultStatus) + { + return __witnet.getQueryResultStatus(_witnetQueryId); + } + + function _witnetCheckQueryResultError(uint256 _witnetQueryId) + internal view + returns (Witnet.ResultError memory) + { + return __witnet.getQueryResultError(_witnetQueryId); + } + + function _witnetDefaultSLA() virtual internal view returns (WitnetV2.RadonSLA memory) { + return WitnetV2.toRadonSLA(__witnetDefaultPackedSLA); + } + + function _witnetBaseFeeOverheadPercentage() virtual internal view returns (uint16) { + return __witnetBaseFeeOverheadPercentage; + } + + function __witnetSetDefaultSLA(WitnetV2.RadonSLA memory _defaultSLA) virtual internal { + __witnetDefaultPackedSLA = WitnetV2.toBytes32(_defaultSLA); + } + + function __witnetSetBaseFeeOverheadPercentage(uint16 _baseFeeOverheadPercentage) virtual internal { + __witnetBaseFeeOverheadPercentage = _baseFeeOverheadPercentage; + } +} diff --git a/contracts/apps/UsingWitnetRandomness.sol b/contracts/apps/UsingWitnetRandomness.sol new file mode 100644 index 000000000..fa62d6f45 --- /dev/null +++ b/contracts/apps/UsingWitnetRandomness.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./WitnetConsumer.sol"; +import "../WitnetRequest.sol"; + +abstract contract UsingWitnetRandomness + is + WitnetConsumer +{ + using Witnet for bytes; + using WitnetCBOR for WitnetCBOR.CBOR; + using WitnetV2 for bytes32; + using WitnetV2 for WitnetV2.RadonSLA; + + bytes32 internal immutable __witnetRandomnessRadHash; + + /// @param _wrb Address of the WitnetRequestBoard contract. + /// @param _baseFeeOverheadPercentage Percentage over base fee to pay as on every data request. + /// @param _callbackGasLimit Maximum gas to be spent by the IWitnetConsumer's callback methods. + /// @param _defaultSLA Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain. + constructor( + WitnetRequestBoard _wrb, + uint16 _baseFeeOverheadPercentage, + uint96 _callbackGasLimit, + WitnetV2.RadonSLA memory _defaultSLA + ) + UsingWitnet(_wrb) + WitnetConsumer(_callbackGasLimit) + { + // On-chain building of the Witnet Randomness Request: + { + WitnetRequestFactory _factory = witnet().factory(); + WitnetBytecodes _registry = witnet().registry(); + // Build own Witnet Randomness Request: + bytes32[] memory _retrievals = new bytes32[](1); + _retrievals[0] = _registry.verifyRadonRetrieval( + Witnet.RadonDataRequestMethods.Rng, + "", // no url + "", // no body + new string[2][](0), // no headers + hex"80" // no retrieval 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 + })); + WitnetRequestTemplate _template = WitnetRequestTemplate(_factory.buildRequestTemplate( + _retrievals, + _aggregator, + _tally, + 32 // 256 bits of pure entropy ;-) + )); + __witnetRandomnessRadHash = WitnetRequest( + _template.buildRequest(new string[][](_retrievals.length)) + ).radHash(); + } + // Settle default randomize SLA: + __witnetSetDefaultSLA(_defaultSLA); + __witnetSetBaseFeeOverheadPercentage(_baseFeeOverheadPercentage); + } + + function _witnetEstimateEvmReward() virtual override internal view returns (uint256) { + return _witnetEstimateEvmReward(32); + } + + function _witnetRandomUniformUint32(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); + } + + function _witnetReadRandomizeFromResultValue(WitnetCBOR.CBOR calldata cborValue) internal pure returns (bytes32) { + return cborValue.readBytes().toBytes32(); + } + + function __witnetRandomize(uint256 _witnetEvmReward) virtual internal returns (uint256) { + return __witnetRandomize(_witnetEvmReward, _witnetDefaultSLA()); + } + + function __witnetRandomize( + uint256 _witnetEvmReward, + WitnetV2.RadonSLA memory _witnetQuerySLA + ) + virtual internal + returns (uint256 _randomizeId) + { + return __witnet.postRequest{value: _witnetEvmReward}( + __witnetRandomnessRadHash, + _witnetQuerySLA + ); + } +} diff --git a/contracts/apps/UsingWitnetRequest.sol b/contracts/apps/UsingWitnetRequest.sol new file mode 100644 index 000000000..fa5cbec20 --- /dev/null +++ b/contracts/apps/UsingWitnetRequest.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./UsingWitnet.sol"; +import "../WitnetRequest.sol"; + +abstract contract UsingWitnetRequest + is UsingWitnet +{ + WitnetRequest immutable public dataRequest; + + bytes32 immutable internal __witnetRequestRadHash; + uint16 immutable internal __witnetResultMaxSize; + + /// @param _witnetRequest Address of the WitnetRequest contract containing the actual data request. + /// @param _baseFeeOverheadPercentage Percentage over base fee to pay as on every data request. + /// @param _defaultSLA Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain. + constructor ( + WitnetRequest _witnetRequest, + uint16 _baseFeeOverheadPercentage, + WitnetV2.RadonSLA memory _defaultSLA + ) + UsingWitnet(_witnetRequest.witnet()) + { + require( + _witnetRequest.specs() == type(WitnetRequest).interfaceId, + "UsingWitnetRequest: uncompliant WitnetRequest" + ); + dataRequest = _witnetRequest; + __witnetResultMaxSize = _witnetRequest.resultDataMaxSize(); + __witnetRequestRadHash = _witnetRequest.radHash(); + __witnetSetDefaultSLA(_defaultSLA); + __witnetSetBaseFeeOverheadPercentage(_baseFeeOverheadPercentage); + } + + function _witnetEstimateEvmReward() + virtual internal view + returns (uint256) + { + return _witnetEstimateEvmReward(__witnetResultMaxSize); + } + + function __witnetRequestData(uint256 _witnetEvmReward) + virtual internal returns (uint256) + { + return __witnetRequestData(_witnetEvmReward, _witnetDefaultSLA()); + } + + function __witnetRequestData( + uint256 _witnetEvmReward, + WitnetV2.RadonSLA memory _witnetQuerySLA + ) + virtual internal returns (uint256) + { + return __witnet.postRequest{value: _witnetEvmReward}( + __witnetRequestRadHash, + _witnetQuerySLA + ); + } +} diff --git a/contracts/apps/UsingWitnetRequestTemplate.sol b/contracts/apps/UsingWitnetRequestTemplate.sol new file mode 100644 index 000000000..d3ad0a172 --- /dev/null +++ b/contracts/apps/UsingWitnetRequestTemplate.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./UsingWitnet.sol"; +import "../WitnetRequest.sol"; + +abstract contract UsingWitnetRequestTemplate + is UsingWitnet +{ + WitnetRequestTemplate immutable public dataRequestTemplate; + + uint16 immutable internal __witnetResultMaxSize; + + /// @param _witnetRequestTemplate Address of the WitnetRequestTemplate from which actual data requests will get built. + /// @param _baseFeeOverheadPercentage Percentage over base fee to pay as on every data request. + /// @param _defaultSLA Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain. + constructor ( + WitnetRequestTemplate _witnetRequestTemplate, + uint16 _baseFeeOverheadPercentage, + WitnetV2.RadonSLA memory _defaultSLA + ) + UsingWitnet(_witnetRequestTemplate.witnet()) + { + require( + _witnetRequestTemplate.specs() == type(WitnetRequestTemplate).interfaceId, + "UsingWitnetRequestTemplate: uncompliant WitnetRequestTemplate" + ); + dataRequestTemplate = _witnetRequestTemplate; + __witnetResultMaxSize = _witnetRequestTemplate.resultDataMaxSize(); + __witnetSetDefaultSLA(_defaultSLA); + __witnetSetBaseFeeOverheadPercentage(_baseFeeOverheadPercentage); + } + + function _witnetBuildRadHash(string[][] memory _witnetRequestArgs) + internal returns (bytes32) + { + return dataRequestTemplate.verifyRadonRequest(_witnetRequestArgs); + } + + function _witnetBuildRequest(string[][] memory _witnetRequestArgs) + internal returns (WitnetRequest) + { + return WitnetRequest(dataRequestTemplate.buildRequest(_witnetRequestArgs)); + } + + function _witnetEstimateEvmReward() + virtual internal view + returns (uint256) + { + return _witnetEstimateEvmReward(__witnetResultMaxSize); + } + + function __witnetRequestData( + uint256 _witnetEvmReward, + string[][] memory _witnetRequestArgs + ) + virtual internal returns (uint256) + { + return __witnetRequestData(_witnetEvmReward, _witnetRequestArgs, _witnetDefaultSLA()); + } + + function __witnetRequestData( + uint256 _witnetEvmReward, + string[][] memory _witnetRequestArgs, + WitnetV2.RadonSLA memory _witnetQuerySLA + ) + virtual internal returns (uint256) + { + return __witnet.postRequest{value: _witnetEvmReward}( + _witnetBuildRadHash(_witnetRequestArgs), + _witnetQuerySLA + ); + } +} diff --git a/contracts/apps/WitnetConsumer.sol b/contracts/apps/WitnetConsumer.sol new file mode 100644 index 000000000..c0029b640 --- /dev/null +++ b/contracts/apps/WitnetConsumer.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./UsingWitnet.sol"; +import "../interfaces/V2/IWitnetConsumer.sol"; + +abstract contract WitnetConsumer + is + IWitnetConsumer, + UsingWitnet +{ + /// @dev Maximum gas to be spent by the IWitnetConsumer's callback methods. + uint96 private immutable __witnetCallbackGasLimit; + + modifier onlyFromWitnet { + require(msg.sender == address(__witnet), "WitnetConsumer: unauthorized"); + _; + } + + /// @param _callbackGasLimit Maximum gas to be spent by the IWitnetConsumer's callback methods. + constructor (uint96 _callbackGasLimit) { + __witnetCallbackGasLimit = _callbackGasLimit; + } + + + /// =============================================================================================================== + /// --- Base implementation of IWitnetConsumer -------------------------------------------------------------------- + + function reportableFrom(address _from) virtual override external view returns (bool) { + return _from == address(__witnet); + } + + + /// =============================================================================================================== + /// --- WitnetConsumer virtual methods ---------------------------------------------------------------------------- + + function _witnetCallbackGasLimit() + virtual internal view + returns (uint96) + { + return __witnetCallbackGasLimit; + } + + function _witnetEstimateEvmReward() virtual internal view returns (uint256) { + return ( + (100 + _witnetBaseFeeOverheadPercentage()) + * __witnet.estimateBaseFeeWithCallback( + tx.gasprice, + _witnetCallbackGasLimit() + ) + ) / 100; + } + + function _witnetEstimateEvmReward(uint16) + virtual override internal view + returns (uint256) + { + return _witnetEstimateEvmReward(); + } + + + /// @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 _callbackGasLimit Maximum gas to be spent when reporting the data request result. + function _witnetEstimateEvmRewardWithCallback(uint96 _callbackGasLimit) + virtual internal view + returns (uint256) + { + return ( + (100 + _witnetBaseFeeOverheadPercentage()) + * __witnet.estimateBaseFeeWithCallback( + tx.gasprice, + _callbackGasLimit + ) + ) / 100; + } +} diff --git a/contracts/apps/WitnetFeeds.sol b/contracts/apps/WitnetFeeds.sol new file mode 100644 index 000000000..0eb7ef337 --- /dev/null +++ b/contracts/apps/WitnetFeeds.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; + +import "../interfaces/V2/IFeeds.sol"; +import "../interfaces/V2/IWitnetFeeds.sol"; +import "../interfaces/V2/IWitnetFeedsAdmin.sol"; + +abstract contract WitnetFeeds + is + IFeeds, + IWitnetFeeds, + IWitnetFeedsAdmin +{ + Witnet.RadonDataTypes immutable public override dataType; + + bytes32 immutable internal __prefix; + + constructor( + Witnet.RadonDataTypes _dataType, + string memory _prefix + ) + { + dataType = _dataType; + __prefix = Witnet.toBytes32(bytes(_prefix)); + } + + function prefix() override public view returns (string memory) { + return Witnet.toString(__prefix); + } +} \ No newline at end of file diff --git a/contracts/impls/apps/WitnetPriceFeedsUpgradable.sol b/contracts/apps/WitnetPriceFeeds.sol similarity index 70% rename from contracts/impls/apps/WitnetPriceFeedsUpgradable.sol rename to contracts/apps/WitnetPriceFeeds.sol index 515a640c9..7c6de97a6 100644 --- a/contracts/impls/apps/WitnetPriceFeedsUpgradable.sol +++ b/contracts/apps/WitnetPriceFeeds.sol @@ -3,39 +3,56 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../../WitnetPriceFeeds.sol"; -import "../../data/WitnetPriceFeedsData.sol"; -import "../../impls/WitnetUpgradableBase.sol"; +import "ado-contracts/contracts/interfaces/IERC2362.sol"; -import "../../interfaces/V2/IWitnetPriceSolver.sol"; -import "../../libs/WitnetPriceFeedsLib.sol"; +import "./WitnetFeeds.sol"; +import "../WitnetRequestBoard.sol"; +import "../data/WitnetPriceFeedsData.sol"; +import "../interfaces/V2/IWitnetPriceFeeds.sol"; +import "../interfaces/V2/IWitnetPriceSolver.sol"; +import "../interfaces/V2/IWitnetPriceSolverDeployer.sol"; +import "../libs/WitnetPriceFeedsLib.sol"; +import "../patterns/Ownable2Step.sol"; -/// @title WitnetPriceFeedsUpgradable: ... -/// @author Witnet Foundation. -contract WitnetPriceFeedsUpgradable +/// @title WitnetPriceFeeds: Price Feeds oracle reliant on the Witnet Solidity Bridge. +/// @author Guillermo Díaz + +contract WitnetPriceFeeds is - WitnetPriceFeeds, - WitnetPriceFeedsData, - WitnetUpgradableBase + IERC2362, + IWitnetPriceFeeds, + IWitnetPriceSolverDeployer, + Ownable2Step, + WitnetFeeds, + WitnetPriceFeedsData { using Witnet for Witnet.Result; + using WitnetV2 for WitnetV2.Response; using WitnetV2 for WitnetV2.RadonSLA; + + bytes4 immutable public specs = type(IWitnetPriceFeeds).interfaceId; + WitnetRequestBoard immutable public override witnet; - constructor( - WitnetRequestBoard _wrb, - bool _upgradable, - bytes32 _version - ) - WitnetPriceFeeds(_wrb) - WitnetUpgradableBase( - _upgradable, - _version, - "io.witnet.proxiable.router" + constructor(address _operator, WitnetRequestBoard _wrb) + WitnetFeeds( + Witnet.RadonDataTypes.Integer, + "Price-" ) - {} + { + _transferOwnership(_operator); + require( + _wrb.specs() == type(IWitnetRequestBoard).interfaceId, + "WitnetPriceFeeds: uncompliant request board" + ); + witnet = _wrb; + __settleDefaultRadonSLA(WitnetV2.RadonSLA({ + witnessingCommitteeSize: 10, + witnessingWitTotalReward: 10 ** 9 + })); + } // solhint-disable-next-line payable-fallback - fallback() override external { + fallback() external { if ( msg.sig == IWitnetPriceSolver.solve.selector && msg.sender == address(this) @@ -43,7 +60,7 @@ contract WitnetPriceFeedsUpgradable address _solver = __records_(bytes4(bytes8(msg.data) << 32)).solver; require( _solver != address(0), - "WitnetPriceFeedsUpgradable: unsettled solver" + "WitnetPriceFeeds: unsettled solver" ); assembly { let ptr := mload(0x40) @@ -56,61 +73,8 @@ contract WitnetPriceFeedsUpgradable default { return(ptr, size) } } } else { - revert("WitnetPriceFeedsUpgradable: not implemented"); - } - } - - - // ================================================================================================================ - // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------- - - /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. - /// @dev Must fail when trying to upgrade to same logic contract more than once. - function initialize(bytes memory) - public override - onlyDelegateCalls // => we don't want the logic base contract to be ever initialized - { - if ( - __proxiable().proxy == address(0) - && __proxiable().implementation == address(0) - ) { - // a proxy is being initialized for the first time... - __proxiable().proxy = address(this); - _transferOwnership(msg.sender); - } else { - // only the owner can initialize: - if (msg.sender != owner()) { - revert("WitnetPriceFeedsUpgradable: not the owner"); - } + revert("WitnetPriceFeeds: not implemented"); } - require( - __proxiable().implementation != base(), - "WitnetPriceFeedsUpgradable: already initialized" - ); - if (__storage().defaultSlaHash == 0) { - settleDefaultRadonSLA(WitnetV2.RadonSLA({ - numWitnesses: 5, - witnessCollateral: 15 * 10 ** 9, - witnessReward: 15 * 10 ** 7, - minerCommitRevealFee: 10 ** 7, - minConsensusPercentage: 51 - })); - } - __proxiable().implementation = base(); - emit Upgraded(msg.sender, base(), codehash(), version()); - } - - /// Tells whether provided address could eventually upgrade the contract. - function isUpgradableFrom(address _from) - override - external view - returns (bool) - { - return ( - // false if the contract is set as not upgradable, or `_from` is not the owner - isUpgradable() - && _from == owner() - ); } @@ -174,39 +138,29 @@ contract WitnetPriceFeedsUpgradable public view returns (WitnetV2.RadonSLA memory) { - return registry.lookupRadonSLA(__storage().defaultSlaHash); + return WitnetV2.toRadonSLA(__storage().packedDefaultSLA); } - function estimateUpdateBaseFee(bytes4, uint256 _evmGasPrice, uint256) + function estimateUpdateBaseFee(uint256 _evmGasPrice) virtual override public view returns (uint) { - // TODO: refactor when WRB.estimateBaseFee(bytes32,bytes32,uint256,uint256) is implemented. - return witnet.estimateReward(_evmGasPrice); - } - - function estimateUpdateBaseFee(bytes4, uint256 _evmGasPrice, uint256, bytes32) - virtual override - public view - returns (uint) - { - // TODO: refactor when WRB.estimateBaseFee(bytes32,bytes32,uint256,uint256) is implemented. - return witnet.estimateReward(_evmGasPrice); + return witnet.estimateBaseFee(_evmGasPrice, 32); } function latestResponse(bytes4 feedId) override public view - returns (Witnet.Response memory) + returns (WitnetV2.Response memory) { - return witnet.readResponse(_latestValidQueryId(feedId)); + return witnet.getQueryResponse(_latestValidQueryId(feedId)); } function latestResult(bytes4 feedId) override external view returns (Witnet.Result memory) { - return witnet.readResponseResult(_latestValidQueryId(feedId)); + return witnet.getQueryResult(_latestValidQueryId(feedId)); } function latestUpdateQueryId(bytes4 feedId) @@ -218,28 +172,28 @@ contract WitnetPriceFeedsUpgradable function latestUpdateRequest(bytes4 feedId) override external view - returns (Witnet.Request memory) + returns (bytes32, WitnetV2.RadonSLA memory) { - return witnet.readRequest(latestUpdateQueryId(feedId)); + return witnet.getQueryRequest(latestUpdateQueryId(feedId)); } function latestUpdateResponse(bytes4 feedId) override external view - returns (Witnet.Response memory) + returns (WitnetV2.Response memory) { - return witnet.readResponse(latestUpdateQueryId(feedId)); + return witnet.getQueryResponse(latestUpdateQueryId(feedId)); } function latestUpdateResultError(bytes4 feedId) override external view returns (Witnet.ResultError memory) { - return witnet.checkResultError(latestUpdateQueryId(feedId)); + return witnet.getQueryResultError(latestUpdateQueryId(feedId)); } function latestUpdateResultStatus(bytes4 feedId) override public view - returns (Witnet.ResultStatus) + returns (WitnetV2.ResultStatus) { return _checkQueryResultStatus(latestUpdateQueryId(feedId)); } @@ -251,12 +205,9 @@ contract WitnetPriceFeedsUpgradable Record storage __record = __records_(feedId); require( __record.radHash != 0, - "WitnetPriceFeedsUpgradable: no RAD hash" - ); - return registry.bytecodeOf( - __record.radHash, - __storage().defaultSlaHash + "WitnetPriceFeeds: no RAD hash" ); + return registry().bytecodeOf(__record.radHash); } function lookupRadHash(bytes4 feedId) @@ -268,99 +219,76 @@ contract WitnetPriceFeedsUpgradable function lookupRetrievals(bytes4 feedId) override external view - returns (WitnetV2.RadonRetrieval[] memory _retrievals) + returns (Witnet.RadonRetrieval[] memory _retrievals) { - bytes32[] memory _hashes = registry.lookupRadonRequestSources(lookupRadHash(feedId)); - _retrievals = new WitnetV2.RadonRetrieval[](_hashes.length); + bytes32[] memory _hashes = registry().lookupRadonRequestSources(lookupRadHash(feedId)); + _retrievals = new Witnet.RadonRetrieval[](_hashes.length); for (uint _ix = 0; _ix < _retrievals.length; _ix ++) { - _retrievals[_ix] = registry.lookupRadonRetrieval(_hashes[_ix]); + _retrievals[_ix] = registry().lookupRadonRetrieval(_hashes[_ix]); } } + function registry() public view virtual override returns (WitnetBytecodes) { + return WitnetRequestBoard(address(witnet)).registry(); + } + function requestUpdate(bytes4 feedId) external payable virtual override returns (uint256) { - return _requestUpdate(feedId, __storage().defaultSlaHash); + return __requestUpdate( + feedId, + WitnetV2.toRadonSLA(__storage().packedDefaultSLA) + ); } - function requestUpdate(bytes4 feedId, bytes32 _slaHash) + function requestUpdate(bytes4 feedId, WitnetV2.RadonSLA calldata updateSLA) public payable virtual override returns (uint256 _usedFunds) { require( - registry.lookupRadonSLA(_slaHash).equalOrGreaterThan(defaultRadonSLA()), - "WitnetPriceFeedsUpgradable: unsecure update" + updateSLA.equalOrGreaterThan(defaultRadonSLA()), + "WitnetPriceFeeds: unsecure update" ); - return _requestUpdate(feedId, _slaHash); + return __requestUpdate(feedId, updateSLA); } - function _requestUpdate(bytes4[] memory _deps, bytes32 slaHash) - virtual internal - returns (uint256 _usedFunds) + + // ================================================================================================================ + // --- Implements 'IWitnetFeedsAdmin' ----------------------------------------------------------------------------- + + function owner() + virtual override (IWitnetFeedsAdmin, Ownable) + public view + returns (address) { - uint _partial = msg.value / _deps.length; - for (uint _ix = 0; _ix < _deps.length; _ix ++) { - _usedFunds += this.requestUpdate{value: _partial}(_deps[_ix], slaHash); - } + return Ownable.owner(); } - - function _requestUpdate(bytes4 feedId, bytes32 _slaHash) - virtual internal - returns (uint256 _usedFunds) + + function acceptOwnership() + virtual override (IWitnetFeedsAdmin, Ownable2Step) + public { - Record storage __feed = __records_(feedId); - if (__feed.radHash != 0) { - _usedFunds = estimateUpdateBaseFee(feedId, tx.gasprice, 0, _slaHash); - require(msg.value>= _usedFunds, "WitnetPriceFeedsUpgradable: reward too low"); - uint _latestId = __feed.latestUpdateQueryId; - Witnet.ResultStatus _latestStatus = _checkQueryResultStatus(_latestId); - if (_latestStatus == Witnet.ResultStatus.Awaiting) { - // latest update is still pending, so just increase the reward - // accordingly to current tx gasprice: - int _deltaReward = int(witnet.readRequestReward(_latestId)) - int(_usedFunds); - if (_deltaReward > 0) { - _usedFunds = uint(_deltaReward); - witnet.upgradeReward{value: _usedFunds}(_latestId); - emit UpdatingFeedReward(msg.sender, feedId, _usedFunds); - } else { - _usedFunds = 0; - } - } else { - // Check if latest update ended successfully: - if (_latestStatus == Witnet.ResultStatus.Ready) { - // If so, remove previous last valid query from the WRB: - if (__feed.latestValidQueryId > 0) { - witnet.deleteQuery(__feed.latestValidQueryId); - } - __feed.latestValidQueryId = _latestId; - } else { - // Otherwise, try to delete latest query, as it was faulty - // and we are about to post a new update request: - try witnet.deleteQuery(_latestId) {} catch {} - } - // Post update request to the WRB: - _latestId = witnet.postRequest{value: _usedFunds}(__feed.radHash, _slaHash); - // Update latest query id: - __feed.latestUpdateQueryId = _latestId; - emit UpdatingFeed(msg.sender, feedId, _slaHash, _usedFunds); - } - } else if (__feed.solver != address(0)) { - _usedFunds = _requestUpdate(_depsOf(feedId), _slaHash); - } else { - revert("WitnetPriceFeedsUpgradable: unknown feed"); - } - if (_usedFunds < msg.value) { - // transfer back unused funds: - payable(msg.sender).transfer(msg.value - _usedFunds); - } + Ownable2Step.acceptOwnership(); } - - // ================================================================================================================ - // --- Implements 'IWitnetFeedsAdmin' ----------------------------------------------------------------------- + function pendingOwner() + virtual override (IWitnetFeedsAdmin, Ownable2Step) + public view + returns (address) + { + return Ownable2Step.pendingOwner(); + } + + function transferOwnership(address _newOwner) + virtual override (IWitnetFeedsAdmin, Ownable2Step) + public + onlyOwner + { + Ownable.transferOwnership(_newOwner); + } function deleteFeed(string calldata caption) virtual override @@ -371,7 +299,7 @@ contract WitnetPriceFeedsUpgradable bytes4[] storage __ids = __storage().ids; Record storage __record = __records_(feedId); uint _index = __record.index; - require(_index != 0, "WitnetPriceFeedsUpgradable: unknown feed"); + require(_index != 0, "WitnetPriceFeeds: unknown feed"); { bytes4 _lastFeedId = __ids[__ids.length - 1]; __ids[_index - 1] = _lastFeedId; @@ -381,11 +309,11 @@ contract WitnetPriceFeedsUpgradable emit DeletedFeed(msg.sender, feedId, caption); } - function settleDefaultRadonSLA(WitnetV2.RadonSLA memory sla) + function settleDefaultRadonSLA(WitnetV2.RadonSLA memory defaultSLA) override public onlyOwner { - __storage().defaultSlaHash = registry.verifyRadonSLA(sla); + __settleDefaultRadonSLA(defaultSLA); } function settleFeedRequest(string calldata caption, bytes32 radHash) @@ -393,8 +321,8 @@ contract WitnetPriceFeedsUpgradable onlyOwner { require( - registry.lookupRadonRequestResultDataType(radHash) == dataType, - "WitnetPriceFeedsUpgradable: bad result data type" + registry().lookupRadonRequestResultDataType(radHash) == dataType, + "WitnetPriceFeeds: bad result data type" ); bytes4 feedId = hash(caption); Record storage __record = __records_(feedId); @@ -441,7 +369,7 @@ contract WitnetPriceFeedsUpgradable { require( solver != address(0), - "WitnetPriceFeedsUpgradable: no solver address" + "WitnetPriceFeeds: no solver address" ); bytes4 feedId = hash(caption); Record storage __record = __records_(feedId); @@ -487,7 +415,7 @@ contract WitnetPriceFeedsUpgradable _reason := add(_reason, 4) } revert(string(abi.encodePacked( - "WitnetPriceFeedsUpgradable: smoke-test failed: ", + "WitnetPriceFeeds: smoke-test failed: ", string(abi.decode(_reason,(string))) ))); } @@ -527,12 +455,12 @@ contract WitnetPriceFeedsUpgradable { uint _queryId = _latestValidQueryId(feedId); if (_queryId > 0) { - Witnet.Response memory _latestResponse = latestResponse(feedId); + WitnetV2.Response memory _latestResponse = latestResponse(feedId); Witnet.Result memory _latestResult = Witnet.resultFromCborBytes(_latestResponse.cborBytes); return IWitnetPriceSolver.Price({ value: _latestResult.asUint(), timestamp: _latestResponse.timestamp, - drTxHash: _latestResponse.drTxHash, + tallyHash: _latestResponse.tallyHash, status: latestUpdateResultStatus(feedId) }); } else { @@ -548,7 +476,7 @@ contract WitnetPriceFeedsUpgradable _result := add(_result, 4) } revert(string(abi.encodePacked( - "WitnetPriceFeedsUpgradable: ", + "WitnetPriceFeeds: ", string(abi.decode(_result, (string))) ))); } else { @@ -558,7 +486,7 @@ contract WitnetPriceFeedsUpgradable return IWitnetPriceSolver.Price({ value: 0, timestamp: 0, - drTxHash: 0, + tallyHash: 0, status: latestUpdateResultStatus(feedId) }); } @@ -616,11 +544,13 @@ contract WitnetPriceFeedsUpgradable return ( int(_latestPrice.value), _latestPrice.timestamp, - _latestPrice.status == Witnet.ResultStatus.Ready + _latestPrice.status == WitnetV2.ResultStatus.Ready ? 200 - : _latestPrice.status == Witnet.ResultStatus.Awaiting - ? 404 - : 400 + : ( + _latestPrice.status == WitnetV2.ResultStatus.Awaiting + || _latestPrice.status == WitnetV2.ResultStatus.AwaitingReady + || _latestPrice.status == WitnetV2.ResultStatus.AwaitingError + ) ? 404 : 400 ); } @@ -630,12 +560,12 @@ contract WitnetPriceFeedsUpgradable function _checkQueryResultStatus(uint _queryId) internal view - returns (Witnet.ResultStatus) + returns (WitnetV2.ResultStatus) { if (_queryId > 0) { - return witnet.checkResultStatus(_queryId); + return witnet.getQueryResultStatus(_queryId); } else { - return Witnet.ResultStatus.Ready; + return WitnetV2.ResultStatus.Ready; } } @@ -646,7 +576,7 @@ contract WitnetPriceFeedsUpgradable uint _latestUpdateQueryId = latestUpdateQueryId(feedId); if ( _latestUpdateQueryId > 0 - && witnet.checkResultStatus(_latestUpdateQueryId) == Witnet.ResultStatus.Ready + && witnet.getQueryResultStatus(_latestUpdateQueryId) == WitnetV2.ResultStatus.Ready ) { return _latestUpdateQueryId; } else { @@ -661,9 +591,88 @@ contract WitnetPriceFeedsUpgradable return _decimals; } catch Error(string memory reason) { revert(string(abi.encodePacked( - "WitnetPriceFeedsUpgradable: ", + "WitnetPriceFeeds: ", reason ))); } } + + function __requestUpdate(bytes4[] memory _deps, WitnetV2.RadonSLA memory sla) + virtual internal + returns (uint256 _usedFunds) + { + uint _partial = msg.value / _deps.length; + for (uint _ix = 0; _ix < _deps.length; _ix ++) { + _usedFunds += this.requestUpdate{value: _partial}(_deps[_ix], sla); + } + } + + function __requestUpdate(bytes4 feedId, WitnetV2.RadonSLA memory querySLA) + virtual internal + returns (uint256 _usedFunds) + { + Record storage __feed = __records_(feedId); + if (__feed.radHash != 0) { + _usedFunds = estimateUpdateBaseFee(tx.gasprice); + require( + msg.value >= _usedFunds, + "WitnetPriceFeeds: insufficient reward" + ); + uint _latestId = __feed.latestUpdateQueryId; + WitnetV2.ResultStatus _latestStatus = _checkQueryResultStatus(_latestId); + if (_latestStatus == WitnetV2.ResultStatus.Awaiting) { + // latest update is still pending, so just increase the reward + // accordingly to current tx gasprice: + int _deltaReward = int(witnet.getQueryReward(_latestId)) - int(_usedFunds); + if (_deltaReward > 0) { + _usedFunds = uint(_deltaReward); + witnet.upgradeQueryReward{value: _usedFunds}(_latestId); + emit UpdatingFeedReward(msg.sender, feedId, _usedFunds); + } else { + _usedFunds = 0; + } + } else { + // Check if latest update ended successfully: + if (_latestStatus == WitnetV2.ResultStatus.Ready) { + // If so, remove previous last valid query from the WRB: + if (__feed.latestValidQueryId > 0) { + witnet.fetchQueryResponse(__feed.latestValidQueryId); + } + __feed.latestValidQueryId = _latestId; + } else { + // Otherwise, try to delete latest query, as it was faulty + // and we are about to post a new update request: + try witnet.fetchQueryResponse(_latestId) {} catch {} + } + // Post update request to the WRB: + _latestId = witnet.postRequest{value: _usedFunds}( + __feed.radHash, + querySLA + ); + // Update latest query id: + __feed.latestUpdateQueryId = _latestId; + emit UpdatingFeed( + msg.sender, + feedId, + querySLA.toBytes32(), + _usedFunds + ); + } + } else if (__feed.solver != address(0)) { + _usedFunds = __requestUpdate( + _depsOf(feedId), + querySLA + ); + } else { + revert("WitnetPriceFeeds: unknown feed"); + } + if (_usedFunds < msg.value) { + // transfer back unused funds: + payable(msg.sender).transfer(msg.value - _usedFunds); + } + } + + function __settleDefaultRadonSLA(WitnetV2.RadonSLA memory sla) internal { + __storage().packedDefaultSLA = WitnetV2.toBytes32(sla); + } } diff --git a/contracts/impls/apps/WitnetRandomnessProxiable.sol b/contracts/apps/WitnetRandomness.sol similarity index 70% rename from contracts/impls/apps/WitnetRandomnessProxiable.sol rename to contracts/apps/WitnetRandomness.sol index 678c3dd8c..7947ef024 100644 --- a/contracts/impls/apps/WitnetRandomnessProxiable.sol +++ b/contracts/apps/WitnetRandomness.sol @@ -3,107 +3,104 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; - -import "../../UsingWitnet.sol"; -import "../../WitnetRandomness.sol"; -import "../../impls/WitnetUpgradableBase.sol"; -import "../../patterns/Clonable.sol"; - -import "../../requests/WitnetRequest.sol"; - -/// @title WitnetRandomnessProxiable: A trustless randomness generator and registry, using the Witnet oracle. -/// @author Witnet Foundation. -contract WitnetRandomnessProxiable +import "./UsingWitnet.sol"; +import "../WitnetRequest.sol"; +import "../core/WitnetUpgradableBase.sol"; +import "../interfaces/IWitnetRandomness.sol"; +import "../interfaces/IWitnetRandomnessAdmin.sol"; +import "../patterns/Clonable.sol"; +import "../patterns/Ownable2Step.sol"; + +/// @title WitnetRandomness: Randomness oracle reliant on the Witnet Solidity Bridge. +/// @author Guillermo Díaz + +contract WitnetRandomness is + IWitnetRandomness, + IWitnetRandomnessAdmin, Clonable, - UsingWitnet, - WitnetRandomness, - WitnetUpgradableBase + Ownable2Step, + UsingWitnet { - using ERC165Checker for address; using Witnet for Witnet.Result; + using WitnetV2 for bytes32; + using WitnetV2 for WitnetV2.RadonSLA; + bytes4 public immutable specs = type(IWitnetRandomness).interfaceId; uint256 public override latestRandomizeBlock; WitnetRequest public immutable override witnetRandomnessRequest; bytes32 internal immutable __witnetRandomnessRadHash; - bytes32 internal __witnetRandomnessSlaHash; + bytes32 internal __witnetRandomnessPackedSLA; mapping (uint256 => RandomizeData) internal __randomize_; struct RandomizeData { - address from; uint256 prevBlock; uint256 nextBlock; uint256 witnetQueryId; } - modifier onlyDelegateCalls override(Clonable, Upgradeable) { - require(address(this) != base(), "WitnetRandomnessProxiable: not a delegate call"); - _; - } - - function witnet() - virtual override (IWitnetRandomness, UsingWitnet) - public view returns (WitnetRequestBoard) - { - return UsingWitnet.witnet(); - } - - /// Include an address to specify the immutable WitnetRequestBoard entrypoint address. - /// @param _wrb The WitnetRequestBoard immutable entrypoint address. - constructor( - WitnetRequestBoard _wrb, - bytes32 _version - ) + constructor(address _operator, WitnetRequestBoard _wrb) UsingWitnet(_wrb) - WitnetUpgradableBase( - false, - _version, - "io.witnet.proxiable.randomness" - ) { - require( - address(_wrb) == address(0) - || address(_wrb).supportsInterface(type(WitnetRequestBoard).interfaceId), - "WitnetRandomnessProxiable: uncompliant request board" - ); - WitnetBytecodes _registry = witnet().registry(); + _transferOwnership(_operator); + assert(_wrb.specs() == type(IWitnetRequestBoard).interfaceId); WitnetRequestFactory _factory = witnet().factory(); + WitnetBytecodes _registry = witnet().registry(); { // Build own Witnet Randomness Request: bytes32[] memory _retrievals = new bytes32[](1); _retrievals[0] = _registry.verifyRadonRetrieval( - WitnetV2.DataRequestMethods.Rng, - "", // no schema - "", // no authority - "", // no path - "", // no query + Witnet.RadonDataRequestMethods.Rng, + "", // no url "", // no body new string[2][](0), // no headers hex"80" // no retrieval script ); - WitnetV2.RadonFilter[] memory _filters; - bytes32 _aggregator = _registry.verifyRadonReducer(WitnetV2.RadonReducer({ - opcode: WitnetV2.RadonReducerOpcodes.Mode, - filters: _filters, // no filters - script: hex"" // no aggregation script + Witnet.RadonFilter[] memory _filters; + bytes32 _aggregator = _registry.verifyRadonReducer(Witnet.RadonReducer({ + opcode: Witnet.RadonReducerOpcodes.Mode, + filters: _filters // no filters })); - bytes32 _tally = _registry.verifyRadonReducer(WitnetV2.RadonReducer({ - opcode: WitnetV2.RadonReducerOpcodes.ConcatenateAndHash, - filters: _filters, // no filters - script: hex"" // no aggregation script + bytes32 _tally = _registry.verifyRadonReducer(Witnet.RadonReducer({ + opcode: Witnet.RadonReducerOpcodes.ConcatenateAndHash, + filters: _filters // no filters })); WitnetRequestTemplate _template = WitnetRequestTemplate(_factory.buildRequestTemplate( _retrievals, _aggregator, _tally, - 0 + 32 // 256 bits of pure entropy ;-) )); witnetRandomnessRequest = WitnetRequest(_template.buildRequest(new string[][](_retrievals.length))); __witnetRandomnessRadHash = witnetRandomnessRequest.radHash(); } - __initializeWitnetRandomnessSlaHash(); + __initializeWitnetRandomnessSLA(); + } + + /// Deploys and returns the address of a minimal proxy clone that replicates contract + /// behaviour while using its own EVM storage. + /// @dev This function should always provide a new address, no matter how many times + /// @dev is actually called from the same `msg.sender`. + function clone() + virtual public + wasInitialized + returns (WitnetRandomness) + { + return __afterClone(_clone()); + } + + /// Deploys and returns the address of a minimal proxy clone that replicates contract + /// behaviour while using its own EVM storage. + /// @dev This function uses the CREATE2 opcode and a `_salt` to deterministically deploy + /// @dev the clone. Using the same `_salt` multiple time will revert, since + /// @dev no contract can be deployed more than once at the same address. + function cloneDeterministic(bytes32 _salt) + virtual public + wasInitialized + returns (WitnetRandomness) + { + return __afterClone(_cloneDeterministic(_salt)); } /// @notice Initializes a cloned instance. @@ -113,12 +110,12 @@ contract WitnetRandomnessProxiable initializer // => ensure a cloned instance can only be initialized once onlyDelegateCalls // => this method can only be called upon cloned instances { - _initialize(_initData); + __initialize(_initData); } /// =============================================================================================================== - /// --- 'WitnetRandomnessAdmin' implementation ------------------------------------------------------------------------- + /// --- 'IWitnetRandomnessAdmin' implementation ------------------------------------------------------------------- function owner() virtual override (IWitnetRandomnessAdmin, Ownable) @@ -151,45 +148,19 @@ contract WitnetRandomnessProxiable Ownable.transferOwnership(_newOwner); } - function settleWitnetRandomnessSLA(WitnetV2.RadonSLA memory _radonSLA) + function settleWitnetRandomnessSLA(WitnetV2.RadonSLA calldata sla) virtual override public onlyOwner - returns (bytes32 _radonSlaHash) + returns (bytes32) { - _radonSlaHash = witnet().registry().verifyRadonSLA(_radonSLA); - __witnetRandomnessSlaHash = _radonSlaHash; + require(sla.isValid(), "WitnetRandomness: invalid SLA"); + return __settleWitnetRandomnessSLA(sla); } + /// =============================================================================================================== - /// --- 'WitnetRandomness' implementation ------------------------------------------------------------------------- - - /// Deploys and returns the address of a minimal proxy clone that replicates contract - /// behaviour while using its own EVM storage. - /// @dev This function should always provide a new address, no matter how many times - /// @dev is actually called from the same `msg.sender`. - function clone() - virtual override - public - wasInitialized - returns (WitnetRandomness) - { - return _afterClone(_clone()); - } - - /// Deploys and returns the address of a minimal proxy clone that replicates contract - /// behaviour while using its own EVM storage. - /// @dev This function uses the CREATE2 opcode and a `_salt` to deterministically deploy - /// @dev the clone. Using the same `_salt` multiple time will revert, since - /// @dev no contract can be deployed more than once at the same address. - function cloneDeterministic(bytes32 _salt) - virtual override - public - wasInitialized - returns (WitnetRandomness) - { - return _afterClone(_cloneDeterministic(_salt)); - } + /// --- '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. @@ -198,13 +169,12 @@ contract WitnetRandomnessProxiable virtual override returns (uint256) { - return witnet().estimateReward(_gasPrice); + return __witnet.estimateBaseFee(_gasPrice, 35); } /// Retrieves data of a randomization request that got successfully posted to the WRB within a given block. /// @dev Returns zero values if no randomness request was actually posted within a given block. /// @param _block Block number whose randomness request is being queried for. - /// @return _from Address from which the latest randomness request was posted. /// @return _id Unique request identifier as provided by the WRB. /// @return _prevBlock Block number in which a randomness request got posted just before this one. 0 if none. /// @return _nextBlock Block number in which a randomness request got posted just after this one, 0 if none. @@ -212,7 +182,6 @@ contract WitnetRandomnessProxiable external view virtual override returns ( - address _from, uint256 _id, uint256 _prevBlock, uint256 _nextBlock @@ -220,7 +189,6 @@ contract WitnetRandomnessProxiable { RandomizeData storage _data = __randomize_[_block]; _id = _data.witnetQueryId; - _from = _data.from; _prevBlock = _data.prevBlock; _nextBlock = _data.nextBlock; } @@ -240,20 +208,20 @@ contract WitnetRandomnessProxiable virtual override returns (bytes32) { - if (__randomize_[_block].from == address(0)) { + if (__randomize_[_block].witnetQueryId == 0) { _block = getRandomnessNextBlock(_block); } uint256 _queryId = __randomize_[_block].witnetQueryId; - require(_queryId != 0, "WitnetRandomnessProxiable: not randomized"); - Witnet.ResultStatus _resultStatus = witnet().checkResultStatus(_queryId); - if (_resultStatus == Witnet.ResultStatus.Ready) { - return witnet().readResponseResult(_queryId).asBytes32(); - } else if (_resultStatus == Witnet.ResultStatus.Error) { + require(_queryId != 0, "WitnetRandomness: not randomized"); + WitnetV2.ResultStatus _resultStatus = witnet().getQueryResultStatus(_queryId); + if (_resultStatus == WitnetV2.ResultStatus.Ready) { + return witnet().getQueryResult(_queryId).asBytes32(); + } else if (_resultStatus == WitnetV2.ResultStatus.Error) { uint256 _nextRandomizeBlock = __randomize_[_block].nextBlock; - require(_nextRandomizeBlock != 0, "WitnetRandomnessProxiable: faulty randomize"); + require(_nextRandomizeBlock != 0, "WitnetRandomness: faulty randomize"); return getRandomnessAfter(_nextRandomizeBlock); } else { - revert("WitnetRandomnessProxiable: pending randomize"); + revert("WitnetRandomness: pending randomize"); } } @@ -265,7 +233,7 @@ contract WitnetRandomnessProxiable virtual override returns (uint256) { - return ((__randomize_[_block].from != address(0)) + return ((__randomize_[_block].witnetQueryId != 0) ? __randomize_[_block].nextBlock // start search from the latest block : _searchNextBlock(_block, latestRandomizeBlock) @@ -297,9 +265,10 @@ contract WitnetRandomnessProxiable returns (bool) { RandomizeData storage _data = __randomize_[_block]; + WitnetV2.QueryStatus _qstatus = witnet().getQueryStatus(_data.witnetQueryId); return ( _data.witnetQueryId != 0 - && witnet().getQueryStatus(_data.witnetQueryId) == Witnet.QueryStatus.Reported + && (_qstatus == WitnetV2.QueryStatus.Finalized) ); } @@ -354,22 +323,20 @@ contract WitnetRandomnessProxiable function randomize() external payable virtual override - returns (uint256 _usedFunds) + returns (uint256) { if (latestRandomizeBlock < block.number) { // Post the Witnet Randomness request: - uint _queryId; - (_queryId, _usedFunds) = _witnetPostRequest( + uint _queryId = __witnet.postRequest{value: msg.value}( __witnetRandomnessRadHash, - __witnetRandomnessSlaHash + __witnetRandomnessPackedSLA.toRadonSLA() ); // Keep Randomize data in storage: - RandomizeData storage _data = __randomize_[block.number]; - _data.witnetQueryId = _queryId; - _data.from = msg.sender; + RandomizeData storage __data = __randomize_[block.number]; + __data.witnetQueryId = _queryId; // Update block links: uint256 _prevBlock = latestRandomizeBlock; - _data.prevBlock = _prevBlock; + __data.prevBlock = _prevBlock; __randomize_[_prevBlock].nextBlock = block.number; latestRandomizeBlock = block.number; // Throw event: @@ -379,13 +346,10 @@ contract WitnetRandomnessProxiable _queryId, __witnetRandomnessRadHash ); - // Transfer back unused tx value: - if (_usedFunds < msg.value) { - payable(msg.sender).transfer(msg.value - _usedFunds); - } } else { return upgradeRandomizeFee(block.number); } + return msg.value; } /// Increases Witnet fee related to a pending-to-be-solved randomness request, as much as it @@ -396,15 +360,21 @@ contract WitnetRandomnessProxiable function upgradeRandomizeFee(uint256 _block) public payable virtual override - returns (uint256 _usedFunds) + returns (uint256) { RandomizeData storage _data = __randomize_[_block]; if (_data.witnetQueryId != 0) { - _usedFunds = _witnetUpgradeReward(_data.witnetQueryId); - } - if (_usedFunds < msg.value) { - payable(msg.sender).transfer(msg.value - _usedFunds); + __witnet.upgradeQueryReward{value: msg.value}(_data.witnetQueryId); } + return msg.value; + } + + /// @notice Result the WitnetRequestBoard address upon which this contract relies on. + function witnet() + virtual override (IWitnetRandomness, UsingWitnet) + public view returns (WitnetRequestBoard) + { + return UsingWitnet.witnet(); } /// @notice Returns SLA parameters that are being used every time there's a new randomness request. @@ -413,38 +383,7 @@ contract WitnetRandomnessProxiable external view returns (WitnetV2.RadonSLA memory) { - return witnet().registry().lookupRadonSLA(__witnetRandomnessSlaHash); - } - - - // ================================================================================================================ - // --- 'Upgradeable' extension ------------------------------------------------------------------------------------ - - /// Initialize storage-context when invoked as delegatecall. - /// @dev Must fail when trying to initialize same instance more than once. - function initialize(bytes memory) - public - virtual override - onlyDelegateCalls // => we don't want the logic base contract to be ever initialized - { - if ( - __proxiable().proxy == address(0) - && __proxiable().implementation == address(0) - ) { - // a proxy is being initilized for the first time ... - __proxiable().proxy = address(this); - _transferOwnership(msg.sender); - __initializeWitnetRandomnessSlaHash(); - } - else if (__proxiable().implementation == base()) { - revert("WitnetRandomnessProxiable: not upgradeable"); - } - __proxiable().implementation = base(); - } - - /// Tells whether provided address could eventually upgrade the contract. - function isUpgradableFrom(address) external pure override returns (bool) { - return false; + return __witnetRandomnessPackedSLA.toRadonSLA(); } @@ -464,38 +403,6 @@ contract WitnetRandomnessProxiable // ================================================================================================================ // --- INTERNAL FUNCTIONS ----------------------------------------------------------------------------------------- - /// @dev Common steps for both deterministic and non-deterministic cloning. - function _afterClone(address _instance) - virtual internal - returns (WitnetRandomness) - { - WitnetRandomnessProxiable(_instance).initializeClone(hex""); - return WitnetRandomness(_instance); - } - - /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. - /// @dev Must fail when trying to upgrade to same logic contract more than once. - function _initialize(bytes memory) - virtual internal - { - // settle ownership: - _transferOwnership(msg.sender); - // initialize default Witnet SLA parameters used for every randomness request; - __initializeWitnetRandomnessSlaHash(); - // make sure that this clone cannot ever get initialized as a proxy: - __proxiable().implementation = base(); - } - - function __initializeWitnetRandomnessSlaHash() virtual internal { - settleWitnetRandomnessSLA(WitnetV2.RadonSLA({ - numWitnesses: 5, - minConsensusPercentage: 51, - witnessReward: 10 ** 8, - witnessCollateral: 10 ** 9, - minerCommitRevealFee: 10 ** 7 - })); - } - /// @dev Returns index of the Most Significant Bit of the given number, applying De Bruijn O(1) algorithm. function _msbDeBruijn32(uint32 _v) internal pure @@ -536,4 +443,39 @@ contract WitnetRandomnessProxiable ); } + /// @dev Common steps for both deterministic and non-deterministic cloning. + function __afterClone(address _instance) + virtual internal + returns (WitnetRandomness) + { + WitnetRandomness(_instance).initializeClone(hex""); + return WitnetRandomness(_instance); + } + + /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. + /// @dev Must fail when trying to upgrade to same logic contract more than once. + function __initialize(bytes memory) + virtual internal + { + // settle ownership: + _transferOwnership(msg.sender); + // initialize default Witnet SLA parameters used for every randomness request; + __initializeWitnetRandomnessSLA(); + } + + function __initializeWitnetRandomnessSLA() virtual internal { + __settleWitnetRandomnessSLA(WitnetV2.RadonSLA({ + witnessingCommitteeSize: 10, + witnessingWitTotalReward: 10 ** 9 + })); + } + + function __settleWitnetRandomnessSLA(WitnetV2.RadonSLA memory sla) + internal + returns (bytes32 _packed) + { + _packed = sla.toBytes32(); + __witnetRandomnessPackedSLA = _packed; + } + } diff --git a/contracts/apps/WitnetRequestConsumer.sol b/contracts/apps/WitnetRequestConsumer.sol new file mode 100644 index 000000000..e93b66dfb --- /dev/null +++ b/contracts/apps/WitnetRequestConsumer.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./UsingWitnetRequest.sol"; +import "./WitnetConsumer.sol"; + +abstract contract WitnetRequestConsumer + is + UsingWitnetRequest, + WitnetConsumer +{ + using WitnetCBOR for WitnetCBOR.CBOR; + using WitnetCBOR for WitnetCBOR.CBOR[]; + + /// @param _witnetRequest Address of the WitnetRequest contract containing the actual data request. + /// @param _baseFeeOverheadPercentage Percentage over base fee to pay as on every data request. + /// @param _callbackGasLimit Maximum gas to be spent by the IWitnetConsumer's callback methods. + /// @param _defaultSLA Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain. + constructor( + WitnetRequest _witnetRequest, + uint16 _baseFeeOverheadPercentage, + uint96 _callbackGasLimit, + WitnetV2.RadonSLA memory _defaultSLA + ) + UsingWitnetRequest(_witnetRequest, _baseFeeOverheadPercentage, _defaultSLA) + WitnetConsumer(_callbackGasLimit) + {} + + function _witnetEstimateEvmReward() + virtual override(UsingWitnetRequest, WitnetConsumer) + internal view + returns (uint256) + { + return WitnetConsumer._witnetEstimateEvmReward(); + } + + function _witnetEstimateEvmReward(uint16) + virtual override(UsingWitnet, WitnetConsumer) + internal view + returns (uint256) + { + return WitnetConsumer._witnetEstimateEvmReward(); + } + +} diff --git a/contracts/apps/WitnetRequestTemplateConsumer.sol b/contracts/apps/WitnetRequestTemplateConsumer.sol new file mode 100644 index 000000000..dc00a9c11 --- /dev/null +++ b/contracts/apps/WitnetRequestTemplateConsumer.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./UsingWitnetRequestTemplate.sol"; +import "./WitnetConsumer.sol"; + +abstract contract WitnetRequestTemplateConsumer + is + UsingWitnetRequestTemplate, + WitnetConsumer +{ + using WitnetCBOR for WitnetCBOR.CBOR; + using WitnetCBOR for WitnetCBOR.CBOR[]; + + /// @param _witnetRequestTemplate Address of the WitnetRequestTemplate from which actual data requests will get built. + /// @param _baseFeeOverheadPercentage Percentage over base fee to pay as on every data request. + /// @param _callbackGasLimit Maximum gas to be spent by the IWitnetConsumer's callback methods. + /// @param _defaultSLA Default Security-Level Agreement parameters to be fulfilled by the Witnet blockchain. + constructor( + WitnetRequestTemplate _witnetRequestTemplate, + uint16 _baseFeeOverheadPercentage, + uint96 _callbackGasLimit, + WitnetV2.RadonSLA memory _defaultSLA + ) + UsingWitnetRequestTemplate(_witnetRequestTemplate, _baseFeeOverheadPercentage, _defaultSLA) + WitnetConsumer(_callbackGasLimit) + {} + + function _witnetEstimateEvmReward() + virtual override(UsingWitnetRequestTemplate, WitnetConsumer) + internal view + returns (uint256) + { + return WitnetConsumer._witnetEstimateEvmReward(__witnetResultMaxSize); + } + + function _witnetEstimateEvmReward(uint16) + virtual override(UsingWitnet, WitnetConsumer) + internal view + returns (uint256) + { + return WitnetConsumer._witnetEstimateEvmReward(); + } + +} diff --git a/contracts/core/WitnetDeployer.sol b/contracts/core/WitnetDeployer.sol new file mode 100644 index 000000000..ddcda5a87 --- /dev/null +++ b/contracts/core/WitnetDeployer.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.0 <0.9.0; + +import "./WitnetProxy.sol"; +import "../libs/Create3.sol"; + +/// @notice WitnetDeployer contract used both as CREATE2 (EIP-1014) factory for Witnet artifacts, +/// @notice and CREATE3 (EIP-3171) factory for Witnet proxies. +/// @author Guillermo Díaz + +contract WitnetDeployer { + + /// @notice Use given `_initCode` and `_salt` to deploy a contract into a deterministic address. + /// @dev The address of deployed address will be determined by both the `_initCode` and the `_salt`, but not the address + /// @dev nor the nonce of the caller (i.e. see EIP-1014). + /// @param _initCode Creation code, including construction logic and input parameters. + /// @param _salt Arbitrary value to modify resulting address. + /// @return _deployed Just deployed contract address. + function deploy(bytes memory _initCode, bytes32 _salt) + external + returns (address _deployed) + { + _deployed = determineAddr(_initCode, _salt); + if (_deployed.code.length == 0) { + assembly { + _deployed := create2(0, add(_initCode, 0x20), mload(_initCode), _salt) + } + require(_deployed != address(0), "WitnetDeployer: deployment failed"); + } + } + + /// @notice Determine counter-factual address of the contract that would be deployed by the given `_initCode` and a `_salt`. + /// @param _initCode Creation code, including construction logic and input parameters. + /// @param _salt Arbitrary value to modify resulting address. + /// @return Deterministic contract address. + function determineAddr(bytes memory _initCode, bytes32 _salt) + public view + returns (address) + { + return address( + uint160(uint(keccak256( + abi.encodePacked( + bytes1(0xff), + address(this), + _salt, + keccak256(_initCode) + ) + ))) + ); + } + + function determineProxyAddr(bytes32 _salt) + public view + returns (address) + { + return Create3.determineAddr(_salt); + } + + function proxify(bytes32 _proxySalt, address _firstImplementation, bytes memory _initData) + external + returns (WitnetProxy) + { + address _proxyAddr = determineProxyAddr(_proxySalt); + if (_proxyAddr.code.length == 0) { + // deploy the WitnetProxy + Create3.deploy(_proxySalt, type(WitnetProxy).creationCode); + // settle first implementation address, + WitnetProxy(payable(_proxyAddr)).upgradeTo( + _firstImplementation, + // and initialize it, providing + abi.encode( + // the owner (i.e. the caller of this function) + msg.sender, + // and some (optional) initialization data + _initData + ) + ); + return WitnetProxy(payable(_proxyAddr)); + } else { + revert("WitnetDeployer: already proxified"); + } + } + +} \ No newline at end of file diff --git a/contracts/impls/WitnetProxy.sol b/contracts/core/WitnetProxy.sol similarity index 87% rename from contracts/impls/WitnetProxy.sol rename to contracts/core/WitnetProxy.sol index d640592a8..fb5249e1d 100644 --- a/contracts/impls/WitnetProxy.sol +++ b/contracts/core/WitnetProxy.sol @@ -6,7 +6,7 @@ pragma experimental ABIEncoderV2; import "../patterns/Upgradeable.sol"; /// @title WitnetProxy: upgradable delegate-proxy contract. -/// @author The Witnet Foundation. +/// @author Guillermo Díaz contract WitnetProxy { /// Event emitted every time the implementation gets updated. @@ -75,7 +75,7 @@ contract WitnetProxy { msg.sender ) ); - require(_wasCalled, "WitnetProxy: not compliant"); + require(_wasCalled, "WitnetProxy: uncompliant implementation"); require(abi.decode(_result, (bool)), "WitnetProxy: not authorized"); require( Upgradeable(_oldImplementation).proxiableUUID() == Upgradeable(_newImplementation).proxiableUUID(), @@ -84,16 +84,26 @@ contract WitnetProxy { } // Initialize new implementation within proxy-context storage: - (bool _wasInitialized,) = _newImplementation.delegatecall( + (bool _wasInitialized, bytes memory _returnData) = _newImplementation.delegatecall( abi.encodeWithSignature( "initialize(bytes)", _initData ) ); - require(_wasInitialized, "WitnetProxy: unable to initialize"); + if (!_wasInitialized) { + if (_returnData.length < 68) { + revert("WitnetProxy: initialization failed"); + } else { + assembly { + _returnData := add(_returnData, 0x04) + } + revert(abi.decode(_returnData, (string))); + } + } // If all checks and initialization pass, update implementation address: __proxySlot().implementation = _newImplementation; + emit Upgraded(_newImplementation); // Asserts new implementation complies w/ minimal implementation of Upgradeable interface: @@ -101,7 +111,7 @@ contract WitnetProxy { return _isUpgradable; } catch { - revert ("WitnetProxy: not compliant"); + revert ("WitnetProxy: uncompliant implementation"); } } diff --git a/contracts/impls/WitnetUpgradableBase.sol b/contracts/core/WitnetUpgradableBase.sol similarity index 78% rename from contracts/impls/WitnetUpgradableBase.sol rename to contracts/core/WitnetUpgradableBase.sol index 5d6bc17a6..57b316272 100644 --- a/contracts/impls/WitnetUpgradableBase.sol +++ b/contracts/core/WitnetUpgradableBase.sol @@ -4,7 +4,6 @@ pragma solidity >=0.8.0 <0.9.0; -import "../patterns/ERC165.sol"; import "../patterns/Ownable2Step.sol"; import "../patterns/ReentrancyGuard.sol"; import "../patterns/Upgradeable.sol"; @@ -12,20 +11,16 @@ import "../patterns/Upgradeable.sol"; import "./WitnetProxy.sol"; /// @title Witnet Request Board base contract, with an Upgradeable (and Destructible) touch. -/// @author The Witnet Foundation. +/// @author Guillermo Díaz abstract contract WitnetUpgradableBase is - ERC165, Ownable2Step, Upgradeable, ReentrancyGuard { bytes32 internal immutable _WITNET_UPGRADABLE_VERSION; - error AlreadyUpgraded(address implementation); - error NotCompliant(bytes4 interfaceId); - error NotUpgradable(address self); - error OnlyOwner(address owner); + address public immutable deployer = msg.sender; constructor( bool _upgradable, @@ -43,22 +38,7 @@ abstract contract WitnetUpgradableBase revert("WitnetUpgradableBase: not implemented"); } - - // ================================================================================================================ - // --- Overrides IERC165 interface -------------------------------------------------------------------------------- - - /// @dev See {IERC165-supportsInterface}. - function supportsInterface(bytes4 _interfaceId) - public view - virtual override - returns (bool) - { - return _interfaceId == type(Ownable2Step).interfaceId - || _interfaceId == type(Upgradeable).interfaceId - || super.supportsInterface(_interfaceId); - } - - + // ================================================================================================================ // --- Overrides 'Proxiable' -------------------------------------------------------------------------------------- diff --git a/contracts/impls/core/customs/WitnetBytecodesNoSha256.sol b/contracts/core/customs/WitnetBytecodesNoSha256.sol similarity index 74% rename from contracts/impls/core/customs/WitnetBytecodesNoSha256.sol rename to contracts/core/customs/WitnetBytecodesNoSha256.sol index 0d50f2621..684f27268 100644 --- a/contracts/impls/core/customs/WitnetBytecodesNoSha256.sol +++ b/contracts/core/customs/WitnetBytecodesNoSha256.sol @@ -3,14 +3,11 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../WitnetBytecodesDefault.sol"; +import "../defaults/WitnetBytecodesDefault.sol"; contract WitnetBytecodesNoSha256 is WitnetBytecodesDefault { - constructor( - bool _upgradable, - bytes32 _versionTag - ) + constructor(bool _upgradable, bytes32 _versionTag) WitnetBytecodesDefault(_upgradable, _versionTag) {} diff --git a/contracts/core/customs/WitnetRequestBoardTrustableOvm2.sol b/contracts/core/customs/WitnetRequestBoardTrustableOvm2.sol new file mode 100644 index 000000000..85feec5dc --- /dev/null +++ b/contracts/core/customs/WitnetRequestBoardTrustableOvm2.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT + +/* solhint-disable var-name-mixedcase */ + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../defaults/WitnetRequestBoardTrustableDefault.sol"; + +// solhint-disable-next-line +interface OVM_GasPriceOracle { + function getL1Fee(bytes calldata _data) external view returns (uint256); +} + +/// @title Witnet Request Board "trustable" implementation contract. +/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. +/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. +/// The result of the requests will be posted back to this contract by the bridge nodes too. +/// @author The Witnet Foundation +contract WitnetRequestBoardTrustableOvm2 + is + WitnetRequestBoardTrustableDefault +{ + OVM_GasPriceOracle immutable public gasPriceOracleL1; + + constructor( + WitnetRequestFactory _factory, + WitnetBytecodes _registry, + bool _upgradable, + bytes32 _versionTag, + uint256 _reportResultGasBase, + uint256 _reportResultWithCallbackGasBase, + uint256 _reportResultWithCallbackRevertGasBase, + uint256 _sstoreFromZeroGas + ) + WitnetRequestBoardTrustableDefault( + _factory, + _registry, + _upgradable, + _versionTag, + _reportResultGasBase, + _reportResultWithCallbackGasBase, + _reportResultWithCallbackRevertGasBase, + _sstoreFromZeroGas + ) + { + gasPriceOracleL1 = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); + } + + + // ================================================================================================================ + // --- Overrides 'IWitnetRequestBoard' ---------------------------------------------------------------------------- + + /// @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) + public view + virtual override + returns (uint256) + { + return WitnetRequestBoardTrustableDefault.estimateBaseFee(_gasPrice, _resultMaxSize) + ( + _gasPrice * gasPriceOracleL1.getL1Fee( + hex"c8f5cdd500000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000225820ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ) + ); + } + + /// @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, uint96 _callbackGasLimit) + public view + virtual override + returns (uint256) + { + return WitnetRequestBoardTrustableDefault.estimateBaseFeeWithCallback( + _gasPrice, + _callbackGasLimit + ) + ( + _gasPrice * gasPriceOracleL1.getL1Fee( + hex"c8f5cdd500000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000225820ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ) + ); + } +} diff --git a/contracts/impls/core/customs/WitnetRequestBoardTrustableReef.sol b/contracts/core/customs/WitnetRequestBoardTrustableReef.sol similarity index 51% rename from contracts/impls/core/customs/WitnetRequestBoardTrustableReef.sol rename to contracts/core/customs/WitnetRequestBoardTrustableReef.sol index f99ec4628..682c7f500 100644 --- a/contracts/impls/core/customs/WitnetRequestBoardTrustableReef.sol +++ b/contracts/core/customs/WitnetRequestBoardTrustableReef.sol @@ -6,7 +6,7 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; // Inherits from: -import "../WitnetRequestBoardTrustableDefault.sol"; +import "../defaults/WitnetRequestBoardTrustableDefault.sol"; /// @title Witnet Request Board OVM-compatible (Optimism) "trustable" implementation. /// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. @@ -19,31 +19,51 @@ contract WitnetRequestBoardTrustableReef { constructor( WitnetRequestFactory _factory, + WitnetBytecodes _registry, bool _upgradable, bytes32 _versionTag, - uint256 _reportResultGasLimit + uint256 _reportResultGasBase, + uint256 _reportResultWithCallbackGasBase, + uint256 _reportResultWithCallbackRevertGasBase, + uint256 _sstoreFromZeroGas ) WitnetRequestBoardTrustableDefault( _factory, + _registry, _upgradable, _versionTag, - _reportResultGasLimit + _reportResultGasBase, + _reportResultWithCallbackGasBase, + _reportResultWithCallbackRevertGasBase, + _sstoreFromZeroGas ) {} // ================================================================================================================ - // --- Overrides implementation of 'IWitnetRequestBoardView' ------------------------------------------------------ + // --- Overrides 'IWitnetRequestBoard' ---------------------------------------------------------------------------- - /// @dev Estimate the minimal amount of reward we need to insert for a given gas price. - /// @return The minimal reward to be included for the given gas price. - function estimateReward(uint256) + /// @notice Estimate the minimum reward required for posting a data request. + /// @dev Underestimates if the size of returned data is greater than `_resultMaxSize`. + /// @param _resultMaxSize Maximum expected size of returned data (in bytes). + function estimateBaseFee(uint256, uint16 _resultMaxSize) public view virtual override returns (uint256) { - return _ESTIMATED_REPORT_RESULT_GAS; + return WitnetRequestBoardTrustableDefault.estimateBaseFee(1, _resultMaxSize); } + /// @notice Estimate the minimum reward required for posting a data request with a callback. + /// @param _callbackGasLimit Maximum gas to be spent when reporting the data request result. + function estimateBaseFeeWithCallback(uint256, uint96 _callbackGasLimit) + public view + virtual override + returns (uint256) + { + return WitnetRequestBoardTrustableDefault.estimateBaseFeeWithCallback(1, _callbackGasLimit); + } + + // ================================================================================================================ // --- Overrides 'Payable' ---------------------------------------------------------------------------------------- diff --git a/contracts/impls/core/customs/WitnetRequestFactoryCfxCore.sol b/contracts/core/customs/WitnetRequestFactoryCfxCore.sol similarity index 78% rename from contracts/impls/core/customs/WitnetRequestFactoryCfxCore.sol rename to contracts/core/customs/WitnetRequestFactoryCfxCore.sol index 87090fb62..fbb8574b1 100644 --- a/contracts/impls/core/customs/WitnetRequestFactoryCfxCore.sol +++ b/contracts/core/customs/WitnetRequestFactoryCfxCore.sol @@ -3,15 +3,16 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../WitnetRequestFactoryDefault.sol"; +import "../defaults/WitnetRequestFactoryDefault.sol"; contract WitnetRequestFactoryCfxCore is WitnetRequestFactoryDefault { constructor( + WitnetRequestBoard _witnet, WitnetBytecodes _registry, bool _upgradable, bytes32 _versionTag ) - WitnetRequestFactoryDefault(_registry, _upgradable, _versionTag) + WitnetRequestFactoryDefault(_witnet, _registry, _upgradable, _versionTag) {} function _cloneDeterministic(bytes32 _salt) diff --git a/contracts/impls/core/WitnetBytecodesDefault.sol b/contracts/core/defaults/WitnetBytecodesDefault.sol similarity index 58% rename from contracts/impls/core/WitnetBytecodesDefault.sol rename to contracts/core/defaults/WitnetBytecodesDefault.sol index d4a2c93f9..636a5fe66 100644 --- a/contracts/impls/core/WitnetBytecodesDefault.sol +++ b/contracts/core/defaults/WitnetBytecodesDefault.sol @@ -2,12 +2,9 @@ pragma solidity >=0.8.4 <0.9.0; -import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; - import "../WitnetUpgradableBase.sol"; import "../../WitnetBytecodes.sol"; import "../../data/WitnetBytecodesData.sol"; - import "../../libs/WitnetEncodingLib.sol"; /// @title Witnet Request Board EVM-default implementation contract. @@ -20,23 +17,20 @@ contract WitnetBytecodesDefault WitnetBytecodes, WitnetBytecodesData, WitnetUpgradableBase -{ - using ERC165Checker for address; - +{ using Witnet for bytes; using Witnet for string; - using WitnetEncodingLib for WitnetV2.DataRequestMethods; - using WitnetEncodingLib for WitnetV2.RadonRetrieval; - using WitnetEncodingLib for WitnetV2.RadonRetrieval[]; - using WitnetEncodingLib for WitnetV2.RadonReducer; - using WitnetEncodingLib for WitnetV2.RadonSLA; - using WitnetEncodingLib for WitnetV2.RadonDataTypes; + using WitnetEncodingLib for Witnet.RadonDataRequestMethods; + using WitnetEncodingLib for Witnet.RadonRetrieval; + using WitnetEncodingLib for Witnet.RadonRetrieval[]; + using WitnetEncodingLib for Witnet.RadonReducer; + using WitnetEncodingLib for Witnet.RadonSLA; + using WitnetEncodingLib for Witnet.RadonDataTypes; + + bytes4 public immutable override specs = type(IWitnetBytecodes).interfaceId; - constructor( - bool _upgradable, - bytes32 _versionTag - ) + constructor(bool _upgradable, bytes32 _versionTag) WitnetUpgradableBase( _upgradable, _versionTag, @@ -48,20 +42,6 @@ contract WitnetBytecodesDefault revert("WitnetBytecodesDefault: no transfers"); } - - // ================================================================================================================ - // --- Overrides IERC165 interface -------------------------------------------------------------------------------- - - /// @dev See {IERC165-supportsInterface}. - function supportsInterface(bytes4 _interfaceId) - public view - virtual override - returns (bool) - { - return _interfaceId == type(WitnetBytecodes).interfaceId - || super.supportsInterface(_interfaceId); - } - // ================================================================================================================ // --- Overrides 'Ownable2Step' ----------------------------------------------------------------------------------- @@ -115,32 +95,32 @@ contract WitnetBytecodesDefault /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. /// @dev Must fail when trying to upgrade to same logic contract more than once. - function initialize(bytes memory) + function initialize(bytes memory _initData) public override { address _owner = __bytecodes().owner; if (_owner == address(0)) { - // set owner if none set yet - _owner = msg.sender; + // set owner from the one specified in _initData + _owner = abi.decode(_initData, (address)); __bytecodes().owner = _owner; } else { // only owner can initialize: if (msg.sender != _owner) { - revert WitnetUpgradableBase.OnlyOwner(_owner); + revert("WitnetBytecodesDefault: not the owner"); } } if (__bytecodes().base != address(0)) { // current implementation cannot be initialized more than once: if(__bytecodes().base == base()) { - revert WitnetUpgradableBase.AlreadyUpgraded(base()); + revert("WitnetBytecodesDefault: already initialized"); } } __bytecodes().base = base(); emit Upgraded( - msg.sender, + _owner, base(), codehash(), version() @@ -169,76 +149,9 @@ contract WitnetBytecodesDefault return __database().radsBytecode[_radHash]; } - function bytecodeOf(bytes32 _radHash, bytes32 _slaHash) - external view - returns (bytes memory) - { - WitnetV2.RadonSLA storage __sla = __database().slas[_slaHash]; - if (__sla.numWitnesses == 0) { - revert IWitnetBytecodesErrors.UnknownRadonSLA(_slaHash); - } - bytes memory _radBytecode = bytecodeOf(_radHash); - return abi.encodePacked( - WitnetEncodingLib.encode(uint64(_radBytecode.length), 0x0a), - _radBytecode, - __database().slasBytecode[_slaHash] - ); - } - - function hashOf( - bytes32[] calldata _retrievalsIds, - bytes32 _aggregatorId, - bytes32 _tallyId, - uint16 _resultMaxSize, - string[][] calldata _args - ) - external pure - virtual override - returns (bytes32) - { - return keccak256(abi.encode( - _retrievalsIds, - _aggregatorId, - _tallyId, - _resultMaxSize, - _args - )); - } - - function hashOf(bytes32 _radHash, bytes32 _slaHash) - public pure - virtual override - returns (bytes32) - { - return sha256(abi.encode( - _radHash, - _slaHash - )); - } - - function hashWeightWitsOf( - bytes32 _radHash, - bytes32 _slaHash - ) - external view - virtual override - returns (bytes32, uint32, uint256) - { - WitnetV2.RadonSLA storage __sla = __database().slas[_slaHash]; - { - uint _numWitnesses = __sla.numWitnesses; - uint _weight = __database().radsBytecode[_radHash].length; - uint _witnessWits = __sla.witnessReward + 2 * __sla.minerCommitRevealFee; - return ( - hashOf(_radHash, _slaHash), - uint32(_weight - + _numWitnesses * 636 - // + (8 + 2 + 8 + 4 + 8) - + 100 - ), - _numWitnesses * _witnessWits - ); - } + function hashOf(bytes calldata _radBytecode) external pure override returns (bytes32) { + // todo: validate correctness of _radBytecode + return _witnetHash(_radBytecode); } function lookupDataProvider(uint256 _index) @@ -268,7 +181,7 @@ contract WitnetBytecodesDefault external view returns (bytes32[] memory _endpoints) { - WitnetV2.DataProvider storage __provider = __database().providers[_index]; + DataProvider storage __provider = __database().providers[_index]; uint _totalEndpoints = __provider.totalEndpoints; if (_offset < _totalEndpoints){ if (_offset + _length > _totalEndpoints) { @@ -284,11 +197,11 @@ contract WitnetBytecodesDefault function lookupRadonRetrieval(bytes32 _hash) external view override - returns (WitnetV2.RadonRetrieval memory _source) + returns (Witnet.RadonRetrieval memory _source) { _source = __database().retrievals[_hash]; - if (_source.method == WitnetV2.DataRequestMethods.Unknown) { - revert IWitnetBytecodesErrors.UnknownRadonRetrieval(_hash); + if (_source.method == Witnet.RadonDataRequestMethods.Unknown) { + revert UnknownRadonRetrieval(_hash); } } @@ -297,8 +210,8 @@ contract WitnetBytecodesDefault override returns (uint8) { - if (__database().retrievals[_hash].method == WitnetV2.DataRequestMethods.Unknown) { - revert IWitnetBytecodesErrors.UnknownRadonRetrieval(_hash); + if (__database().retrievals[_hash].method == Witnet.RadonDataRequestMethods.Unknown) { + revert UnknownRadonRetrieval(_hash); } return __database().retrievals[_hash].argsCount; } @@ -306,10 +219,10 @@ contract WitnetBytecodesDefault function lookupRadonRetrievalResultDataType(bytes32 _hash) external view override - returns (WitnetV2.RadonDataTypes) + returns (Witnet.RadonDataTypes) { - if (__database().retrievals[_hash].method == WitnetV2.DataRequestMethods.Unknown) { - revert IWitnetBytecodesErrors.UnknownRadonRetrieval(_hash); + if (__database().retrievals[_hash].method == Witnet.RadonDataRequestMethods.Unknown) { + revert UnknownRadonRetrieval(_hash); } return __database().retrievals[_hash].resultDataType; } @@ -317,18 +230,18 @@ contract WitnetBytecodesDefault function lookupRadonReducer(bytes32 _hash) external view override - returns (WitnetV2.RadonReducer memory _reducer) + returns (Witnet.RadonReducer memory _reducer) { _reducer = __database().reducers[_hash]; if (uint8(_reducer.opcode) == 0) { - revert IWitnetBytecodesErrors.UnknownRadonReducer(_hash); + revert UnknownRadonReducer(_hash); } } function lookupRadonRequestAggregator(bytes32 _radHash) external view override - returns (WitnetV2.RadonReducer memory) + returns (Witnet.RadonReducer memory) { return __database().reducers[ __requests(_radHash).aggregator @@ -338,7 +251,7 @@ contract WitnetBytecodesDefault function lookupRadonRequestResultDataType(bytes32 _radHash) external view override - returns (WitnetV2.RadonDataTypes) + returns (Witnet.RadonDataTypes) { return __requests(_radHash).resultDataType; } @@ -346,9 +259,9 @@ contract WitnetBytecodesDefault function lookupRadonRequestResultMaxSize(bytes32 _radHash) external view override - returns (uint256) + returns (uint16) { - return __requests(_radHash).resultMaxSize; + return uint16(__requests(_radHash).resultMaxSize); } function lookupRadonRequestSources(bytes32 _radHash) @@ -370,35 +283,40 @@ contract WitnetBytecodesDefault function lookupRadonRequestTally(bytes32 _radHash) external view override - returns (WitnetV2.RadonReducer memory) + returns (Witnet.RadonReducer memory) { return __database().reducers[ __requests(_radHash).tally ]; } - function lookupRadonSLA(bytes32 _slaHash) + function lookupRadonRAD(bytes32 _radHash) external view override - returns (WitnetV2.RadonSLA memory sla) - { - sla = __database().slas[_slaHash]; - if (sla.numWitnesses == 0) { - revert IWitnetBytecodesErrors.UnknownRadonSLA(_slaHash); - } - } - - function lookupRadonSLAReward(bytes32 _slaHash) - public view - override - returns (uint) - { - WitnetV2.RadonSLA storage __sla = __database().slas[_slaHash]; - return __sla.numWitnesses * __sla.witnessReward; - } + returns (Witnet.RadonRAD memory rad) + { + DataRequest storage __request = __requests(_radHash); + rad.retrieve = new Witnet.RadonRetrieval[](__request.retrievals.length); + for (uint _ix = 0; _ix < rad.retrieve.length; _ix ++) { + rad.retrieve[_ix] = __database().retrievals[__request.retrievals[_ix]]; + } + rad.aggregate = __database().reducers[__request.aggregator]; + rad.tally = __database().reducers[__request.tally]; + } + + // function lookupRadonSLA(bytes32 _slaHash) + // external view + // override + // returns (Witnet.RadonSLA memory sla) + // { + // sla = __database().slas[_slaHash]; + // if (sla.numWitnesses == 0) { + // revert UnknownRadonSLA(_slaHash); + // } + // } function verifyRadonRetrieval( - WitnetV2.DataRequestMethods _requestMethod, + Witnet.RadonDataRequestMethods _requestMethod, string calldata _requestURL, string calldata _requestBody, string[2][] memory _requestHeaders, @@ -407,85 +325,25 @@ contract WitnetBytecodesDefault public virtual override returns (bytes32 hash) - { - // validate data source params - hash = _requestMethod.validate(_requestURL, _requestBody, _requestHeaders, _requestRadonScript); - - // should it be a new data source: - if ( - __database().retrievals[hash].method == WitnetV2.DataRequestMethods.Unknown - ) { - // compose data source and save it in storage: - __database().retrievals[hash] = WitnetV2.RadonRetrieval({ - argsCount: - WitnetBuffer.argsCountOf( - abi.encode( - _requestURL, bytes(" "), - _requestBody, bytes(" "), - _requestHeaders, bytes(" "), - _requestRadonScript - ) - ), - - method: - _requestMethod, - - resultDataType: - WitnetEncodingLib.verifyRadonScriptResultDataType(_requestRadonScript), - - url: - _requestURL, - - body: - _requestBody, - - headers: - _requestHeaders, - - script: - _requestRadonScript - }); - emit NewRadonRetrievalHash(hash); - } - } - - function verifyRadonRetrieval( - WitnetV2.DataRequestMethods _requestMethod, - string memory _requestSchema, - string memory _requestAuthority, - string memory _requestPath, - string memory _requestQuery, - string memory _requestBody, - string[2][] memory _requestHeaders, - bytes calldata _requestRadonScript - ) - external - virtual override - returns (bytes32 hash) { // validate data source params hash = _requestMethod.validate( - _requestSchema, - _requestAuthority, - _requestPath, - _requestQuery, - _requestBody, - _requestHeaders, + _requestURL, + _requestBody, + _requestHeaders, _requestRadonScript ); // should it be a new data source: if ( - __database().retrievals[hash].method == WitnetV2.DataRequestMethods.Unknown + __database().retrievals[hash].method == Witnet.RadonDataRequestMethods.Unknown ) { // compose data source and save it in storage: - __database().retrievals[hash] = WitnetV2.RadonRetrieval({ + __database().retrievals[hash] = Witnet.RadonRetrieval({ argsCount: WitnetBuffer.argsCountOf( abi.encode( - _requestAuthority, bytes(" "), - _requestPath, bytes(" "), - _requestQuery, bytes(" "), + _requestURL, bytes(" "), _requestBody, bytes(" "), _requestHeaders, bytes(" "), _requestRadonScript @@ -499,16 +357,7 @@ contract WitnetBytecodesDefault WitnetEncodingLib.verifyRadonScriptResultDataType(_requestRadonScript), url: - string(abi.encodePacked( - _requestSchema, - _requestAuthority, - bytes(_requestPath).length > 0 - ? abi.encodePacked(bytes("/"), _requestPath) - : bytes(""), - bytes(_requestQuery).length > 0 - ? abi.encodePacked("?", _requestQuery) - : bytes("") - )), + _requestURL, body: _requestBody, @@ -519,16 +368,15 @@ contract WitnetBytecodesDefault script: _requestRadonScript }); - __pushDataProviderSource(_requestAuthority, hash); emit NewRadonRetrievalHash(hash); } } - function verifyRadonReducer(WitnetV2.RadonReducer memory _reducer) + function verifyRadonReducer(Witnet.RadonReducer memory _reducer) external returns (bytes32 hash) { hash = keccak256(abi.encode(_reducer)); - WitnetV2.RadonReducer storage __reducer = __database().reducers[hash]; + Witnet.RadonReducer storage __reducer = __database().reducers[hash]; if ( uint8(__reducer.opcode) == 0 && __reducer.filters.length == 0 @@ -565,46 +413,32 @@ contract WitnetBytecodesDefault // Check that at least one source is provided; if (_retrievalsIds.length == 0) { - revert WitnetV2.RadonRequestNoSources(); + revert("WitnetBytecodesDefault: no retrievals"); } // Check that number of args arrays matches the number of sources: if ( _retrievalsIds.length != _args.length) { - revert WitnetV2.RadonRequestSourcesArgsMismatch( - _retrievalsIds.length, - _args.length - ); + revert("WitnetBytecodesDefault: args mismatch"); } // Check sources and tally reducers: - WitnetV2.RadonReducer memory _aggregator = __database().reducers[_aggregatorId]; - WitnetV2.RadonReducer memory _tally = __database().reducers[_tallyId]; - if (_tally.script.length > 0) { - revert WitnetV2.UnsupportedRadonTallyScript(_tallyId); - } + Witnet.RadonReducer memory _aggregator = __database().reducers[_aggregatorId]; + Witnet.RadonReducer memory _tally = __database().reducers[_tallyId]; // Check result type consistency among all sources: - WitnetV2.RadonDataTypes _resultDataType; - WitnetV2.RadonRetrieval[] memory _retrievals = new WitnetV2.RadonRetrieval[](_retrievalsIds.length); + Witnet.RadonDataTypes _resultDataType; + Witnet.RadonRetrieval[] memory _retrievals = new Witnet.RadonRetrieval[](_retrievalsIds.length); for (uint _ix = 0; _ix < _retrievals.length; _ix ++) { _retrievals[_ix] = __database().retrievals[_retrievalsIds[_ix]]; // Check all sources return same Radon data type: if (_ix == 0) { _resultDataType = _retrievals[0].resultDataType; } else if (_retrievals[_ix].resultDataType != _resultDataType) { - revert WitnetV2.RadonRequestResultsMismatch( - _ix, - uint8(_retrievals[_ix].resultDataType), - uint8(_resultDataType) - ); + revert("WitnetBytecodesDefault: mismatching retrievals"); } // check enough args are provided for each source if (_args[_ix].length < uint(_retrievals[_ix].argsCount)) { - revert WitnetV2.RadonRequestMissingArgs( - _ix, - _retrievals[_ix].argsCount, - _args[_ix].length - ); + revert("WitnetBytecodesDefault: missing args"); } } @@ -619,14 +453,14 @@ contract WitnetBytecodesDefault _resultMaxSize ); if (_bytecode.length > 65535) { - revert WitnetV2.RadonRequestTooHeavy(_bytecode, _bytecode.length); + revert("WitnetBytecodesDefault: too heavy request"); } // Calculate radhash and add request metadata and rad bytecode to storage: _radHash = _witnetHash(_bytecode); __database().rads[hash] = _radHash; __database().radsBytecode[_radHash] = _bytecode; - __database().requests[_radHash] = RadonRequest({ + __database().requests[_radHash] = DataRequest({ aggregator: _aggregatorId, args: _args, radHash: _radHash, @@ -639,26 +473,6 @@ contract WitnetBytecodesDefault } } - function verifyRadonSLA(WitnetV2.RadonSLA calldata _sla) - external - virtual override - returns (bytes32 _slaHash) - { - // Validate SLA params: - _sla.validate(); - - // Build RadonSLA bytecode: - bytes memory _bytecode = _sla.encode(); - - // Calculate hash and add to storage if new: - _slaHash = _witnetHash(_bytecode); - if (__database().slas[_slaHash].numWitnesses == 0) { - __database().slas[_slaHash] = _sla; - __database().slasBytecode[_slaHash] = _bytecode; - emit NewSlaHash(_slaHash); - } - } - function totalDataProviders() external view override @@ -697,8 +511,8 @@ contract WitnetBytecodesDefault } function __pushRadonReducerFilters( - WitnetV2.RadonReducer storage __reducer, - WitnetV2.RadonFilter[] memory _filters + Witnet.RadonReducer storage __reducer, + Witnet.RadonFilter[] memory _filters ) internal virtual diff --git a/contracts/core/defaults/WitnetRequestBoardTrustableBase.sol b/contracts/core/defaults/WitnetRequestBoardTrustableBase.sol new file mode 100644 index 000000000..f8056eb5e --- /dev/null +++ b/contracts/core/defaults/WitnetRequestBoardTrustableBase.sol @@ -0,0 +1,1004 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../WitnetUpgradableBase.sol"; +import "../../WitnetRequestBoard.sol"; +import "../../WitnetRequestFactory.sol"; + +import "../../data/WitnetRequestBoardDataACLs.sol"; +import "../../interfaces/IWitnetRequest.sol"; +import "../../interfaces/IWitnetRequestBoardAdminACLs.sol"; +import "../../interfaces/V2/IWitnetRequestBoardReporter.sol"; +import "../../interfaces/V2/IWitnetConsumer.sol"; +import "../../libs/WitnetErrorsLib.sol"; +import "../../patterns/Payable.sol"; + +/// @title Witnet Request Board "trustable" base implementation contract. +/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. +/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. +/// The result of the requests will be posted back to this contract by the bridge nodes too. +/// @author The Witnet Foundation +abstract contract WitnetRequestBoardTrustableBase + is + WitnetUpgradableBase, + WitnetRequestBoard, + WitnetRequestBoardDataACLs, + IWitnetRequestBoardReporter, + IWitnetRequestBoardAdminACLs, + Payable +{ + using Witnet for bytes; + using Witnet for Witnet.Result; + using WitnetCBOR for WitnetCBOR.CBOR; + using WitnetV2 for WitnetV2.RadonSLA; + using WitnetV2 for WitnetV2.Request; + using WitnetV2 for WitnetV2.Response; + + bytes4 public immutable override specs = type(IWitnetRequestBoard).interfaceId; + WitnetBytecodes immutable public override registry; + + WitnetRequestFactory immutable private __factory; + + modifier checkCallbackRecipient(address _addr, uint96 _callbackGasLimit) { + require( + _addr.code.length > 0 && IWitnetConsumer(_addr).reportableFrom(address(this)) && _callbackGasLimit > 0, + "WitnetRequestBoardTrustableBase: invalid callback" + ); _; + } + + modifier checkReward(uint256 _baseFee) { + require( + _getMsgValue() >= _baseFee, + "WitnetRequestBoardTrustableBase: insufficient reward" + ); _; + } + + modifier checkSLA(WitnetV2.RadonSLA calldata sla) { + require( + WitnetV2.isValid(sla), + "WitnetRequestBoardTrustableBase: invalid SLA" + ); _; + } + + constructor( + WitnetRequestFactory _factory, + WitnetBytecodes _registry, + bool _upgradable, + bytes32 _versionTag, + address _currency + ) + Payable(_currency) + WitnetUpgradableBase( + _upgradable, + _versionTag, + "io.witnet.proxiable.board" + ) + { + __factory = _factory; + registry = _registry; + } + + receive() external payable { + revert("WitnetRequestBoardTrustableBase: no transfers accepted"); + } + + /// @dev Provide backwards compatibility for dapps bound to versions <= 0.6.1 + /// @dev (i.e. calling methods in IWitnetRequestBoard) + /// @dev (Until 'function ... abi(...)' modifier is allegedly supported in solc versions >= 0.9.1) + /* solhint-disable payable-fallback */ + /* solhint-disable no-complex-fallback */ + fallback() override external { + revert(string(abi.encodePacked( + "WitnetRequestBoardTrustableBase: 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 channel() virtual override public view returns (bytes4) { + return bytes4(keccak256(abi.encode(address(this), block.chainid))); + } + + function factory() virtual override public view returns (WitnetRequestFactory) { + return __factory; + } + + + // ================================================================================================================ + // --- Yet to be implemented virtual methods ---------------------------------------------------------------------- + + /// @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) virtual public 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, uint96 _callbackGasLimit) virtual public view returns (uint256); + + + // ================================================================================================================ + // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------ + + /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. + /// @dev Must fail when trying to upgrade to same logic contract more than once. + function initialize(bytes memory _initData) + public + override + { + address _owner = __storage().owner; + address[] memory _reporters; + + if (_owner == address(0)) { + // get owner (and reporters) from _initData + bytes memory _reportersRaw; + (_owner, _reportersRaw) = abi.decode(_initData, (address, bytes)); + __storage().owner = _owner; + _reporters = abi.decode(_reportersRaw, (address[])); + } else { + // only owner can initialize: + require( + msg.sender == _owner, + "WitnetRequestBoardTrustableBase: not the owner" + ); + // get reporters from _initData + _reporters = abi.decode(_initData, (address[])); + } + + if (__storage().base != address(0)) { + // current implementation cannot be initialized more than once: + require( + __storage().base != base(), + "WitnetRequestBoardTrustableBase: already upgraded" + ); + } + __storage().base = base(); + + require( + address(__factory).code.length > 0, + "WitnetRequestBoardTrustableBase: inexistent factory" + ); + require( + __factory.specs() == type(IWitnetRequestFactory).interfaceId, + "WitnetRequestBoardTrustableBase: uncompliant factory" + ); + require( + address(__factory.witnet()) == address(this) + && address(__factory.registry()) == address(registry), + "WitnetRequestBoardTrustableBase: discordant factory" + ); + + // Set reporters + __setReporters(_reporters); + + emit Upgraded(_owner, base(), codehash(), version()); + } + + /// Tells whether provided address could eventually upgrade the contract. + function isUpgradableFrom(address _from) external view override returns (bool) { + address _owner = __storage().owner; + return ( + // false if the WRB is intrinsically not upgradable, or `_from` is no owner + isUpgradable() + && _owner == _from + ); + } + + + // ================================================================================================================ + // --- Partial implementation of IWitnetRequestBoard -------------------------------------------------------------- + + /// @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 radHash The hash of some Witnet Data Request previously posted in the WitnetBytecodes registry. + function estimateBaseFee(uint256 gasPrice, bytes32 radHash) + override + public view + returns (uint256) + { + uint16 _resultMaxSize = registry.lookupRadonRequestResultMaxSize(radHash); + require( + _resultMaxSize > 0, + "WitnetRequestBoardTrustableDefault: invalid RAD" + ); + return estimateBaseFee( + gasPrice, + _resultMaxSize + ); + } + + /// Retrieves copy of all response data related to a previously posted request, removing the whole query from storage. + /// @dev Fails if the `_witnetQueryId` is not in 'Reported' status, or called from an address different to + /// @dev the one that actually posted the given request. + /// @param _witnetQueryId The unique query identifier. + function fetchQueryResponse(uint256 _witnetQueryId) + virtual override + external + inStatus(_witnetQueryId, WitnetV2.QueryStatus.Reported) + onlyRequester(_witnetQueryId) + returns (WitnetV2.Response memory _response) + { + _response = __seekQuery(_witnetQueryId).response; + delete __storage().queries[_witnetQueryId]; + } + + /// Gets the whole Query data contents, if any, no matter its current status. + function getQuery(uint256 _witnetQueryId) + external view + override + returns (WitnetV2.Query memory) + { + return __storage().queries[_witnetQueryId]; + } + + /// @notice Retrieves the serialized bytecode of a previously posted Witnet Data Request. + /// @dev Fails if the query does not exist. + /// @param _witnetQueryId The unique query identifier. + function getQueryBytecode(uint256 _witnetQueryId) + external view + virtual override + returns (bytes memory) + { + require( + _statusOf(_witnetQueryId) != WitnetV2.QueryStatus.Unknown, + "WitnetRequestBoardTrustableBase: unknown query" + ); + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryId); + if (__request.RAD != bytes32(0)) { + return registry.bytecodeOf(__request.RAD); + } else { + return __request.bytecode; + } + } + + /// @notice Retrieves the RAD hash and SLA parameters of the given query. + /// @param _witnetQueryId The unique query identifier. + function getQueryRequest(uint256 _witnetQueryId) + external view + override + returns (bytes32, WitnetV2.RadonSLA memory) + { + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryId); + return ( + __request.RAD == bytes32(0) ? registry.hashOf(__request.bytecode) : __request.RAD, + WitnetV2.toRadonSLA(__request.SLA) + ); + } + + /// Retrieves the Witnet-provable result, and metadata, to a previously posted request. + /// @dev Fails if the `_witnetQueryId` is not in 'Reported' status. + /// @param _witnetQueryId The unique query identifier + function getQueryResponse(uint256 _witnetQueryId) + external view + override + returns (WitnetV2.Response memory _response) + { + return __seekQueryResponse(_witnetQueryId); + } + + /// @notice Retrieves the Witnet-provable CBOR-bytes result of a previously posted request. + /// @param _witnetQueryId The unique query identifier. + function getQueryResult(uint256 _witnetQueryId) + external view + override + returns (Witnet.Result memory) + { + // todo: fail if not in finalized status ? + WitnetV2.Response storage _response = __seekQueryResponse(_witnetQueryId); + return _response.cborBytes.resultFromCborBytes(); + } + + /// @notice Returns reference to the commit/reveal act that took place on the Witnet blockchain. + /// @param _witnetQueryId The unique query identifier. + /// @return _witnetTimestamp Timestamp at which the query was solved by the Witnet blockchain. + /// @return _witnetTallyHash Hash of the commit/reveal act that solved the query on the Witnet blockchain. + /// @return _witnetEvmFinalityBlock EVM block at which the provided data can be considered to be final. + function getQueryResultAuditTrail(uint256 _witnetQueryId) + external view + override + returns ( + uint256 _witnetTimestamp, + bytes32 _witnetTallyHash, + uint256 _witnetEvmFinalityBlock + ) + { + WitnetV2.Response storage __response = __seekQueryResponse(_witnetQueryId); + return ( + __response.timestamp, + __response.tallyHash, + __response.unpackEvmFinalityBlock() + ); + } + + /// @notice Gets error code identifying some possible failure on the resolution of the given query. + /// @param _witnetQueryId The unique query identifier. + function getQueryResultError(uint256 _witnetQueryId) + override external view + returns (Witnet.ResultError memory) + { + WitnetV2.ResultStatus _status = getQueryResultStatus(_witnetQueryId); + try WitnetErrorsLib.asResultError(_status, __seekQueryResponse(_witnetQueryId).cborBytes) + returns (Witnet.ResultError memory _resultError) + { + return _resultError; + } + catch Error(string memory _reason) { + return Witnet.ResultError({ + code: Witnet.ResultErrorCodes.Unknown, + reason: string(abi.encodePacked("WitnetErrorsLib: ", _reason)) + }); + } + catch (bytes memory) { + return Witnet.ResultError({ + code: Witnet.ResultErrorCodes.Unknown, + reason: "WitnetErrorsLib: assertion failed" + }); + } + } + + /// @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 has been succesfully solved; + /// @notice - 3 => Error: the query couldn't get solved due to some issue. + /// @param _witnetQueryId The unique query identifier. + function getQueryResultStatus(uint256 _witnetQueryId) + virtual public view + returns (WitnetV2.ResultStatus) + { + WitnetV2.QueryStatus _queryStatus = _statusOf(_witnetQueryId); + if ( + _queryStatus == WitnetV2.QueryStatus.Finalized + || _queryStatus == WitnetV2.QueryStatus.Reported + ) { + bytes storage __cborValues = __seekQueryResponse(_witnetQueryId).cborBytes; + // determine whether reported result is an error by peeking the first byte + return (__cborValues[0] == bytes1(0xd8) + ? (_queryStatus == WitnetV2.QueryStatus.Finalized + ? WitnetV2.ResultStatus.Error + : WitnetV2.ResultStatus.AwaitingError + ) : (_queryStatus == WitnetV2.QueryStatus.Finalized + ? WitnetV2.ResultStatus.Ready + : WitnetV2.ResultStatus.AwaitingReady + ) + ); + } else if ( + _queryStatus == WitnetV2.QueryStatus.Posted + || _queryStatus == WitnetV2.QueryStatus.Undeliverable + ) { + return WitnetV2.ResultStatus.Awaiting; + } else { + return WitnetV2.ResultStatus.Void; + } + } + + /// Retrieves the reward currently set for a previously posted request. + /// @dev Fails if the `_witnetQueryId` is not valid or, if it has already been + /// @dev reported, or deleted. + /// @param _witnetQueryId The unique query identifier + function getQueryReward(uint256 _witnetQueryId) + override + external view + inStatus(_witnetQueryId, WitnetV2.QueryStatus.Posted) + returns (uint256) + { + return __seekQueryRequest(_witnetQueryId).evmReward; + } + + /// Gets current status of given query. + function getQueryStatus(uint256 _witnetQueryId) + external view + override + returns (WitnetV2.QueryStatus) + { + return _statusOf(_witnetQueryId); + + } + + + /// @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 WitnetBytecodes 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 _witnetQueryId Unique query identifier. + function postRequest( + bytes32 _queryRAD, + WitnetV2.RadonSLA calldata _querySLA + ) + virtual override + external payable + checkReward(estimateBaseFee(_getGasPrice(), _queryRAD)) + checkSLA(_querySLA) + returns (uint256 _witnetQueryId) + { + _witnetQueryId = __postRequest(_queryRAD, _querySLA.toBytes32(), 0); + // Let Web3 observers know that a new request has been posted + emit WitnetQuery( + _witnetQueryId, + _querySLA.witnessingWitTotalReward, + _getMsgValue() + ); + } + + /// @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 `WitnetResponseDeliveryFailed` + /// @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 WitnetBytecodes registry; + /// @dev - invalid SLA parameters were provided; + /// @dev - zero callback gas limit is 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 _witnetQueryId Unique query identifier. + function postRequestWithCallback( + bytes32 _queryRAD, + WitnetV2.RadonSLA calldata _querySLA, + uint96 _queryCallbackGasLimit + ) + virtual override + external payable + checkCallbackRecipient(msg.sender, _queryCallbackGasLimit) + checkReward(estimateBaseFeeWithCallback(_getGasPrice(), _queryCallbackGasLimit)) + checkSLA(_querySLA) + returns (uint256 _witnetQueryId) + { + _witnetQueryId = __postRequest( + _queryRAD, + _querySLA.toBytes32(), + _queryCallbackGasLimit + ); + emit WitnetQuery( + _witnetQueryId, + _querySLA.witnessingWitTotalReward, + _getMsgValue() + ); + } + + /// @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 `WitnetResponseDeliveryFailed` + /// @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 - zero callback gas limit is 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 _witnetQueryId Unique query identifier. + function postRequestWithCallback( + bytes calldata _queryUnverifiedBytecode, + WitnetV2.RadonSLA calldata _querySLA, + uint96 _queryCallbackGasLimit + ) + virtual override + external payable + checkCallbackRecipient(msg.sender, _queryCallbackGasLimit) + checkReward(estimateBaseFeeWithCallback(_getGasPrice(), _queryCallbackGasLimit)) + checkSLA(_querySLA) + returns (uint256 _witnetQueryId) + { + _witnetQueryId = __postRequest( + bytes32(0), + _querySLA.toBytes32(), + _queryCallbackGasLimit + ); + __seekQueryRequest(_witnetQueryId).bytecode = _queryUnverifiedBytecode; + emit WitnetQuery( + _witnetQueryId, + _querySLA.witnessingWitTotalReward, + _getMsgValue() + ); + } + + /// Increments the reward of a previously posted request by adding the transaction value to it. + /// @dev Fails if the `_witnetQueryId` is not in 'Posted' status. + /// @param _witnetQueryId The unique query identifier. + function upgradeQueryReward(uint256 _witnetQueryId) + external payable + virtual override + inStatus(_witnetQueryId, WitnetV2.QueryStatus.Posted) + { + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryId); + __request.evmReward += _getMsgValue(); + emit WitnetQueryRewardUpgraded(_witnetQueryId, __request.evmReward); + } + + + // ================================================================================================================ + // --- Full implementation of IWitnetRequestBoardReporter --------------------------------------------------------- + + /// @notice Estimates the actual earnings (or loss), in WEI, that a reporter would get by reporting result to given query, + /// @notice based on the gas price of the calling transaction. Data requesters should consider upgrading the reward on + /// @notice queries providing no actual earnings. + /// @dev Fails if the query does not exist, or if deleted. + function estimateQueryEarnings(uint256[] calldata _witnetQueryIds, uint256 _gasPrice) + virtual override + external view + returns (int256 _earnings) + { + uint256 _expenses; uint256 _revenues; + for (uint _ix = 0; _ix < _witnetQueryIds.length; _ix ++) { + if (_statusOf(_witnetQueryIds[_ix]) == WitnetV2.QueryStatus.Posted) { + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryIds[_ix]); + _revenues += __request.evmReward; + _expenses += _gasPrice * __request.unpackCallbackGasLimit(); + } + } + return int256(_revenues) - int256(_expenses); + } + + /// Reports the Witnet-provable result to a previously posted request. + /// @dev Will assume `block.timestamp` as the timestamp at which the request was solved. + /// @dev Fails if: + /// @dev - the `_witnetQueryId` is not in 'Posted' status. + /// @dev - provided `_witnetResultTallyHash` is zero; + /// @dev - length of provided `_result` is zero. + /// @param _witnetQueryId The unique identifier of the data request. + /// @param _witnetResultTallyHash Hash of the commit/reveal witnessing act that took place in the Witnet blockahin. + /// @param _witnetResultCborBytes The result itself as bytes. + function reportResult( + uint256 _witnetQueryId, + bytes32 _witnetResultTallyHash, + bytes calldata _witnetResultCborBytes + ) + external + override + onlyReporters + inStatus(_witnetQueryId, WitnetV2.QueryStatus.Posted) + returns (uint256) + { + require( + _witnetResultTallyHash != 0, + "WitnetRequestBoardTrustableDefault: tally has cannot be zero" + ); + // Ensures the result bytes do not have zero length + // This would not be a valid encoding with CBOR and could trigger a reentrancy attack + require( + _witnetResultCborBytes.length != 0, + "WitnetRequestBoardTrustableDefault: result cannot be empty" + ); + // Do actual report: + // solhint-disable not-rely-on-time + return __reportResultAndReward( + _witnetQueryId, + uint64(block.timestamp), + _witnetResultTallyHash, + _witnetResultCborBytes + ); + } + + /// Reports the Witnet-provable result to a previously posted request. + /// @dev Fails if: + /// @dev - called from unauthorized address; + /// @dev - the `_witnetQueryId` is not in 'Posted' status. + /// @dev - provided `_witnetResultTallyHash` is zero; + /// @dev - length of provided `_witnetResultCborBytes` is zero. + /// @param _witnetQueryId The unique query identifier + /// @param _witnetResultTimestamp Timestamp at which the reported value was captured by the Witnet blockchain. + /// @param _witnetResultTallyHash Hash of the commit/reveal witnessing act that took place in the Witnet blockahin. + /// @param _witnetResultCborBytes The result itself as bytes. + function reportResult( + uint256 _witnetQueryId, + uint64 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + bytes calldata _witnetResultCborBytes + ) + external + override + onlyReporters + inStatus(_witnetQueryId, WitnetV2.QueryStatus.Posted) + returns (uint256) + { + require( + _witnetResultTimestamp <= block.timestamp, + "WitnetRequestBoardTrustableDefault: bad timestamp" + ); + require( + _witnetResultTallyHash != 0, + "WitnetRequestBoardTrustableDefault: Witnet tallyHash cannot be zero" + ); + // Ensures the result bytes do not have zero length (this would not be a valid CBOR encoding + // and could trigger a reentrancy attack) + require( + _witnetResultCborBytes.length != 0, + "WitnetRequestBoardTrustableDefault: result cannot be empty" + ); + // Do actual report and return reward transfered to the reproter: + return __reportResultAndReward( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + _witnetResultCborBytes + ); + } + + /// Reports Witnet-provable results to multiple requests within a single EVM tx. + /// @dev Fails if called from unauthorized address. + /// @dev Emits a PostedResult event for every succesfully reported result, if any. + /// @param _batchResults Array of BatchedResult structs, every one containing: + /// - unique query identifier; + /// - timestamp of the solving tally txs in Witnet. If zero is provided, EVM-timestamp will be used instead; + /// - hash of the corresponding data request tx at the Witnet side-chain level; + /// - data request result in raw bytes. + /// @param _verbose If true, emits a BatchReportError event for every failing report, if any. + function reportResultBatch( + IWitnetRequestBoardReporter.BatchResult[] calldata _batchResults, + bool _verbose + ) + external + override + onlyReporters + returns (uint256 _batchReward) + { + for ( uint _i = 0; _i < _batchResults.length; _i ++) { + if (_statusOf(_batchResults[_i].queryId) != WitnetV2.QueryStatus.Posted) { + if (_verbose) { + emit BatchReportError( + _batchResults[_i].queryId, + "WitnetRequestBoardTrustableBase: bad queryId" + ); + } + } else if (_batchResults[_i].tallyHash == 0) { + if (_verbose) { + emit BatchReportError( + _batchResults[_i].queryId, + "WitnetRequestBoardTrustableBase: bad tallyHash" + ); + } + } else if (_batchResults[_i].cborBytes.length == 0) { + if (_verbose) { + emit BatchReportError( + _batchResults[_i].queryId, + "WitnetRequestBoardTrustableBase: bad cborBytes" + ); + } + } else if (_batchResults[_i].timestamp > 0 && _batchResults[_i].timestamp > block.timestamp) { + if (_verbose) { + emit BatchReportError( + _batchResults[_i].queryId, + "WitnetRequestBoardTrustableBase: bad timestamp" + ); + } + } else { + _batchReward += __reportResult( + _batchResults[_i].queryId, + _batchResults[_i].timestamp == 0 ? uint64(block.timestamp) : _batchResults[_i].timestamp, + _batchResults[_i].tallyHash, + _batchResults[_i].cborBytes + ); + } + } + // Transfer rewards to all reported results in one single transfer to the reporter: + if (_batchReward > 0) { + __safeTransferTo( + payable(msg.sender), + _batchReward + ); + } + } + + + // ================================================================================================================ + // --- Full implementation of 'IWitnetRequestBoardAdmin' ---------------------------------------------------------- + + /// Gets admin/owner address. + function owner() + public view + override + returns (address) + { + return __storage().owner; + } + + /// Transfers ownership. + function transferOwnership(address _newOwner) + public + virtual override + onlyOwner + { + address _owner = __storage().owner; + if (_newOwner != _owner) { + __storage().owner = _newOwner; + emit OwnershipTransferred(_owner, _newOwner); + } + } + + + // ================================================================================================================ + // --- Full implementation of 'IWitnetRequestBoardAdminACLs' ------------------------------------------------------ + + /// Tells whether given address is included in the active reporters control list. + /// @param _reporter The address to be checked. + function isReporter(address _reporter) public view override returns (bool) { + return __acls().isReporter_[_reporter]; + } + + /// Adds given addresses to the active reporters control list. + /// @dev Can only be called from the owner address. + /// @dev Emits the `ReportersSet` event. + /// @param _reporters List of addresses to be added to the active reporters control list. + function setReporters(address[] memory _reporters) + public + override + onlyOwner + { + __setReporters(_reporters); + } + + /// Removes given addresses from the active reporters control list. + /// @dev Can only be called from the owner address. + /// @dev Emits the `ReportersUnset` event. + /// @param _exReporters List of addresses to be added to the active reporters control list. + function unsetReporters(address[] memory _exReporters) + public + override + onlyOwner + { + for (uint ix = 0; ix < _exReporters.length; ix ++) { + address _reporter = _exReporters[ix]; + __acls().isReporter_[_reporter] = false; + } + emit ReportersUnset(_exReporters); + } + + + // ================================================================================================================ + // --- Internal functions ----------------------------------------------------------------------------------------- + + function __newQueryId(bytes32 _queryRAD, bytes32 _querySLA) + virtual internal view + returns (uint256) + { + return uint(keccak256(abi.encode( + channel(), + block.number, + msg.sender, + _queryRAD, + _querySLA + ))); + } + + function __postRequest(bytes32 _radHash, bytes32 _packedSLA, uint96 _callbackGasLimit) + virtual internal + returns (uint256 _witnetQueryId) + { + _witnetQueryId = __newQueryId(_radHash, _packedSLA); + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryId); + require( + __request.fromCallbackGas == bytes32(0), + "WitnetRequestBoardTrustableBase: already posted" + ); + { + __request.fromCallbackGas = WitnetV2.packRequesterCallbackGasLimit(msg.sender, _callbackGasLimit); + __request.RAD = _radHash; + __request.SLA = _packedSLA; + __request.evmReward = _getMsgValue(); + } + } + + function __reportResult( + uint256 _witnetQueryId, + uint64 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + bytes calldata _witnetResultCborBytes + ) + virtual internal + returns (uint256 _evmReward) + { + // read requester address and whether a callback was requested: + WitnetV2.Request storage __request = __seekQueryRequest(_witnetQueryId); + (address _evmRequester, uint96 _evmCallbackGasLimit) = __request.unpackRequesterAndCallbackGasLimit(); + + // read query EVM reward: + _evmReward = __request.evmReward; + + // set EVM reward right now as to avoid re-entrancy attacks: + __request.evmReward = 0; + + // determine whether a callback is required + if (_evmCallbackGasLimit > 0) { + ( + uint256 _evmCallbackActualGas, + bool _evmCallbackSuccess, + string memory _evmCallbackRevertMessage + ) = __reportResultCallback( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + _witnetResultCborBytes, + _evmRequester, + _evmCallbackGasLimit + ); + if (_evmCallbackSuccess) { + // => the callback run successfully + emit WitnetResponseDelivered( + _witnetQueryId, + _getGasPrice(), + _evmCallbackActualGas + ); + // upon successfull delivery, the audit trail is saved into storage, but not the actual result + // as it was already passed over to the requester: + __writeQueryResponse( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + hex"" + ); + } else { + // => the callback reverted + emit WitnetResponseDeliveryFailed( + _witnetQueryId, + _witnetResultCborBytes, + _getGasPrice(), + _evmCallbackActualGas, + bytes(_evmCallbackRevertMessage).length > 0 + ? _evmCallbackRevertMessage + : "WitnetRequestBoardTrustableBase: callback exceeded gas limit" + ); + // upon failing delivery, only the witnet result tally hash is saved into storage, + // as to distinguish Reported vs Undelivered status. The query result is not saved + // into storage as to avoid buffer-overflow attacks (on reporters): + __writeQueryResponse( + _witnetQueryId, + 0, + _witnetResultTallyHash, + hex"" + ); + } + } else { + // => no callback is involved + emit WitnetQueryReported( + _witnetQueryId, + _getGasPrice() + ); + // write query result and audit trail data into storage + __writeQueryResponse( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + _witnetResultCborBytes + ); + } + } + + function __reportResultAndReward( + uint256 _witnetQueryId, + uint64 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + bytes calldata _witnetResultCborBytes + ) + virtual internal + returns (uint256 _evmReward) + { + _evmReward = __reportResult( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + _witnetResultCborBytes + ); + // transfer reward to reporter + __safeTransferTo( + payable(msg.sender), + _evmReward + ); + } + + function __reportResultCallback( + uint256 _witnetQueryId, + uint64 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + bytes calldata _witnetResultCborBytes, + address _evmRequester, + uint256 _evmCallbackGasLimit + ) + virtual internal + returns ( + uint256 _evmCallbackActualGas, + bool _evmCallbackSuccess, + string memory _evmCallbackRevertMessage + ) + { + _evmCallbackActualGas = gasleft(); + if (_witnetResultCborBytes[0] == bytes1(0xd8)) { + WitnetCBOR.CBOR[] memory _errors = WitnetCBOR.fromBytes(_witnetResultCborBytes).readArray(); + if (_errors.length < 2) { + // try to report result with unknown error: + try IWitnetConsumer(_evmRequester).reportWitnetQueryError{gas: _evmCallbackGasLimit}( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + block.number, + Witnet.ResultErrorCodes.Unknown, + WitnetCBOR.CBOR({ + buffer: WitnetBuffer.Buffer({ data: hex"", cursor: 0}), + initialByte: 0, + majorType: 0, + additionalInformation: 0, + len: 0, + tag: 0 + }) + ) { + _evmCallbackSuccess = true; + } catch Error(string memory err) { + _evmCallbackRevertMessage = err; + } + } else { + // try to report result with parsable error: + try IWitnetConsumer(_evmRequester).reportWitnetQueryError{gas: _evmCallbackGasLimit}( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + block.number, + Witnet.ResultErrorCodes(_errors[0].readUint()), + _errors[0] + ) { + _evmCallbackSuccess = true; + } catch Error(string memory err) { + _evmCallbackRevertMessage = err; + } + } + } else { + // try to report result result with no error : + try IWitnetConsumer(_evmRequester).reportWitnetQueryResult{gas: _evmCallbackGasLimit}( + _witnetQueryId, + _witnetResultTimestamp, + _witnetResultTallyHash, + block.number, + WitnetCBOR.fromBytes(_witnetResultCborBytes) + ) { + _evmCallbackSuccess = true; + } catch Error(string memory err) { + _evmCallbackRevertMessage = err; + } catch (bytes memory) {} + } + _evmCallbackActualGas -= gasleft(); + } + + function __setReporters(address[] memory _reporters) + virtual internal + { + for (uint ix = 0; ix < _reporters.length; ix ++) { + address _reporter = _reporters[ix]; + __acls().isReporter_[_reporter] = true; + } + emit ReportersSet(_reporters); + } + + function __writeQueryResponse( + uint256 _witnetQueryId, + uint64 _witnetResultTimestamp, + bytes32 _witnetResultTallyHash, + bytes memory _witnetResultCborBytes + ) + virtual internal + { + __seekQuery(_witnetQueryId).response = WitnetV2.Response({ + fromFinality: WitnetV2.packReporterEvmFinalityBlock(msg.sender, block.number), + timestamp: _witnetResultTimestamp, + tallyHash: _witnetResultTallyHash, + cborBytes: _witnetResultCborBytes + }); + } + +} \ No newline at end of file diff --git a/contracts/core/defaults/WitnetRequestBoardTrustableDefault.sol b/contracts/core/defaults/WitnetRequestBoardTrustableDefault.sol new file mode 100644 index 000000000..eb71a0cc2 --- /dev/null +++ b/contracts/core/defaults/WitnetRequestBoardTrustableDefault.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT + +/* solhint-disable var-name-mixedcase */ + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./WitnetRequestBoardTrustableBase.sol"; + +/// @title Witnet Request Board "trustable" implementation contract. +/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. +/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. +/// The result of the requests will be posted back to this contract by the bridge nodes too. +/// @author The Witnet Foundation +contract WitnetRequestBoardTrustableDefault + is + WitnetRequestBoardTrustableBase +{ + uint256 internal immutable __reportResultGasBase; + uint256 internal immutable __reportResultWithCallbackGasBase; + uint256 internal immutable __reportResultWithCallbackRevertGasBase; + uint256 internal immutable __sstoreFromZeroGas; + + constructor( + WitnetRequestFactory _factory, + WitnetBytecodes _registry, + bool _upgradable, + bytes32 _versionTag, + uint256 _reportResultGasBase, + uint256 _reportResultWithCallbackGasBase, + uint256 _reportResultWithCallbackRevertGasBase, + uint256 _sstoreFromZeroGas + ) + WitnetRequestBoardTrustableBase( + _factory, + _registry, + _upgradable, + _versionTag, + address(0) + ) + { + __reportResultGasBase = _reportResultGasBase; + __reportResultWithCallbackGasBase = _reportResultWithCallbackGasBase; + __reportResultWithCallbackRevertGasBase = _reportResultWithCallbackRevertGasBase; + __sstoreFromZeroGas = _sstoreFromZeroGas; + } + + + // ================================================================================================================ + // --- Overrides 'IWitnetRequestBoard' ---------------------------------------------------------------------------- + + /// @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) + public view + virtual override + returns (uint256) + { + return _gasPrice * ( + __reportResultGasBase + + __sstoreFromZeroGas * ( + 5 + (_resultMaxSize == 0 ? 0 : _resultMaxSize - 1) / 32 + ) + ); + } + + /// @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, uint96 _callbackGasLimit) + public view + virtual override + returns (uint256) + { + uint _reportResultWithCallbackGasThreshold = ( + __reportResultWithCallbackRevertGasBase + + 3 * __sstoreFromZeroGas + ); + if ( + _callbackGasLimit < _reportResultWithCallbackGasThreshold + || __reportResultWithCallbackGasBase + _callbackGasLimit < _reportResultWithCallbackGasThreshold + ) { + return ( + _gasPrice + * _reportResultWithCallbackGasThreshold + ); + } else { + return ( + _gasPrice + * ( + __reportResultWithCallbackGasBase + + _callbackGasLimit + ) + ); + } + } + + + // ================================================================================================================ + // --- Overrides 'Payable' ---------------------------------------------------------------------------------------- + + /// Gets current transaction price. + function _getGasPrice() + internal view + virtual override + returns (uint256) + { + return tx.gasprice; + } + + /// Gets current payment value. + function _getMsgValue() + internal view + virtual override + returns (uint256) + { + return msg.value; + } + + /// Transfers ETHs to given address. + /// @param _to Recipient address. + /// @param _amount Amount of ETHs to transfer. + function __safeTransferTo(address payable _to, uint256 _amount) + internal + virtual override + { + payable(_to).transfer(_amount); + } +} diff --git a/contracts/impls/core/WitnetRequestFactoryDefault.sol b/contracts/core/defaults/WitnetRequestFactoryDefault.sol similarity index 89% rename from contracts/impls/core/WitnetRequestFactoryDefault.sol rename to contracts/core/defaults/WitnetRequestFactoryDefault.sol index c13eb0294..6bc54b6fb 100644 --- a/contracts/impls/core/WitnetRequestFactoryDefault.sol +++ b/contracts/core/defaults/WitnetRequestFactoryDefault.sol @@ -3,14 +3,11 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; - +import "../WitnetUpgradableBase.sol"; import "../../WitnetBytecodes.sol"; import "../../WitnetRequestFactory.sol"; import "../../data/WitnetRequestFactoryData.sol"; -import "../../impls/WitnetUpgradableBase.sol"; import "../../patterns/Clonable.sol"; -import "../../requests/WitnetRequest.sol"; contract WitnetRequestFactoryDefault is @@ -20,10 +17,11 @@ contract WitnetRequestFactoryDefault WitnetRequestFactoryData, WitnetUpgradableBase { - using ERC165Checker for address; + /// @notice Reference to Witnet Data Requests Bytecode Registry. + WitnetBytecodes immutable public override(WitnetRequestFactory, WitnetRequestTemplate) registry; - /// @notice Reference to Witnet Data Requests Bytecode Registry - WitnetBytecodes immutable public override(IWitnetRequestFactory, WitnetRequestTemplate) registry; + /// @notice Reference to the Witnet Request Board that all templates built out from this factory will refer to. + WitnetRequestBoard immutable public override(WitnetRequestFactory, WitnetRequestTemplate) witnet; modifier onlyDelegateCalls override(Clonable, Upgradeable) { require( @@ -51,6 +49,7 @@ contract WitnetRequestFactoryDefault } constructor( + WitnetRequestBoard _witnet, WitnetBytecodes _registry, bool _upgradable, bytes32 _versionTag @@ -61,10 +60,7 @@ contract WitnetRequestFactoryDefault "io.witnet.requests.factory" ) { - require( - address(_registry).supportsInterface(type(WitnetBytecodes).interfaceId), - "WitnetRequestFactoryDefault: uncompliant registry" - ); + witnet = _witnet; registry = _registry; // let logic contract be used as a factory, while avoiding further initializations: __proxiable().proxy = address(this); @@ -83,7 +79,7 @@ contract WitnetRequestFactoryDefault returns (WitnetRequestTemplate) { // check that at least one retrieval is provided - WitnetV2.RadonDataTypes _resultDataType; + Witnet.RadonDataTypes _resultDataType; require( _retrievalsIds.length > 0, "WitnetRequestTemplate: no retrievals?" @@ -187,48 +183,37 @@ contract WitnetRequestFactoryDefault ); } - function class() - virtual override(IWitnetRequestFactory, WitnetRequestTemplate) + function class() + virtual override(WitnetRequestFactory, WitnetRequestTemplate) external view - returns (bytes4) + returns (string memory) { if ( address(this) == _SELF || address(this) == __proxy() ) { - return type(WitnetRequestFactory).interfaceId; + return type(WitnetRequestFactory).name; } else if (__witnetRequest().radHash != bytes32(0)) { - return type(WitnetRequest).interfaceId; + return type(WitnetRequest).name; } else { - return type(WitnetRequestTemplate).interfaceId; + return type(WitnetRequestTemplate).name; } } - - // ================================================================================================================ - // ---Overrides 'IERC165' ----------------------------------------------------------------------------------------- - - /// @dev See {IERC165-supportsInterface}. - function supportsInterface(bytes4 _interfaceId) - public view - virtual override - returns (bool) - { - if (__witnetRequest().radHash != bytes32(0)) { - return ( - _interfaceId == type(IWitnetRequest).interfaceId - || _interfaceId == type(WitnetRequest).interfaceId - || _interfaceId == type(WitnetRequestTemplate).interfaceId - ); - } - else if (__witnetRequestTemplate().retrievals.length > 0) { - return (_interfaceId == type(WitnetRequestTemplate).interfaceId); - } - else { - return ( - _interfaceId == type(WitnetRequestFactory).interfaceId - || super.supportsInterface(_interfaceId) - ); + function specs() + virtual override(WitnetRequestFactory, WitnetRequestTemplate) + external view + returns (bytes4) + { + if ( + address(this) == _SELF + || address(this) == __proxy() + ) { + return type(IWitnetRequestFactory).interfaceId; + } else if (__witnetRequest().radHash != bytes32(0)) { + return type(WitnetRequest).interfaceId; + } else { + return type(WitnetRequestTemplate).interfaceId; } } @@ -285,7 +270,7 @@ contract WitnetRequestFactoryDefault /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. /// @dev Must fail when trying to upgrade to same logic contract more than once. - function initialize(bytes memory) + function initialize(bytes memory _initData) virtual override public onlyDelegateCalls @@ -295,13 +280,13 @@ contract WitnetRequestFactoryDefault address _owner = __witnetRequestFactory().owner; if (_owner == address(0)) { - // set owner if none set yet - _owner = msg.sender; + // set owner from the one specified in _initData + _owner = abi.decode(_initData, (address)); __witnetRequestFactory().owner = _owner; } else { // only owner can initialize the proxy if (msg.sender != _owner) { - revert WitnetUpgradableBase.OnlyOwner(_owner); + revert("WitnetRequestFactoryDefault: not the owner"); } } @@ -313,11 +298,14 @@ contract WitnetRequestFactoryDefault if (__proxiable().implementation != address(0)) { // same implementation cannot be initialized more than once: if(__proxiable().implementation == base()) { - revert WitnetUpgradableBase.AlreadyUpgraded(base()); + revert("WitnetRequestFactoryDefault: already initialized"); } } __proxiable().implementation = base(); + require(address(registry).code.length > 0, "WitnetRequestFactoryDefault: inexistent requests registry"); + require(registry.specs() == type(IWitnetBytecodes).interfaceId, "WitnetRequestFactoryDefault: uncompliant requests registry"); + emit Upgraded(msg.sender, base(), codehash(), version()); } @@ -471,7 +459,7 @@ contract WitnetRequestFactoryDefault override external view onlyDelegateCalls - returns (WitnetV2.RadonDataTypes) + returns (Witnet.RadonDataTypes) { WitnetRequestTemplate _template = __witnetRequest().template; if (address(_template) != address(0)) { @@ -514,7 +502,7 @@ contract WitnetRequestFactoryDefault override external view onlyDelegateCalls - returns (WitnetV2.RadonReducer memory) + returns (Witnet.RadonReducer memory) { WitnetRequestTemplate _template = __witnetRequest().template; if (address(_template) != address(0)) { @@ -530,7 +518,7 @@ contract WitnetRequestFactoryDefault override external view onlyDelegateCalls - returns (WitnetV2.RadonRetrieval memory) + returns (Witnet.RadonRetrieval memory) { WitnetRequestTemplate _template = __witnetRequest().template; if (address(_template) != address(0)) { @@ -564,7 +552,7 @@ contract WitnetRequestFactoryDefault override external view onlyDelegateCalls - returns (WitnetV2.RadonReducer memory) + returns (Witnet.RadonReducer memory) { WitnetRequestTemplate _template = __witnetRequest().template; if (address(_template) != address(0)) { diff --git a/contracts/data/WitnetBoardData.sol b/contracts/data/WitnetBoardData.sol deleted file mode 100644 index c24664377..000000000 --- a/contracts/data/WitnetBoardData.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; - -import "../libs/Witnet.sol"; - -/// @title Witnet Request Board base data model. -/// @author The Witnet Foundation. -abstract contract WitnetBoardData { - - bytes32 internal constant _WITNET_BOARD_DATA_SLOTHASH = - /* keccak256("io.witnet.boards.data") */ - 0xf595240b351bc8f951c2f53b26f4e78c32cb62122cf76c19b7fdda7d4968e183; - - struct WitnetBoardState { - address base; - address owner; - uint256 numQueries; - mapping (uint => Witnet.Query) queries; - } - - constructor() { - __storage().owner = msg.sender; - } - - /// Asserts the given query is currently in the given status. - modifier inStatus(uint256 _queryId, Witnet.QueryStatus _status) { - require( - _statusOf(_queryId) == _status, - _statusOfRevertMessage(_status) - ); - _; - } - - /// Asserts the given query was previously posted and that it was not yet deleted. - modifier notDeleted(uint256 _queryId) { - require(_queryId > 0 && _queryId <= __storage().numQueries, "WitnetRequestBoard: not yet posted"); - require(__query(_queryId).from != address(0), "WitnetRequestBoard: deleted"); - _; - } - - /// Asserts the give query was actually posted before calling this method. - modifier wasPosted(uint256 _queryId) { - require(_queryId > 0 && _queryId <= __storage().numQueries, "WitnetRequestBoard: not yet posted"); - _; - } - - // ================================================================================================================ - // --- Internal functions ----------------------------------------------------------------------------------------- - - /// Gets query storage by query id. - function __query(uint256 _queryId) internal view returns (Witnet.Query storage) { - return __storage().queries[_queryId]; - } - - /// Gets the Witnet.Request part of a given query. - function __request(uint256 _queryId) - internal view - returns (Witnet.Request storage) - { - return __storage().queries[_queryId].request; - } - - /// Gets the Witnet.Result part of a given query. - function __response(uint256 _queryId) - internal view - returns (Witnet.Response storage) - { - return __storage().queries[_queryId].response; - } - - /// Returns storage pointer to contents of 'WitnetBoardState' struct. - function __storage() - internal pure - returns (WitnetBoardState storage _ptr) - { - assembly { - _ptr.slot := _WITNET_BOARD_DATA_SLOTHASH - } - } - - /// Gets current status of given query. - function _statusOf(uint256 _queryId) - internal view - returns (Witnet.QueryStatus) - { - Witnet.Query storage _query = __storage().queries[_queryId]; - if (_query.response.drTxHash != 0) { - // Query is in "Reported" status as soon as the hash of the - // Witnet transaction that solved the query is reported - // back from a Witnet bridge: - return Witnet.QueryStatus.Reported; - } - else if (_query.from != address(0)) { - // Otherwise, while address from which the query was posted - // is kept in storage, the query remains in "Posted" status: - return Witnet.QueryStatus.Posted; - } - else if (_queryId > __storage().numQueries) { - // Requester's address is removed from storage only if - // the query gets "Deleted" by its requester. - return Witnet.QueryStatus.Deleted; - } else { - return Witnet.QueryStatus.Unknown; - } - } - - function _statusOfRevertMessage(Witnet.QueryStatus _status) - internal pure - returns (string memory) - { - if (_status == Witnet.QueryStatus.Posted) { - return "WitnetRequestBoard: not in Posted status"; - } else if (_status == Witnet.QueryStatus.Reported) { - return "WitnetRequestBoard: not in Reported status"; - } else if (_status == Witnet.QueryStatus.Deleted) { - return "WitnetRequestBoard: not in Deleted status"; - } else { - return "WitnetRequestBoard: bad mood"; - } - } -} diff --git a/contracts/data/WitnetBytecodesData.sol b/contracts/data/WitnetBytecodesData.sol index adb92052f..624f5f4e3 100644 --- a/contracts/data/WitnetBytecodesData.sol +++ b/contracts/data/WitnetBytecodesData.sol @@ -22,29 +22,35 @@ abstract contract WitnetBytecodesData { // ... } - struct RadonRequest { + struct DataProvider { + string authority; + uint256 totalEndpoints; + mapping (uint256 => bytes32) endpoints; + } + + struct DataRequest { string[][] args; bytes32 aggregator; bytes32 radHash; - WitnetV2.RadonDataTypes resultDataType; + Witnet.RadonDataTypes resultDataType; uint16 resultMaxSize; bytes32[] retrievals; bytes32 tally; } struct Database { - mapping (uint256 => WitnetV2.DataProvider) providers; + mapping (uint256 => DataProvider) providers; mapping (bytes32 => uint256) providersIndex; - mapping (bytes32 => WitnetV2.RadonReducer) reducers; - mapping (bytes32 => WitnetV2.RadonRetrieval) retrievals; - mapping (bytes32 => WitnetV2.RadonSLA) slas; + mapping (bytes32 => Witnet.RadonReducer) reducers; + mapping (bytes32 => Witnet.RadonRetrieval) retrievals; + mapping (bytes32 => Witnet.RadonSLA) _slas; - mapping (bytes32 => RadonRequest) requests; + mapping (bytes32 => DataRequest) requests; mapping (bytes32 => bytes32) rads; mapping (bytes32 => bytes) radsBytecode; - mapping (bytes32 => bytes) slasBytecode; + mapping (bytes32 => bytes) _slasBytecode; } constructor() { @@ -74,10 +80,10 @@ abstract contract WitnetBytecodesData { return __bytecodes().db; } - function __requests(bytes32 _drRetrievalHash) + function __requests(bytes32 _radHash) internal view - returns (RadonRequest storage _ptr) + returns (DataRequest storage _ptr) { - return __database().requests[_drRetrievalHash]; + return __database().requests[_radHash]; } } \ No newline at end of file diff --git a/contracts/data/WitnetPriceFeedsData.sol b/contracts/data/WitnetPriceFeedsData.sol index 94e486d97..e1fc4b4ed 100644 --- a/contracts/data/WitnetPriceFeedsData.sol +++ b/contracts/data/WitnetPriceFeedsData.sol @@ -11,7 +11,7 @@ abstract contract WitnetPriceFeedsData { 0xe36ea87c48340f2c23c9e1c9f72f5c5165184e75683a4d2a19148e5964c1d1ff; struct Storage { - bytes32 defaultSlaHash; + bytes32 packedDefaultSLA; bytes4[] ids; mapping (bytes4 => Record) records; } diff --git a/contracts/data/WitnetRequestBoardData.sol b/contracts/data/WitnetRequestBoardData.sol new file mode 100644 index 000000000..2b4ab01b8 --- /dev/null +++ b/contracts/data/WitnetRequestBoardData.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; + +import "../libs/WitnetV2.sol"; + +/// @title Witnet Request Board base data model. +/// @author The Witnet Foundation. +abstract contract WitnetRequestBoardData { + + using WitnetV2 for WitnetV2.Request; + + bytes32 internal constant _WITNET_REQUEST_BOARD_DATA_SLOTHASH = + /* keccak256("io.witnet.boards.data") */ + 0xf595240b351bc8f951c2f53b26f4e78c32cb62122cf76c19b7fdda7d4968e183; + + struct WitnetBoardState { + address base; + address owner; + uint256 nonce; + mapping (uint => WitnetV2.Query) queries; + } + + constructor() { + __storage().owner = msg.sender; + } + + /// Asserts the given query is currently in the given status. + modifier inStatus(uint256 _queryId, WitnetV2.QueryStatus _status) { + require( + _statusOf(_queryId) == _status, + _statusOfRevertMessage(_status) + ); _; + } + + /// Asserts the caller actually posted the referred query. + modifier onlyRequester(uint256 _queryId) { + require( + msg.sender == __seekQueryRequest(_queryId).unpackRequester(), + "WitnetRequestBoardBase: not the requester" + ); _; + } + + + // ================================================================================================================ + // --- Internal functions ----------------------------------------------------------------------------------------- + + /// Gets query storage by query id. + function __seekQuery(uint256 _queryId) internal view returns (WitnetV2.Query storage) { + return __storage().queries[_queryId]; + } + + /// Gets the Witnet.Request part of a given query. + function __seekQueryRequest(uint256 _queryId) + internal view + returns (WitnetV2.Request storage) + { + return __storage().queries[_queryId].request; + } + + /// Gets the Witnet.Result part of a given query. + function __seekQueryResponse(uint256 _queryId) + internal view + returns (WitnetV2.Response storage) + { + return __storage().queries[_queryId].response; + } + + /// Returns storage pointer to contents of 'WitnetBoardState' struct. + function __storage() + internal pure + returns (WitnetBoardState storage _ptr) + { + assembly { + _ptr.slot := _WITNET_REQUEST_BOARD_DATA_SLOTHASH + } + } + + /// Gets current status of given query. + function _statusOf(uint256 _queryId) + internal view + returns (WitnetV2.QueryStatus) + { + WitnetV2.Query storage __query = __storage().queries[_queryId]; + if (__query.response.tallyHash != bytes32(0)) { + if (__query.response.timestamp != 0) { + if (block.number >= WitnetV2.unpackEvmFinalityBlock(__query.response.fromFinality)) { + return WitnetV2.QueryStatus.Finalized; + } else { + return WitnetV2.QueryStatus.Reported; + } + } else { + return WitnetV2.QueryStatus.Undeliverable; + } + } else if (__query.request.fromCallbackGas != bytes32(0)) { + return WitnetV2.QueryStatus.Posted; + } else { + return WitnetV2.QueryStatus.Unknown; + } + } + + function _statusOfRevertMessage(WitnetV2.QueryStatus _status) + internal pure + returns (string memory) + { + if (_status == WitnetV2.QueryStatus.Posted) { + return "WitnetRequestBoard: not in Posted status"; + } else if (_status == WitnetV2.QueryStatus.Reported) { + return "WitnetRequestBoard: not in Reported status"; + } else if (_status == WitnetV2.QueryStatus.Finalized) { + return "WitnetRequestBoard: not in Finalized status"; + } else if (_status == WitnetV2.QueryStatus.Undeliverable) { + return "WitnetRequestBoard: not in Undeliverable status"; + } else { + return "WitnetRequestBoard: bad mood"; + } + } +} diff --git a/contracts/data/WitnetBoardDataACLs.sol b/contracts/data/WitnetRequestBoardDataACLs.sol similarity index 76% rename from contracts/data/WitnetBoardDataACLs.sol rename to contracts/data/WitnetRequestBoardDataACLs.sol index 989f79068..42ca19217 100644 --- a/contracts/data/WitnetBoardDataACLs.sol +++ b/contracts/data/WitnetRequestBoardDataACLs.sol @@ -2,13 +2,13 @@ pragma solidity >=0.7.0 <0.9.0; -import "./WitnetBoardData.sol"; +import "./WitnetRequestBoardData.sol"; /// @title Witnet Access Control Lists storage layout, for Witnet-trusted request boards. /// @author The Witnet Foundation. -abstract contract WitnetBoardDataACLs +abstract contract WitnetRequestBoardDataACLs is - WitnetBoardData + WitnetRequestBoardData { bytes32 internal constant _WITNET_BOARD_ACLS_SLOTHASH = /* keccak256("io.witnet.boards.data.acls") */ @@ -19,12 +19,12 @@ abstract contract WitnetBoardDataACLs } constructor() { - _acls().isReporter_[msg.sender] = true; + __acls().isReporter_[msg.sender] = true; } modifier onlyReporters { require( - _acls().isReporter_[msg.sender], + __acls().isReporter_[msg.sender], "WitnetRequestBoard: unauthorized reporter" ); _; @@ -33,7 +33,7 @@ abstract contract WitnetBoardDataACLs // ================================================================================================================ // --- Internal functions ----------------------------------------------------------------------------------------- - function _acls() internal pure returns (WitnetBoardACLs storage _struct) { + function __acls() internal pure returns (WitnetBoardACLs storage _struct) { assembly { _struct.slot := _WITNET_BOARD_ACLS_SLOTHASH } diff --git a/contracts/data/WitnetRequestFactoryData.sol b/contracts/data/WitnetRequestFactoryData.sol index b7e04459c..6679dfd64 100644 --- a/contracts/data/WitnetRequestFactoryData.sol +++ b/contracts/data/WitnetRequestFactoryData.sol @@ -3,7 +3,7 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../requests/WitnetRequest.sol"; +import "../WitnetRequest.sol"; contract WitnetRequestFactoryData { @@ -45,7 +45,7 @@ contract WitnetRequestFactoryData { /// @notice Array of retrievals hashes passed upon construction. bytes32[] retrievals; /// @notice Result data type. - WitnetV2.RadonDataTypes resultDataType; + Witnet.RadonDataTypes resultDataType; /// @notice Result max size or rank (if variable type). uint16 resultDataMaxSize; } diff --git a/contracts/impls/apps/WitnetPriceRouter.sol b/contracts/impls/apps/WitnetPriceRouter.sol deleted file mode 100644 index 48fd600df..000000000 --- a/contracts/impls/apps/WitnetPriceRouter.sol +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/utils/Strings.sol"; -import "../../interfaces/IWitnetPriceFeed.sol"; - -import "../../impls/WitnetUpgradableBase.sol"; -import "../../interfaces/IWitnetPriceRouter.sol"; - -contract WitnetPriceRouter - is - WitnetUpgradableBase, - IWitnetPriceRouter -{ - using Strings for uint256; - - struct Pair { - IERC165 pricefeed; - uint256 decimals; - string base; - string quote; - } - - struct Storage { - mapping (bytes4 => Pair) pairs; - mapping (address => bytes32) pricefeedId_; - bytes32[] supportedCurrencyPairs; - } - - constructor( - bool _upgradable, - bytes32 _versionTag - ) - WitnetUpgradableBase( - _upgradable, - _versionTag, - "io.witnet.proxiable.router" - ) - {} - - // ================================================================================================================ - // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------- - - /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. - /// @dev Must fail when trying to upgrade to same logic contract more than once. - function initialize(bytes memory) - public - override - { - address _owner = owner(); - if (_owner == address(0)) { - // set owner if none set yet - _owner = msg.sender; - _transferOwnership(_owner); - } else { - // only owner can initialize: - if (msg.sender != _owner) { - revert WitnetUpgradableBase.OnlyOwner(_owner); - } - } - - if (__proxiable().implementation != address(0)) { - // current implementation cannot be initialized more than once: - if(__proxiable().implementation == base()) { - revert WitnetUpgradableBase.AlreadyUpgraded(base()); - } - } - __proxiable().implementation = base(); - - emit Upgraded( - msg.sender, - base(), - codehash(), - version() - ); - } - - /// Tells whether provided address could eventually upgrade the contract. - function isUpgradableFrom(address _from) external view override returns (bool) { - address _owner = owner(); - return ( - // false if the WRB is intrinsically not upgradable, or `_from` is no owner - isUpgradable() - && _owner == _from - ); - } - - // ======================================================================== - // --- Implementation of 'IERC2362' --------------------------------------- - - /// Returns last valid price value and timestamp, as well as status of - /// the latest update request that got posted to the Witnet Request Board. - /// @dev Fails if the given currency pair is not currently supported. - /// @param _erc2362id Price pair identifier as specified in https://github.com/adoracles/ADOIPs/blob/main/adoip-0010.md - /// @return _lastPrice Last valid price reported back from the Witnet oracle. - /// @return _lastTimestamp EVM-timestamp of the last valid price. - /// @return _latestUpdateStatus Status code of latest update request that got posted to the Witnet Request Board: - /// - 200: latest update request was succesfully solved with no errors - /// - 400: latest update request was solved with errors - /// - 404: latest update request is still pending to be solved - function valueFor(bytes32 _erc2362id) - external view - virtual override - returns ( - int256 _lastPrice, - uint256 _lastTimestamp, - uint256 _latestUpdateStatus - ) - { - IWitnetPriceFeed _pricefeed = IWitnetPriceFeed(address(getPriceFeed(_erc2362id))); - require(address(_pricefeed) != address(0), "WitnetPriceRouter: unsupported currency pair"); - (_lastPrice, _lastTimestamp,, _latestUpdateStatus) = _pricefeed.lastValue(); - } - - - // ======================================================================== - // --- Implementation of 'IWitnetPriceRouter' --------------------------- - - /// Helper pure function: returns hash of the provided ERC2362-compliant currency pair caption (aka ID). - function currencyPairId(string memory _caption) - public pure - virtual override - returns (bytes32) - { - return keccak256(bytes(_caption)); - } - - /// Returns the ERC-165-compliant price feed contract currently serving - /// updates on the given currency pair. - function getPriceFeed(bytes32 _erc2362id) - public view - virtual override - returns (IERC165) - { - return __storage().pairs[bytes4(_erc2362id)].pricefeed; - } - - /// Returns human-readable ERC2362-based caption of the currency pair being - /// served by the given price feed contract address. - /// @dev Fails if the given price feed contract address is not currently - /// @dev registered in the router. - function getPriceFeedCaption(IERC165 _pricefeed) - public view - virtual override - returns (string memory) - { - require(supportsPriceFeed(_pricefeed), "WitnetPriceRouter: unknown"); - return lookupERC2362ID(__storage().pricefeedId_[address(_pricefeed)]); - } - - /// Returns human-readable caption of the ERC2362-based currency pair identifier, if known. - function lookupERC2362ID(bytes32 _erc2362id) - public view - virtual override - returns (string memory _caption) - { - Pair storage _pair = __storage().pairs[bytes4(_erc2362id)]; - if ( - bytes(_pair.base).length > 0 - && bytes(_pair.quote).length > 0 - ) { - _caption = string(abi.encodePacked( - "Price-", - _pair.base, - "/", - _pair.quote, - "-", - _pair.decimals.toString() - )); - } - } - - /// Register a price feed contract that will serve updates for the given currency pair. - /// @dev Setting zero address to a currency pair implies that it will not be served any longer. - /// @dev Otherwise, fails if the price feed contract does not support the `IWitnetPriceFeed` interface, - /// @dev or if given price feed is already serving another currency pair (within this WitnetPriceRouter instance). - function setPriceFeed( - IERC165 _pricefeed, - uint256 _decimals, - string calldata _base, - string calldata _quote - ) - public - virtual override - onlyOwner - { - if (address(_pricefeed) != address(0)) { - require( - _pricefeed.supportsInterface(type(IWitnetPriceFeed).interfaceId), - "WitnetPriceRouter: feed contract is not compliant with IWitnetPriceFeed" - ); - require( - __storage().pricefeedId_[address(_pricefeed)] == bytes32(0), - "WitnetPriceRouter: already serving a currency pair" - ); - } - bytes memory _caption = abi.encodePacked( - "Price-", - bytes(_base), - "/", - bytes(_quote), - "-", - _decimals.toString() - ); - bytes32 _erc2362id = keccak256(_caption); - - Pair storage _record = __storage().pairs[bytes4(_erc2362id)]; - address _currentPriceFeed = address(_record.pricefeed); - if (bytes(_record.base).length == 0) { - _record.base = _base; - _record.quote = _quote; - _record.decimals = _decimals; - __storage().supportedCurrencyPairs.push(_erc2362id); - } - else if (_currentPriceFeed != address(0)) { - __storage().pricefeedId_[_currentPriceFeed] = bytes32(0); - } - if (address(_pricefeed) != _currentPriceFeed) { - __storage().pricefeedId_[address(_pricefeed)] = _erc2362id; - } - _record.pricefeed = _pricefeed; - emit CurrencyPairSet(_erc2362id, _pricefeed); - } - - /// Returns list of known currency pairs IDs. - function supportedCurrencyPairs() - external view - virtual override - returns (bytes32[] memory) - { - return __storage().supportedCurrencyPairs; - } - - /// Returns `true` if given pair is currently being served by a compliant price feed contract. - function supportsCurrencyPair(bytes32 _erc2362id) - public view - virtual override - returns (bool) - { - return address(__storage().pairs[bytes4(_erc2362id)].pricefeed) != address(0); - } - - /// Returns `true` if given price feed contract is currently serving updates to any known currency pair. - function supportsPriceFeed(IERC165 _pricefeed) - public view - virtual override - returns (bool) - { - return __storage().pairs[bytes4(__storage().pricefeedId_[address(_pricefeed)])].pricefeed == _pricefeed; - } - - - /// ======================================================================= - /// --- Internal methods -------------------------------------------------- - - bytes32 internal constant _WITNET_PRICE_ROUTER_SLOTHASH = - /* keccak256("io.witnet.router.data") */ - 0x1ab0a3400242e9b47752f01347893fa91d77046d73895ccd575be9dd5025abd9; - - function __storage() internal pure returns (Storage storage ptr) { - assembly { - ptr.slot := _WITNET_PRICE_ROUTER_SLOTHASH - } - } -} diff --git a/contracts/impls/core/WitnetRequestBoardTrustableDefault.sol b/contracts/impls/core/WitnetRequestBoardTrustableDefault.sol deleted file mode 100644 index bde65694f..000000000 --- a/contracts/impls/core/WitnetRequestBoardTrustableDefault.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT - -/* solhint-disable var-name-mixedcase */ - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "./customs/WitnetRequestBoardTrustableBase.sol"; -import "../../patterns/Destructible.sol"; - -/// @title Witnet Request Board "trustable" implementation contract. -/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. -/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. -/// The result of the requests will be posted back to this contract by the bridge nodes too. -/// @author The Witnet Foundation -contract WitnetRequestBoardTrustableDefault - is - Destructible, - WitnetRequestBoardTrustableBase -{ - uint256 internal immutable _ESTIMATED_REPORT_RESULT_GAS; - - constructor( - WitnetRequestFactory _factory, - bool _upgradable, - bytes32 _versionTag, - uint256 _reportResultGasLimit - ) - WitnetRequestBoardTrustableBase( - _factory, - _upgradable, - _versionTag, - address(0) - ) - { - _ESTIMATED_REPORT_RESULT_GAS = _reportResultGasLimit; - } - - - // ================================================================================================================ - // --- Overrides implementation of 'IWitnetRequestBoardView' ------------------------------------------------------ - - /// Estimates the amount of reward we need to insert for a given gas price. - /// @param _gasPrice The gas price for which we need to calculate the rewards. - function estimateReward(uint256 _gasPrice) - public view - virtual override - returns (uint256) - { - return _gasPrice * _ESTIMATED_REPORT_RESULT_GAS; - } - - - // ================================================================================================================ - // --- Overrides 'Destructible' ----------------------------------------------------------------------------------- - - /// Destroys current instance. Only callable by the owner. - function destruct() external override onlyOwner { - selfdestruct(payable(msg.sender)); - } - - - // ================================================================================================================ - // --- Overrides 'Payable' ---------------------------------------------------------------------------------------- - - /// Gets current transaction price. - function _getGasPrice() - internal view - virtual override - returns (uint256) - { - return tx.gasprice; - } - - /// Gets current payment value. - function _getMsgValue() - internal view - virtual override - returns (uint256) - { - return msg.value; - } - - /// Transfers ETHs to given address. - /// @param _to Recipient address. - /// @param _amount Amount of ETHs to transfer. - function _safeTransferTo(address payable _to, uint256 _amount) - internal - virtual override - { - payable(_to).transfer(_amount); - } -} diff --git a/contracts/impls/core/customs/WitnetRequestBoardTrustableBase.sol b/contracts/impls/core/customs/WitnetRequestBoardTrustableBase.sol deleted file mode 100644 index 4a992376f..000000000 --- a/contracts/impls/core/customs/WitnetRequestBoardTrustableBase.sol +++ /dev/null @@ -1,837 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../../WitnetUpgradableBase.sol"; -import "../../../WitnetRequestBoard.sol"; -import "../../../data/WitnetBoardDataACLs.sol"; -import "../../../interfaces/IWitnetRequestBoardAdminACLs.sol"; -import "../../../patterns/Payable.sol"; - -import "../../../libs/WitnetErrorsLib.sol"; - -/// @title Witnet Request Board "trustable" base implementation contract. -/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. -/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. -/// The result of the requests will be posted back to this contract by the bridge nodes too. -/// @author The Witnet Foundation -abstract contract WitnetRequestBoardTrustableBase - is - WitnetUpgradableBase, - WitnetRequestBoard, - WitnetBoardDataACLs, - IWitnetRequestBoardAdminACLs, - Payable -{ - using Witnet for bytes; - using Witnet for Witnet.Result; - - constructor( - WitnetRequestFactory _factory, - bool _upgradable, - bytes32 _versionTag, - address _currency - ) - Payable(_currency) - WitnetUpgradableBase( - _upgradable, - _versionTag, - "io.witnet.proxiable.board" - ) - WitnetRequestBoard(_factory) - {} - - receive() external payable { - revert("WitnetRequestBoardTrustableBase: no transfers accepted"); - } - - /// @dev Provide backwards compatibility for dapps bound to versions <= 0.6.1 - /// @dev (i.e. calling methods in IWitnetRequestBoardDeprecating) - /// @dev (Until 'function ... abi(...)' modifier is allegedly supported in solc versions >= 0.9.1) - // solhint-disable-next-line payable-fallback - fallback() override external { /* solhint-disable no-complex-fallback */ - bytes4 _newSig = msg.sig; - if (msg.sig == 0xA8604C1A) { - // IWitnetRequestParser.isOk({bool,CBOR}) --> IWitnetRequestBoardDeprecating.isOk({bool,WitnetCBOR.CBOR}) - _newSig = IWitnetRequestBoardDeprecating.isOk.selector; - } else if (msg.sig == 0xCF62D115) { - // IWitnetRequestParser.asBytes32({bool,CBOR}) --> IWitnetRequestBoardDeprecating.asBytes32({bool,WitnetCBOR.CBOR}) - _newSig = IWitnetRequestBoardDeprecating.asBytes32.selector; - } else if (msg.sig == 0xBC7E25FF) { - // IWitnetRequestParser.asUint64({bool,CBOR}) --> IWitnetRequestBoardDeprecating.asUint64({bool,WitnetCBOR.CBOR}) - _newSig = IWitnetRequestBoardDeprecating.asUint64.selector; - } else if (msg.sig == 0xD74803BE) { - // IWitnetRequestParser.asErrorMessage({bool,CBOR}) --> IWitnetRequestBoardDeprecating.asErrorMessage({bool,WitnetCBOR.CBOR}) - _newSig = IWitnetRequestBoardDeprecating.asErrorMessage.selector; - } - if (_newSig != msg.sig) { - address _self = address(this); - assembly { - let ptr := mload(0x40) - calldatacopy(ptr, 0, calldatasize()) - mstore(ptr, or(and(mload(ptr), 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff), _newSig)) - let result := delegatecall(gas(), _self, ptr, calldatasize(), 0, 0) - let size := returndatasize() - returndatacopy(ptr, 0, size) - switch result - case 0 { revert(ptr, size) } - default { return(ptr, size) } - } - } else { - revert(string(abi.encodePacked( - "WitnetRequestBoardTrustableBase: 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))) - ))); - } - } - - - // ================================================================================================================ - // --- Overrides IERC165 interface -------------------------------------------------------------------------------- - - /// @dev See {IERC165-supportsInterface}. - function supportsInterface(bytes4 _interfaceId) - public view - virtual override - returns (bool) - { - return _interfaceId == type(WitnetRequestBoard).interfaceId - || _interfaceId == type(IWitnetRequestBoardAdminACLs).interfaceId - || super.supportsInterface(_interfaceId); - } - - - // ================================================================================================================ - // --- Overrides 'Upgradeable' ------------------------------------------------------------------------------------- - - /// @notice Re-initialize contract's storage context upon a new upgrade from a proxy. - /// @dev Must fail when trying to upgrade to same logic contract more than once. - function initialize(bytes memory _initData) - public - override - { - address _owner = __storage().owner; - if (_owner == address(0)) { - // set owner if none set yet - _owner = msg.sender; - __storage().owner = _owner; - } else { - // only owner can initialize: - require( - msg.sender == _owner, - "WitnetRequestBoardTrustableBase: only owner" - ); - } - - if (__storage().base != address(0)) { - // current implementation cannot be initialized more than once: - require( - __storage().base != base(), - "WitnetRequestBoardTrustableBase: already upgraded" - ); - } - __storage().base = base(); - - emit Upgraded(msg.sender, base(), codehash(), version()); - - // Do actual base initialization: - setReporters(abi.decode(_initData, (address[]))); - } - - /// Tells whether provided address could eventually upgrade the contract. - function isUpgradableFrom(address _from) external view override returns (bool) { - address _owner = __storage().owner; - return ( - // false if the WRB is intrinsically not upgradable, or `_from` is no owner - isUpgradable() - && _owner == _from - ); - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardAdmin' ---------------------------------------------------------- - - /// Gets admin/owner address. - function owner() - public view - override - returns (address) - { - return __storage().owner; - } - - /// Transfers ownership. - function transferOwnership(address _newOwner) - public - virtual override - onlyOwner - { - address _owner = __storage().owner; - if (_newOwner != _owner) { - __storage().owner = _newOwner; - emit OwnershipTransferred(_owner, _newOwner); - } - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardAdminACLs' ------------------------------------------------------ - - /// Tells whether given address is included in the active reporters control list. - /// @param _reporter The address to be checked. - function isReporter(address _reporter) public view override returns (bool) { - return _acls().isReporter_[_reporter]; - } - - /// Adds given addresses to the active reporters control list. - /// @dev Can only be called from the owner address. - /// @dev Emits the `ReportersSet` event. - /// @param _reporters List of addresses to be added to the active reporters control list. - function setReporters(address[] memory _reporters) - public - override - onlyOwner - { - for (uint ix = 0; ix < _reporters.length; ix ++) { - address _reporter = _reporters[ix]; - _acls().isReporter_[_reporter] = true; - } - emit ReportersSet(_reporters); - } - - /// Removes given addresses from the active reporters control list. - /// @dev Can only be called from the owner address. - /// @dev Emits the `ReportersUnset` event. - /// @param _exReporters List of addresses to be added to the active reporters control list. - function unsetReporters(address[] memory _exReporters) - public - override - onlyOwner - { - for (uint ix = 0; ix < _exReporters.length; ix ++) { - address _reporter = _exReporters[ix]; - _acls().isReporter_[_reporter] = false; - } - emit ReportersUnset(_exReporters); - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardReporter' ------------------------------------------------------- - - /// Reports the Witnet-provided result to a previously posted request. - /// @dev Will assume `block.timestamp` as the timestamp at which the request was solved. - /// @dev Fails if: - /// @dev - the `_queryId` is not in 'Posted' status. - /// @dev - provided `_drTxHash` is zero; - /// @dev - length of provided `_result` is zero. - /// @param _queryId The unique identifier of the data request. - /// @param _drTxHash The hash of the solving tally transaction in Witnet. - /// @param _cborBytes The result itself as bytes. - function reportResult( - uint256 _queryId, - bytes32 _drTxHash, - bytes calldata _cborBytes - ) - external - override - onlyReporters - inStatus(_queryId, Witnet.QueryStatus.Posted) - { - require(_drTxHash != 0, "WitnetRequestBoardTrustableDefault: Witnet drTxHash cannot be zero"); - // Ensures the result bytes do not have zero length - // This would not be a valid encoding with CBOR and could trigger a reentrancy attack - require(_cborBytes.length != 0, "WitnetRequestBoardTrustableDefault: result cannot be empty"); - // solhint-disable not-rely-on-time - _safeTransferTo( - payable(msg.sender), - __reportResult( - _queryId, - block.timestamp, - _drTxHash, - _cborBytes - ) - ); - emit PostedResult(_queryId, msg.sender); - } - - /// Reports the Witnet-provided result to a previously posted request. - /// @dev Fails if: - /// @dev - called from unauthorized address; - /// @dev - the `_queryId` is not in 'Posted' status. - /// @dev - provided `_drTxHash` is zero; - /// @dev - length of provided `_result` is zero. - /// @param _queryId The unique query identifier - /// @param _timestamp The timestamp of the solving tally transaction in Witnet. - /// @param _drTxHash The hash of the solving tally transaction in Witnet. - /// @param _cborBytes The result itself as bytes. - function reportResult( - uint256 _queryId, - uint256 _timestamp, - bytes32 _drTxHash, - bytes calldata _cborBytes - ) - external - override - onlyReporters - inStatus(_queryId, Witnet.QueryStatus.Posted) - { - require(_timestamp <= block.timestamp, "WitnetRequestBoardTrustableDefault: bad timestamp"); - require(_drTxHash != 0, "WitnetRequestBoardTrustableDefault: Witnet drTxHash cannot be zero"); - // Ensures the result bytes do not have zero length - // This would not be a valid encoding with CBOR and could trigger a reentrancy attack - require(_cborBytes.length != 0, "WitnetRequestBoardTrustableDefault: result cannot be empty"); - _safeTransferTo( - payable(msg.sender), - __reportResult( - _queryId, - _timestamp, - _drTxHash, - _cborBytes - ) - ); - emit PostedResult(_queryId, msg.sender); - } - - /// Reports Witnet-provided results to multiple requests within a single EVM tx. - /// @dev Fails if called from unauthorized address. - /// @dev Emits a PostedResult event for every succesfully reported result, if any. - /// @param _batchResults Array of BatchedResult structs, every one containing: - /// - unique query identifier; - /// - timestamp of the solving tally txs in Witnet. If zero is provided, EVM-timestamp will be used instead; - /// - hash of the corresponding data request tx at the Witnet side-chain level; - /// - data request result in raw bytes. - /// @param _verbose If true, emits a BatchReportError event for every failing report, if any. - function reportResultBatch( - IWitnetRequestBoardReporter.BatchResult[] memory _batchResults, - bool _verbose - ) - external - override - onlyReporters - { - uint _batchReward; - uint _batchSize = _batchResults.length; - for ( uint _i = 0; _i < _batchSize; _i ++) { - BatchResult memory _result = _batchResults[_i]; - if (_statusOf(_result.queryId) != Witnet.QueryStatus.Posted) { - if (_verbose) { - emit BatchReportError( - _result.queryId, - "WitnetRequestBoardTrustableBase: bad queryId" - ); - } - } else if (_result.drTxHash == 0) { - if (_verbose) { - emit BatchReportError( - _result.queryId, - "WitnetRequestBoardTrustableBase: bad drTxHash" - ); - } - } else if (_result.cborBytes.length == 0) { - if (_verbose) { - emit BatchReportError( - _result.queryId, - "WitnetRequestBoardTrustableBase: bad cborBytes" - ); - } - } else if (_result.timestamp > 0 && _result.timestamp > block.timestamp) { - if (_verbose) { - emit BatchReportError( - _result.queryId, - "WitnetRequestBoardTrustableBase: bad timestamp" - ); - } - } else { - _batchReward += __reportResult( - _result.queryId, - _result.timestamp == 0 ? block.timestamp : _result.timestamp, - _result.drTxHash, - _result.cborBytes - ); - emit PostedResult( - _result.queryId, - msg.sender - ); - } - } - // Transfer all successful rewards in one single shot to the authorized reporter, if any: - if (_batchReward > 0) { - _safeTransferTo( - payable(msg.sender), - _batchReward - ); - } - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardRequestor' ------------------------------------------------------ - - /// @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 has been succesfully solved; - /// @notice - 3 => Error: the query couldn't get solved due to some issue. - /// @param _queryId The unique query identifier. - function checkResultStatus(uint256 _queryId) - virtual public view - returns (Witnet.ResultStatus) - { - Witnet.QueryStatus _queryStatus = _statusOf(_queryId); - if (_queryStatus == Witnet.QueryStatus.Reported) { - bytes storage __cborValues = __response(_queryId).cborBytes; - // determine whether reported result is an error by peeking the first byte - return (__cborValues[0] == bytes1(0xd8) - ? Witnet.ResultStatus.Error - : Witnet.ResultStatus.Ready - ); - } else if (_queryStatus == Witnet.QueryStatus.Posted) { - return Witnet.ResultStatus.Awaiting; - } else { - return Witnet.ResultStatus.Void; - } - } - - /// @notice Gets error code identifying some possible failure on the resolution of the given query. - /// @param _queryId The unique query identifier. - function checkResultError(uint256 _queryId) - override external view - returns (Witnet.ResultError memory) - { - Witnet.ResultStatus _status = checkResultStatus(_queryId); - if (_status == Witnet.ResultStatus.Awaiting) { - return Witnet.ResultError({ - code: Witnet.ResultErrorCodes.Unknown, - reason: "WitnetRequestBoardTrustableBase: not yet solved" - }); - } else if (_status == Witnet.ResultStatus.Void) { - return Witnet.ResultError({ - code: Witnet.ResultErrorCodes.Unknown, - reason: "WitnetRequestBoardTrustableBase: unknown query" - }); - } else { - try WitnetErrorsLib.resultErrorFromCborBytes(__response(_queryId).cborBytes) - returns (Witnet.ResultError memory _error) - { - return _error; - } - catch Error(string memory _reason) { - return Witnet.ResultError({ - code: Witnet.ResultErrorCodes.Unknown, - reason: string(abi.encodePacked("WitnetErrorsLib: ", _reason)) - }); - } - catch (bytes memory) { - return Witnet.ResultError({ - code: Witnet.ResultErrorCodes.Unknown, - reason: "WitnetErrorsLib: assertion failed" - }); - } - } - } - - /// Retrieves copy of all response data related to a previously posted request, removing the whole query from storage. - /// @dev Fails if the `_queryId` is 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 deleteQuery(uint256 _queryId) - public - virtual override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (Witnet.Response memory _response) - { - Witnet.Query storage __query = __storage().queries[_queryId]; - require( - msg.sender == __query.from, - "WitnetRequestBoardTrustableBase: only requester" - ); - _response = __query.response; - delete __storage().queries[_queryId]; - emit DeletedQuery(_queryId, msg.sender); - } - - /// Requests the execution of the given Witnet Data Request in expectation that it will be relayed and solved by the Witnet DON. - /// A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// result to this request. - /// @dev Fails if: - /// @dev - provided reward is too low. - /// @dev - provided address is zero. - /// @param _requestInterface The address of a IWitnetRequest contract, containing the actual Data Request seralized bytecode. - /// @return _queryId An unique query identifier. - function postRequest(IWitnetRequest _requestInterface) - virtual override - public payable - returns (uint256 _queryId) - { - uint256 _value = _getMsgValue(); - uint256 _gasPrice = _getGasPrice(); - - // check base reward - uint256 _baseReward = estimateReward(_gasPrice); - require(_value >= _baseReward, "WitnetRequestBoardTrustableBase: reward too low"); - - // Validates provided script: - require(_requestInterface.hash() != bytes32(0), "WitnetRequestBoardTrustableBase: no precompiled request"); - - _queryId = ++ __storage().numQueries; - __storage().queries[_queryId].from = msg.sender; - - Witnet.Request storage _request = __request(_queryId); - _request.addr = address(_requestInterface); - _request.gasprice = _gasPrice; - _request.reward = _value; - - // Let observers know that a new request has been posted - emit PostedRequest(_queryId, msg.sender); - } - - /// Requests the execution of the given Witnet Data Request in expectation that it will be relayed and solved by the Witnet DON. - /// A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// result to this request. - /// @dev Fails if: - /// @dev - provided reward is too low. - /// @param _radHash The radHash of the Witnet Data Request. - /// @param _slaHash The slaHash of the Witnet Data Request. - function postRequest(bytes32 _radHash, bytes32 _slaHash) - virtual override - public payable - returns (uint256 _queryId) - { - uint256 _value = _getMsgValue(); - uint256 _gasPrice = _getGasPrice(); - - // check base reward - uint256 _baseReward = estimateReward(_gasPrice); - require( - _value >= _baseReward, - "WitnetRequestBoardTrustableBase: reward too low" - ); - - _queryId = ++ __storage().numQueries; - __storage().queries[_queryId].from = msg.sender; - - Witnet.Request storage _request = __request(_queryId); - _request.radHash = _radHash; - _request.slaHash = _slaHash; - _request.gasprice = _gasPrice; - _request.reward = _value; - - // Let observers know that a new request has been posted - emit PostedRequest(_queryId, msg.sender); - } - - /// Requests the execution of the given Witnet Data Request in expectation that it will be relayed and solved by the Witnet DON. - /// A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// result to this request. - /// @dev Fails if: - /// @dev - provided reward is too low. - /// @param _radHash The RAD hash of the data tequest to be solved by Witnet. - /// @param _slaParams The SLA param of the data request to be solved by Witnet. - function postRequest(bytes32 _radHash, WitnetV2.RadonSLA calldata _slaParams) - virtual override - public payable - returns (uint256 _queryId) - { - return postRequest( - _radHash, - registry.verifyRadonSLA(_slaParams) - ); - } - - - /// Increments the reward of a previously posted request by adding the transaction value to it. - /// @dev Updates request `gasPrice` in case this method is called with a higher - /// @dev gas price value than the one used in previous calls to `postRequest` or - /// @dev `upgradeReward`. - /// @dev Fails if the `_queryId` is not in 'Posted' status. - /// @dev Fails also in case the request `gasPrice` is increased, and the new - /// @dev reward value gets below new recalculated threshold. - /// @param _queryId The unique query identifier. - function upgradeReward(uint256 _queryId) - public payable - virtual override - inStatus(_queryId, Witnet.QueryStatus.Posted) - { - Witnet.Request storage _request = __request(_queryId); - - uint256 _newReward = _request.reward + _getMsgValue(); - uint256 _newGasPrice = _getGasPrice(); - - // If gas price is increased, then check if new rewards cover gas costs - if (_newGasPrice > _request.gasprice) { - // Checks the reward is covering gas cost - uint256 _minResultReward = estimateReward(_newGasPrice); - require( - _newReward >= _minResultReward, - "WitnetRequestBoardTrustableBase: reward too low" - ); - _request.gasprice = _newGasPrice; - } - _request.reward = _newReward; - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardView' ----------------------------------------------------------- - - /// Estimates the amount of reward we need to insert for a given gas price. - /// @param _gasPrice The gas price for which we need to calculate the rewards. - function estimateReward(uint256 _gasPrice) - public view - virtual override - returns (uint256); - - /// Returns next request id to be generated by the Witnet Request Board. - function getNextQueryId() - external view - override - returns (uint256) - { - return __storage().numQueries + 1; - } - - /// Gets the whole Query data contents, if any, no matter its current status. - function getQueryData(uint256 _queryId) - external view - override - returns (Witnet.Query memory) - { - return __storage().queries[_queryId]; - } - - /// Gets current status of given query. - function getQueryStatus(uint256 _queryId) - external view - override - returns (Witnet.QueryStatus) - { - return _statusOf(_queryId); - - } - - /// Retrieves the whole Request record posted to the Witnet Request Board. - /// @dev Fails if the `_queryId` is not valid or, if it has already been reported - /// @dev or deleted. - /// @param _queryId The unique identifier of a previously posted query. - function readRequest(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Posted) - returns (Witnet.Request memory _request) - { - return __request(_queryId); - } - - /// Retrieves the serialized bytecode of a previously posted Witnet Data Request. - /// @dev Fails if the `_queryId` is not valid, or if the related script bytecode - /// @dev got changed after being posted. Returns empty array once it gets reported, - /// @dev or deleted. - /// @param _queryId The unique query identifier. - function readRequestBytecode(uint256 _queryId) - external view - virtual override - returns (bytes memory _bytecode) - { - require( - _statusOf(_queryId) != Witnet.QueryStatus.Unknown, - "WitnetRequestBoardTrustableBase: not yet posted" - ); - Witnet.Request storage _request = __request(_queryId); - if (_request.addr != address(0)) { - _bytecode = IWitnetRequest(_request.addr).bytecode(); - } else if (_request.radHash != bytes32(0)) { - _bytecode = registry.bytecodeOf( - _request.radHash, - _request.slaHash - ); - } - } - - /// Retrieves the gas price that any assigned reporter will have to pay when reporting - /// result to a previously posted Witnet data request. - /// @dev Fails if the `_queryId` is not valid or, if it has already been - /// @dev reported, or deleted. - /// @param _queryId The unique query identifier - function readRequestGasPrice(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Posted) - returns (uint256) - { - return __storage().queries[_queryId].request.gasprice; - } - - /// Retrieves the reward currently set for a previously posted request. - /// @dev Fails if the `_queryId` is not valid or, if it has already been - /// @dev reported, or deleted. - /// @param _queryId The unique query identifier - function readRequestReward(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Posted) - returns (uint256) - { - return __storage().queries[_queryId].request.reward; - } - - /// Retrieves the Witnet-provided result, and metadata, to a previously posted request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier - function readResponse(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (Witnet.Response memory _response) - { - return __response(_queryId); - } - - /// Retrieves the hash of the Witnet transaction that actually solved the referred query. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponseDrTxHash(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (bytes32) - { - return __response(_queryId).drTxHash; - } - - /// Retrieves the address that reported the result to a previously-posted request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier - function readResponseReporter(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (address) - { - return __response(_queryId).reporter; - } - - /// Retrieves the Witnet-provided CBOR-bytes result of a previously posted request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier - function readResponseResult(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (Witnet.Result memory) - { - Witnet.Response storage _response = __response(_queryId); - return _response.cborBytes.resultFromCborBytes(); - } - - /// Retrieves the timestamp in which the result to the referred query was solved by the Witnet DON. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponseTimestamp(uint256 _queryId) - external view - override - inStatus(_queryId, Witnet.QueryStatus.Reported) - returns (uint256) - { - return __response(_queryId).timestamp; - } - - - // ================================================================================================================ - // --- Full implementation of 'IWitnetRequestBoardDeprecating' interface ------------------------------------------ - - /// Tell if a Witnet.Result is successful. - /// @param _result An instance of Witnet.Result. - /// @return `true` if successful, `false` if errored. - function isOk(Witnet.Result memory _result) - external pure - override - returns (bool) - { - return _result.success; - } - - /// Decode a bytes value from a Witnet.Result as a `bytes32` value. - /// @param _result An instance of Witnet.Result. - /// @return The `bytes32` decoded from the Witnet.Result. - function asBytes32(Witnet.Result memory _result) - external pure - override - returns (bytes32) - { - return _result.asBytes32(); - } - - /// Generate a suitable error message for a member of `Witnet.ResultErrorCodes` and its corresponding arguments. - /// @dev WARN: Note that client contracts should wrap this function into a try-catch foreseing potential errors generated in this function - /// @param _result An instance of `Witnet.Result`. - /// @return A tuple containing the `CBORValue.Error memory` decoded from the `Witnet.Result`, plus a loggable error message. - function asErrorMessage(Witnet.Result memory _result) - external pure - override - returns (Witnet.ResultErrorCodes, string memory) - { - Witnet.ResultError memory _resultError = WitnetErrorsLib.asError(_result); - return ( - _resultError.code, - _resultError.reason - ); - } - - /// Decode a natural numeric value from a Witnet.Result as a `uint` value. - /// @param _result An instance of Witnet.Result. - /// @return The `uint` decoded from the Witnet.Result. - function asUint64(Witnet.Result memory _result) - external pure - override - returns (uint64) - { - return uint64(_result.asUint()); - } - - /// Decode raw CBOR bytes into a Witnet.Result instance. - /// @param _cborBytes Raw bytes representing a CBOR-encoded value. - /// @return A `Witnet.Result` instance. - function resultFromCborBytes(bytes memory _cborBytes) - external pure - override - returns (Witnet.Result memory) - { - return Witnet.resultFromCborBytes(_cborBytes); - } - - - // ================================================================================================================ - // --- Internal functions ----------------------------------------------------------------------------------------- - - function __reportResult( - uint256 _queryId, - uint256 _timestamp, - bytes32 _drTxHash, - bytes memory _cborBytes - ) - internal - returns (uint256 _reward) - { - Witnet.Query storage _query = __query(_queryId); - Witnet.Request storage _request = _query.request; - Witnet.Response storage _response = _query.response; - - // solhint-disable not-rely-on-time - _response.timestamp = _timestamp; - _response.drTxHash = _drTxHash; - _response.reporter = msg.sender; - _response.cborBytes = _cborBytes; - - // return request latest reward - _reward = _request.reward; - - // Request data won't be needed anymore, so it can just get deleted right now: - delete _query.request; - } -} diff --git a/contracts/impls/core/customs/WitnetRequestBoardTrustableBoba.sol b/contracts/impls/core/customs/WitnetRequestBoardTrustableBoba.sol deleted file mode 100644 index e6c3a33f4..000000000 --- a/contracts/impls/core/customs/WitnetRequestBoardTrustableBoba.sol +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: MIT - -/* solhint-disable var-name-mixedcase */ - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -// Inherits from: -import "./WitnetRequestBoardTrustableBase.sol"; - -// Uses: -import "../../../interfaces/IERC20.sol"; - -/// @title Witnet Request Board OVM-compatible (Optimism) "trustable" implementation. -/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. -/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. -/// The result of the requests will be posted back to this contract by the bridge nodes too. -/// @author The Witnet Foundation -contract WitnetRequestBoardTrustableBoba - is - Payable, - WitnetRequestBoardTrustableBase -{ - uint256 internal lastBalance; - uint256 internal immutable _OVM_GAS_PRICE; - uint256 internal immutable _OVM_ESTIMATED_REPORT_RESULT_GAS; - - modifier ovmPayable virtual { - _; - // all calls to payable methods, - // MUST update internal 'lastBalance' value at the very end. - lastBalance = _balanceOf(address(this)); - } - - constructor( - WitnetRequestFactory _factory, - bool _upgradable, - bytes32 _versionTag, - uint256 _layer2ReportResultGasLimit, - uint256 _layer2GasPrice, - address _oETH - ) - WitnetRequestBoardTrustableBase(_factory, _upgradable, _versionTag, _oETH) - { - require(address(_oETH) != address(0), "WitnetRequestBoardTrustableBoba: null currency"); - _OVM_GAS_PRICE = _layer2GasPrice; - _OVM_ESTIMATED_REPORT_RESULT_GAS = _layer2ReportResultGasLimit; - } - - /// Gets lastBalance of given address. - function _balanceOf(address _from) - internal view - returns (uint256) - { - return currency.balanceOf(_from); - } - - - // ================================================================================================================ - // --- Overrides 'Payable' ---------------------------------------------------------------------------------------- - - /// Gets current transaction price. - function _getGasPrice() - internal view - override - returns (uint256) - { - return _OVM_GAS_PRICE; - } - - /// Calculates `msg.value` equivalent OVM_ETH value. - /// @dev Based on `lastBalance` value. - function _getMsgValue() - internal view - override - returns (uint256) - { - uint256 _newBalance = _balanceOf(address(this)); - assert(_newBalance >= lastBalance); - return _newBalance - lastBalance; - } - - /// Transfers oETHs to given address. - /// @dev Updates `lastBalance` value. - /// @param _to OVM_ETH recipient account. - /// @param _amount Amount of oETHs to transfer. - function _safeTransferTo(address payable _to, uint256 _amount) - internal - override - { - uint256 _lastBalance = _balanceOf(address(this)); - require(_amount <= _lastBalance, "WitnetRequestBoardTrustableBoba: insufficient funds"); - lastBalance = _lastBalance - _amount; - currency.transfer(_to, _amount); - } - - - // ================================================================================================================ - // --- Overrides implementation of 'IWitnetRequestBoardView' ------------------------------------------------------ - - /// @dev Estimate the minimal amount of reward we need to insert for a given gas price. - /// @return The minimal reward to be included for the given gas price. - function estimateReward(uint256) - public view - virtual override - returns (uint256) - { - return _OVM_GAS_PRICE * _OVM_ESTIMATED_REPORT_RESULT_GAS; - } - - - // ================================================================================================================ - // --- Overrides implementation of 'IWitnetRequestBoardRequestor' ------------------------------------------------- - - function postRequest(IWitnetRequest _request) - public payable - virtual override - ovmPayable - returns (uint256) - { - return WitnetRequestBoardTrustableBase.postRequest(_request); - } - - function upgradeReward(uint256 _queryId) - public payable - virtual override - ovmPayable - inStatus(_queryId, Witnet.QueryStatus.Posted) - { - WitnetRequestBoardTrustableBase.upgradeReward(_queryId); - } -} diff --git a/contracts/impls/core/customs/WitnetRequestBoardTrustableOvm2.sol b/contracts/impls/core/customs/WitnetRequestBoardTrustableOvm2.sol deleted file mode 100644 index 369bd398b..000000000 --- a/contracts/impls/core/customs/WitnetRequestBoardTrustableOvm2.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT - -/* solhint-disable var-name-mixedcase */ - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../WitnetRequestBoardTrustableDefault.sol"; - -// solhint-disable-next-line -interface OVM_GasPriceOracle { - function getL1Fee(bytes calldata _data) external view returns (uint256); -} - -/// @title Witnet Request Board "trustable" implementation contract. -/// @notice Contract to bridge requests to Witnet Decentralized Oracle Network. -/// @dev This contract enables posting requests that Witnet bridges will insert into the Witnet network. -/// The result of the requests will be posted back to this contract by the bridge nodes too. -/// @author The Witnet Foundation -contract WitnetRequestBoardTrustableOvm2 - is - Destructible, - WitnetRequestBoardTrustableDefault -{ - OVM_GasPriceOracle immutable public gasPriceOracleL1; - - constructor( - WitnetRequestFactory _factory, - bool _upgradable, - bytes32 _versionTag, - uint256 _reportResultGasLimit - ) - WitnetRequestBoardTrustableDefault( - _factory, - _upgradable, - _versionTag, - _reportResultGasLimit - ) - { - gasPriceOracleL1 = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); - } - - - // ================================================================================================================ - // --- Overrides implementation of 'IWitnetRequestBoardView' ------------------------------------------------------ - - /// Estimates the amount of reward we need to insert for a given gas price. - /// @param _gasPrice The gas price for which we need to calculate the rewards. - function estimateReward(uint256 _gasPrice) - public view - virtual override - returns (uint256) - { - return _gasPrice * _ESTIMATED_REPORT_RESULT_GAS + gasPriceOracleL1.getL1Fee( - hex"c8f5cdd500000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000225820ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - } -} diff --git a/contracts/interfaces/IERC165.sol b/contracts/interfaces/IERC165.sol deleted file mode 100644 index 27d6b9ff4..000000000 --- a/contracts/interfaces/IERC165.sol +++ /dev/null @@ -1,3 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; -import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; diff --git a/contracts/interfaces/IERC20.sol b/contracts/interfaces/IERC20.sol deleted file mode 100644 index 35ce7b279..000000000 --- a/contracts/interfaces/IERC20.sol +++ /dev/null @@ -1,3 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/interfaces/IWitnetPriceFeed.sol b/contracts/interfaces/IWitnetPriceFeed.sol deleted file mode 100644 index d5865f3da..000000000 --- a/contracts/interfaces/IWitnetPriceFeed.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -/// @title The Witnet Price Feed basic interface. -/// @dev Guides implementation of active price feed polling contracts. -/// @author The Witnet Foundation. - -interface IWitnetPriceFeed { - - /// Signals that a new price update request is being posted to the Witnet Request Board - event PriceFeeding(address indexed from, uint256 queryId, uint256 extraFee); - - /// @notice Estimates minimum fee amount in native currency to be paid when - /// @notice requesting a new price update. - /// @dev Actual fee depends on the gas price of the `requestUpdate()` transaction. - /// @param _gasPrice Gas price expected to be paid when calling `requestUpdate()` - function estimateUpdateFee(uint256 _gasPrice) external view returns (uint256); - - /// @notice Returns result of the last valid price update request successfully solved by the Witnet oracle. - function lastPrice() external view returns (int256); - - /// @notice Returns the EVM-timestamp when last valid price was reported back from the Witnet oracle. - function lastTimestamp() external view returns (uint256); - - /// @notice Returns tuple containing last valid price and timestamp, as well as status code of latest update - /// @notice request that got posted to the Witnet Request Board. - /// @return _lastPrice Last valid price reported back from the Witnet oracle. - /// @return _lastTimestamp EVM-timestamp of the last valid price. - /// @return _lastDrTxHash Hash of the Witnet Data Request that solved the last valid price. - /// @return _latestUpdateStatus Status code of the latest update request. - function lastValue() external view returns ( - int _lastPrice, - uint _lastTimestamp, - bytes32 _lastDrTxHash, - uint _latestUpdateStatus - ); - - /// @notice Returns identifier of the latest update request posted to the Witnet Request Board. - function latestQueryId() external view returns (uint256); - - /// @notice Returns hash of the Witnet Data Request that solved the latest update request. - /// @dev Returning 0 while the latest update request remains unsolved. - function latestUpdateDrTxHash() external view returns (bytes32); - - /// @notice Returns error message of latest update request posted to the Witnet Request Board. - /// @dev Returning empty string if the latest update request remains unsolved, or - /// @dev if it was succesfully solved with no errors. - function latestUpdateErrorMessage() external view returns (string memory); - - /// @notice Returns status code of latest update request posted to the Witnet Request Board: - /// @dev Status codes: - /// @dev - 200: update request was succesfully solved with no errors - /// @dev - 400: update request was solved with errors - /// @dev - 404: update request was not solved yet - function latestUpdateStatus() external view returns (uint256); - - /// @notice Returns `true` if latest update request posted to the Witnet Request Board - /// @notice has not been solved yet by the Witnet oracle. - function pendingUpdate() external view returns (bool); - - /// @notice Posts a new price update request to the Witnet Request Board. Requires payment of a fee - /// @notice that depends on the value of `tx.gasprice`. See `estimateUpdateFee(uint256)`. - /// @dev If previous update request was not solved yet, calling this method again allows - /// @dev upgrading the update fee if called with a higher `tx.gasprice` value. - function requestUpdate() external payable; - - /// @notice Tells whether this contract implements the interface defined by `interfaceId`. - /// @dev See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - /// @dev to learn more about how these ids are created. - function supportsInterface(bytes4) external view returns (bool); -} diff --git a/contracts/interfaces/IWitnetPriceRouter.sol b/contracts/interfaces/IWitnetPriceRouter.sol deleted file mode 100644 index 23b25cfaa..000000000 --- a/contracts/interfaces/IWitnetPriceRouter.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "ado-contracts/contracts/interfaces/IERC2362.sol"; -import "./IERC165.sol"; - -/// @title The Witnet Price Router basic interface. -/// @dev Guides implementation of price feeds aggregation contracts. -/// @author The Witnet Foundation. -abstract contract IWitnetPriceRouter - is - IERC2362 -{ - /// Emitted everytime a currency pair is attached to a new price feed contract - /// @dev See https://github.com/adoracles/ADOIPs/blob/main/adoip-0010.md - /// @dev to learn how these ids are created. - event CurrencyPairSet(bytes32 indexed erc2362ID, IERC165 pricefeed); - - /// @notice Helper pure function: returns hash of the provided ERC2362-compliant currency pair caption (aka ID). - function currencyPairId(string memory) external pure virtual returns (bytes32); - - /// @notice Returns the ERC-165-compliant price feed contract currently serving - /// @notice updates on the given currency pair. - function getPriceFeed(bytes32 _erc2362id) external view virtual returns (IERC165); - - /// @notice Returns human-readable ERC2362-based caption of the currency pair being - /// @notice served by the given price feed contract address. - /// @dev Should fail if the given price feed contract address is not currently - /// @dev registered in the router. - function getPriceFeedCaption(IERC165) external view virtual returns (string memory); - - /// @notice Returns human-readable caption of the ERC2362-based currency pair identifier, if known. - function lookupERC2362ID(bytes32 _erc2362id) external view virtual returns (string memory); - - /// @notice Register a price feed contract that will serve updates for the given currency pair. - /// @dev Setting zero address to a currency pair implies that it will not be served any longer. - /// @dev Otherwise, should fail if the price feed contract does not support the `IWitnetPriceFeed` interface, - /// @dev or if given price feed is already serving another currency pair (within this WitnetPriceRouter instance). - function setPriceFeed( - IERC165 _pricefeed, - uint256 _decimals, - string calldata _base, - string calldata _quote - ) - external virtual; - - /// @notice Returns list of known currency pairs IDs. - function supportedCurrencyPairs() external view virtual returns (bytes32[] memory); - - /// @notice Returns `true` if given pair is currently being served by a compliant price feed contract. - function supportsCurrencyPair(bytes32 _erc2362id) external view virtual returns (bool); - - /// @notice Returns `true` if given price feed contract is currently serving updates to any known currency pair. - function supportsPriceFeed(IERC165 _priceFeed) external view virtual returns (bool); -} diff --git a/contracts/interfaces/IWitnetRandomness.sol b/contracts/interfaces/IWitnetRandomness.sol index f3759b945..1e57c354f 100644 --- a/contracts/interfaces/IWitnetRandomness.sol +++ b/contracts/interfaces/IWitnetRandomness.sol @@ -2,8 +2,8 @@ pragma solidity >=0.7.0 <0.9.0; +import "../WitnetRequest.sol"; import "../WitnetRequestBoard.sol"; -import "../requests/WitnetRequest.sol"; /// @title The Witnet Randomness generator interface. /// @author Witnet Foundation. @@ -28,12 +28,11 @@ interface IWitnetRandomness { /// @notice Retrieves data of a randomization request that got successfully posted to the WRB within a given block. /// @dev Returns zero values if no randomness request was actually posted within a given block. /// @param _block Block number whose randomness request is being queried for. - /// @return _from Address from which the latest randomness request was posted. /// @return _id Unique request identifier as provided by the WRB. /// @return _prevBlock Block number in which a randomness request got posted just before this one. 0 if none. /// @return _nextBlock Block number in which a randomness request got posted just after this one, 0 if none. function getRandomizeData(uint256 _block) - external view returns (address _from, uint256 _id, uint256 _prevBlock, uint256 _nextBlock); + external view returns (uint256 _id, uint256 _prevBlock, uint256 _nextBlock); /// @notice Retrieves the randomness generated upon solving a request that was posted within a given block, /// if any, or to the _first_ request posted after that block, otherwise. Should the intended diff --git a/contracts/interfaces/IWitnetRequestBoardDeprecating.sol b/contracts/interfaces/IWitnetRequestBoardDeprecating.sol deleted file mode 100644 index 7e9a6cd09..000000000 --- a/contracts/interfaces/IWitnetRequestBoardDeprecating.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../libs/Witnet.sol"; - -/// @title Witnet Request Board info interface. -/// @author The Witnet Foundation. -interface IWitnetRequestBoardDeprecating { - - /// =============================================================================================================== - /// --- Deprecating funcionality v0.5 ----------------------------------------------------------------------------- - - /// Tell if a Witnet.Result is successful. - /// @param _result An instance of Witnet.Result. - /// @return `true` if successful, `false` if errored. - function isOk(Witnet.Result memory _result) external pure returns (bool); - - /// Decode a bytes value from a Witnet.Result as a `bytes32` value. - /// @param _result An instance of Witnet.Result. - /// @return The `bytes32` decoded from the Witnet.Result. - function asBytes32(Witnet.Result memory _result) external pure returns (bytes32); - - /// Generate a suitable error message for a member of `Witnet.ResultErrorCodes` and its corresponding arguments. - /// @dev WARN: Note that client contracts should wrap this function into a try-catch foreseing potential errors generated in this function - /// @param _result An instance of `Witnet.Result`. - /// @return A tuple containing the `CBORValue.Error memory` decoded from the `Witnet.Result`, plus a loggable error message. - function asErrorMessage(Witnet.Result memory _result) external pure returns (Witnet.ResultErrorCodes, string memory); - - /// Decode a natural numeric value from a Witnet.Result as a `uint` value. - /// @param _result An instance of Witnet.Result. - /// @return The `uint` decoded from the Witnet.Result. - function asUint64(Witnet.Result memory _result) external pure returns (uint64); - - /// Decode raw CBOR bytes into a Witnet.Result instance. - /// @param _cborBytes Raw bytes representing a CBOR-encoded value. - /// @return A `Witnet.Result` instance. - function resultFromCborBytes(bytes memory _cborBytes) external pure returns (Witnet.Result memory); - -} diff --git a/contracts/interfaces/IWitnetRequestBoardEvents.sol b/contracts/interfaces/IWitnetRequestBoardEvents.sol deleted file mode 100644 index 54eb31ab4..000000000 --- a/contracts/interfaces/IWitnetRequestBoardEvents.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; - -/// @title Witnet Request Board emitting events interface. -/// @author The Witnet Foundation. -interface IWitnetRequestBoardEvents { - - /// Emitted when a Witnet Data Request is posted to the WRB. - event PostedRequest(uint256 queryId, address from); - - /// Emitted when a Witnet-solved result is reported to the WRB. - event PostedResult(uint256 queryId, address from); - - /// Emitted when all data related to given query is deleted from the WRB. - event DeletedQuery(uint256 queryId, address from); -} diff --git a/contracts/interfaces/IWitnetRequestBoardReporter.sol b/contracts/interfaces/IWitnetRequestBoardReporter.sol deleted file mode 100644 index 28895bd9d..000000000 --- a/contracts/interfaces/IWitnetRequestBoardReporter.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; - -/// @title The Witnet Request Board Reporter interface. -/// @author The Witnet Foundation. -interface IWitnetRequestBoardReporter { - - /// @notice Reports the Witnet-provided result to a previously posted request. - /// @dev Will assume `block.timestamp` as the timestamp at which the request was solved. - /// @dev Fails if: - /// @dev - the `_queryId` is not in 'Posted' status. - /// @dev - provided `_drTxHash` is zero; - /// @dev - length of provided `_result` is zero. - /// @param _queryId The unique identifier of the data request. - /// @param _drTxHash The hash of the corresponding data request transaction in Witnet. - /// @param _result The result itself as bytes. - function reportResult( - uint256 _queryId, - bytes32 _drTxHash, - bytes calldata _result - ) external; - - /// @notice Reports the Witnet-provided result to a previously posted request. - /// @dev Fails if: - /// @dev - called from unauthorized address; - /// @dev - the `_queryId` is not in 'Posted' status. - /// @dev - provided `_drTxHash` is zero; - /// @dev - length of provided `_result` is zero. - /// @param _queryId The unique query identifier - /// @param _timestamp The timestamp of the solving tally transaction in Witnet. - /// @param _drTxHash The hash of the corresponding data request transaction in Witnet. - /// @param _result The result itself as bytes. - function reportResult( - uint256 _queryId, - uint256 _timestamp, - bytes32 _drTxHash, - bytes calldata _result - ) external; - - /// @notice Reports Witnet-provided results to multiple requests within a single EVM tx. - /// @dev Must emit a PostedResult event for every succesfully reported result. - /// @param _batchResults Array of BatchResult structs, every one containing: - /// - unique query identifier; - /// - timestamp of the solving tally txs in Witnet. If zero is provided, EVM-timestamp will be used instead; - /// - hash of the corresponding data request tx at the Witnet side-chain level; - /// - data request result in raw bytes. - /// @param _verbose If true, must emit a BatchReportError event for every failing report, if any. - function reportResultBatch(BatchResult[] calldata _batchResults, bool _verbose) external; - - struct BatchResult { - uint256 queryId; - uint256 timestamp; - bytes32 drTxHash; - bytes cborBytes; - } - - event BatchReportError(uint256 queryId, string reason); -} diff --git a/contracts/interfaces/IWitnetRequestBoardRequestor.sol b/contracts/interfaces/IWitnetRequestBoardRequestor.sol deleted file mode 100644 index 2dbb46537..000000000 --- a/contracts/interfaces/IWitnetRequestBoardRequestor.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../libs/WitnetV2.sol"; - -/// @title Witnet Requestor Interface -/// @notice It defines how to interact with the Witnet Request Board in order to: -/// - request the execution of Witnet Radon scripts (data request); -/// - upgrade the resolution reward of any previously posted request, in case gas price raises in mainnet; -/// - read the result of any previously posted request, eventually reported by the Witnet DON. -/// - remove from storage all data related to past and solved data requests, and results. -/// @author The Witnet Foundation. -interface IWitnetRequestBoardRequestor { - - /// @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 has been succesfully solved; - /// @notice - 3 => Error: the query couldn't get solved due to some issue. - /// @param _queryId The unique query identifier. - function checkResultStatus(uint256 _queryId) external view returns (Witnet.ResultStatus); - - /// @notice Gets error code identifying some possible failure on the resolution of the given query. - /// @param _queryId The unique query identifier. - function checkResultError(uint256 _queryId) external view returns (Witnet.ResultError memory); - - /// @notice Retrieves a copy of all Witnet-provided data related to a previously posted request, removing the whole query from the WRB storage. - /// @dev Fails if the `_queryId` is 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 deleteQuery(uint256 _queryId) external returns (Witnet.Response memory); - - /// @notice Requests the execution of the given Witnet Data Request in expectation that it will be relayed and solved by the Witnet DON. - /// @notice A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// @notice result to this request. - /// @dev Fails if: - /// @dev - provided reward is too low. - /// @dev - provided script is zero address. - /// @dev - provided script bytecode is empty. - /// @param addr The address of the IWitnetRequest contract that can provide the actual Data Request bytecode. - /// @return _queryId Unique query identifier. - function postRequest(IWitnetRequest addr) 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 the Witnet DON. - /// @notice A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// @notice result to this request. - /// @dev Fails if, provided reward is too low. - /// @param radHash The RAD hash of the data request to be solved by Witnet. - /// @param slaHash The SLA hash of the data request to be solved by Witnet. - /// @return _queryId Unique query identifier. - function postRequest(bytes32 radHash, bytes32 slaHash) 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 the Witnet DON. - /// @notice A reward amount is escrowed by the Witnet Request Board that will be transferred to the reporter who relays back the Witnet-provided - /// @notice result to this request. - /// @dev Fails if, provided reward is too low. - /// @param radHash The RAD hash of the data request to be solved by Witnet. - /// @param slaParams The SLA params of the data request to be solved by Witnet. - /// @return _queryId Unique query identifier. - function postRequest(bytes32 radHash, WitnetV2.RadonSLA calldata slaParams) external payable returns (uint256 _queryId); - - /// @notice Increments the reward of a previously posted request by adding the transaction value to it. - /// @dev Updates request `gasPrice` in case this method is called with a higher - /// @dev gas price value than the one used in previous calls to `postRequest` or - /// @dev `upgradeReward`. - /// @dev Fails if the `_queryId` is not in 'Posted' status. - /// @dev Fails also in case the request `gasPrice` is increased, and the new - /// @dev reward value gets below new recalculated threshold. - /// @param _queryId The unique query identifier. - function upgradeReward(uint256 _queryId) external payable; -} diff --git a/contracts/interfaces/IWitnetRequestBoardView.sol b/contracts/interfaces/IWitnetRequestBoardView.sol deleted file mode 100644 index d86000ee5..000000000 --- a/contracts/interfaces/IWitnetRequestBoardView.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../libs/Witnet.sol"; - -/// @title Witnet Request Board info interface. -/// @author The Witnet Foundation. -interface IWitnetRequestBoardView { - - /// @notice Estimates the amount of reward we need to insert for a given gas price. - /// @param _gasPrice The gas price for which we need to calculate the rewards. - function estimateReward(uint256 _gasPrice) external view returns (uint256); - - /// @notice Returns next query id to be generated by the Witnet Request Board. - function getNextQueryId() external view returns (uint256); - - /// @notice Gets the whole Query data contents, if any, no matter its current status. - function getQueryData(uint256 _queryId) external view returns (Witnet.Query memory); - - /// @notice Gets current status of given query. - function getQueryStatus(uint256 _queryId) external view returns (Witnet.QueryStatus); - - /// @notice Retrieves the whole Request record posted to the Witnet Request Board. - /// @dev Fails if the `_queryId` is not valid or, if it has already been reported - /// @dev or deleted. - /// @param _queryId The unique identifier of a previously posted query. - function readRequest(uint256 _queryId) external view returns (Witnet.Request memory); - - /// @notice Retrieves the serialized bytecode of a previously posted Witnet Data Request. - /// @dev Fails if the `_queryId` is not valid, or if the related script bytecode - /// @dev got changed after being posted. Returns empty array once it gets reported, - /// @dev or deleted. - /// @param _queryId The unique query identifier. - function readRequestBytecode(uint256 _queryId) external view returns (bytes memory); - - /// @notice Retrieves the gas price that any assigned reporter will have to pay when reporting - /// result to a previously posted Witnet data request. - /// @dev Fails if the `_queryId` is not valid or, if it has already been - /// @dev reported, or deleted. - /// @param _queryId The unique query identifie - function readRequestGasPrice(uint256 _queryId) external view returns (uint256); - - /// @notice Retrieves the reward currently set for the referred query. - /// @dev Fails if the `_queryId` is not valid or, if it has already been - /// @dev reported, or deleted. - /// @param _queryId The unique query identifier. - function readRequestReward(uint256 _queryId) external view returns (uint256); - - /// @notice Retrieves the whole `Witnet.Response` record referred to a previously posted Witnet Data Request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponse(uint256 _queryId) external view returns (Witnet.Response memory); - - /// @notice Retrieves error codes of given query. - /// @dev Fails if the `_queryId` is not in 'Reported' status, or if no actual error. - /// @param _queryId The unique query identifier. - function readResponseDrTxHash(uint256 _queryId) external view returns (bytes32); - - /// @notice Retrieves the address that reported the result to a previously-posted request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponseReporter(uint256 _queryId) external view returns (address); - - /// @notice Retrieves the Witnet-provided CBOR-bytes result of a previously posted request. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponseResult(uint256 _queryId) external view returns (Witnet.Result memory); - - /// @notice Retrieves the timestamp in which the result to the referred query was solved by the Witnet DON. - /// @dev Fails if the `_queryId` is not in 'Reported' status. - /// @param _queryId The unique query identifier. - function readResponseTimestamp(uint256 _queryId) external view returns (uint256); -} diff --git a/contracts/interfaces/V2/IWitnetBytecodes.sol b/contracts/interfaces/V2/IWitnetBytecodes.sol index 10d7f2c8c..c6d383fec 100644 --- a/contracts/interfaces/V2/IWitnetBytecodes.sol +++ b/contracts/interfaces/V2/IWitnetBytecodes.sol @@ -1,68 +1,50 @@ // SPDX-License-Identifier: MIT - pragma solidity >=0.8.0 <0.9.0; -import "../../libs/WitnetV2.sol"; +import "../../libs/Witnet.sol"; interface IWitnetBytecodes { - function bytecodeOf(bytes32 radHash) external view returns (bytes memory); - function bytecodeOf(bytes32 radHash, bytes32 slahHash) external view returns (bytes memory); + error UnknownRadonRetrieval(bytes32 hash); + error UnknownRadonReducer(bytes32 hash); + error UnknownRadonRequest(bytes32 hash); - function hashOf( - bytes32[] calldata sources, - bytes32 aggregator, - bytes32 tally, - uint16 resultMaxSize, - string[][] calldata args - ) external pure returns (bytes32); - function hashOf(bytes32 radHash, bytes32 slaHash) external pure returns (bytes32 drQueryHash); - function hashWeightWitsOf(bytes32 radHash, bytes32 slaHash) external view returns ( - bytes32 drQueryHash, - uint32 drQueryWeight, - uint256 drQueryWits - ); + 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 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 (WitnetV2.RadonReducer memory); + function lookupRadonReducer(bytes32 hash) external view returns (Witnet.RadonReducer memory); - function lookupRadonRetrieval(bytes32 hash) external view returns (WitnetV2.RadonRetrieval 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 (WitnetV2.RadonDataTypes); + function lookupRadonRetrievalResultDataType(bytes32 hash) external view returns (Witnet.RadonDataTypes); - function lookupRadonRequestAggregator(bytes32 radHash) external view returns (WitnetV2.RadonReducer memory); - function lookupRadonRequestResultMaxSize(bytes32 radHash) external view returns (uint256); - function lookupRadonRequestResultDataType(bytes32 radHash) external view returns (WitnetV2.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 (WitnetV2.RadonReducer memory); + function lookupRadonRequestTally(bytes32 radHash) external view returns (Witnet.RadonReducer memory); - function lookupRadonSLA(bytes32 slaHash) external view returns (WitnetV2.RadonSLA memory); - function lookupRadonSLAReward(bytes32 slaHash) external view returns (uint); + function lookupRadonRAD(bytes32 radHash) external view returns (Witnet.RadonRAD memory); function verifyRadonRetrieval( - WitnetV2.DataRequestMethods requestMethod, - string calldata requestSchema, - string calldata requestAuthority, - string calldata requestPath, - string calldata requestQuery, - string calldata requestBody, - string[2][] calldata requestHeaders, - bytes calldata requestRadonScript - ) external returns (bytes32 hash); - - function verifyRadonRetrieval( - WitnetV2.DataRequestMethods requestMethod, + Witnet.RadonDataRequestMethods requestMethod, string calldata requestURL, string calldata requestBody, string[2][] calldata requestHeaders, bytes calldata requestRadonScript ) external returns (bytes32 hash); - function verifyRadonReducer(WitnetV2.RadonReducer calldata reducer) + function verifyRadonReducer(Witnet.RadonReducer calldata reducer) external returns (bytes32 hash); function verifyRadonRequest( @@ -72,10 +54,12 @@ interface IWitnetBytecodes { uint16 resultMaxSize, string[][] calldata args ) external returns (bytes32 radHash); - - function verifyRadonSLA(WitnetV2.RadonSLA calldata sla) - external returns (bytes32 slaHash); function totalDataProviders() external view returns (uint); + + /// =============================================================================================================== + /// --- Deprecating methods --------------------------------------------------------------------------------------- + + // function lookupRadonSLA(bytes32 slaHash) external view returns (Witnet.RadonSLA memory); } \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetBytecodesErrors.sol b/contracts/interfaces/V2/IWitnetBytecodesErrors.sol deleted file mode 100644 index 84d72e671..000000000 --- a/contracts/interfaces/V2/IWitnetBytecodesErrors.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -interface IWitnetBytecodesErrors { - error UnknownRadonRetrieval(bytes32 hash); - error UnknownRadonReducer(bytes32 hash); - error UnknownRadonRequest(bytes32 hash); - error UnknownRadonSLA(bytes32 hash); -} \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetBytecodesEvents.sol b/contracts/interfaces/V2/IWitnetBytecodesEvents.sol deleted file mode 100644 index 35924f6d8..000000000 --- a/contracts/interfaces/V2/IWitnetBytecodesEvents.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -interface IWitnetBytecodesEvents { - event NewDataProvider(uint256 index); - event NewRadonRetrievalHash(bytes32 hash); - event NewRadonReducerHash(bytes32 hash); - event NewRadHash(bytes32 hash); - event NewSlaHash(bytes32 hash); -} \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetConsumer.sol b/contracts/interfaces/V2/IWitnetConsumer.sol new file mode 100644 index 000000000..bc191d06a --- /dev/null +++ b/contracts/interfaces/V2/IWitnetConsumer.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../../libs/Witnet.sol"; + +interface IWitnetConsumer { + + /// @notice Method to be called from the WitnetRequestBoard contract as soon as the given Witnet `queryId` + /// @notice gets reported, if reported with no errors. + /// @dev It should revert if called from any other address different to the WitnetRequestBoard being used + /// @dev by the WitnetConsumer contract. + /// @param witnetQueryId The unique identifier of the Witnet query being reported. + /// @param witnetResultTallyHash Hash of the commit/reveal witnessing act that took place in the Witnet blockahin. + /// @param witnetResultTimestamp Timestamp at which the reported value was captured by the Witnet blockchain. + /// @param witnetEvmFinalityBlock EVM block at which the provided data can be considered to be final. + /// @param witnetResultCborValue The CBOR-encoded resulting value of the Witnet query being reported. + function reportWitnetQueryResult( + uint256 witnetQueryId, + uint64 witnetResultTimestamp, + bytes32 witnetResultTallyHash, + uint256 witnetEvmFinalityBlock, + WitnetCBOR.CBOR calldata witnetResultCborValue + ) external; + + /// @notice Method to be called from the WitnetRequestBoard contract as soon as the given Witnet `queryId` + /// @notice gets reported, if reported WITH errors. + /// @dev It should revert if called from any other address different to the WitnetRequestBoard being used + /// @dev by the WitnetConsumer contract. + /// @param witnetQueryId The unique identifier of the Witnet query being reported. + /// @param witnetResultTallyHash Hash of the commit/reveal witnessing act that took place in the Witnet blockahin. + /// @param witnetResultTimestamp Timestamp at which the reported value was captured by the Witnet blockchain. + /// @param witnetEvmFinalityBlock EVM block at which the provided data can be considered to be final. + /// @param errorCode The error code enum identifying the error produced during resolution on the Witnet blockchain. + /// @param errorArgs Error arguments, if any. An empty buffer is to be passed if no error arguments apply. + function reportWitnetQueryError( + uint256 witnetQueryId, + uint64 witnetResultTimestamp, + bytes32 witnetResultTallyHash, + uint256 witnetEvmFinalityBlock, + Witnet.ResultErrorCodes errorCode, + WitnetCBOR.CBOR calldata errorArgs + ) external; + + /// @notice Determines if Witnet queries can be reported from given address. + /// @dev In practice, must only be true on the WitnetRequestBoard address that's being used by + /// @dev the WitnetConsumer to post queries. + function reportableFrom(address) external view returns (bool); +} \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetFeeds.sol b/contracts/interfaces/V2/IWitnetFeeds.sol index 56dfa705c..d0721b3df 100644 --- a/contracts/interfaces/V2/IWitnetFeeds.sol +++ b/contracts/interfaces/V2/IWitnetFeeds.sol @@ -2,32 +2,39 @@ pragma solidity >=0.8.0 <0.9.0; +import "../../WitnetBytecodes.sol"; import "../../WitnetRequestBoard.sol"; interface IWitnetFeeds { - function dataType() external view returns (WitnetV2.RadonDataTypes); + + event DeletedFeed(address indexed from, bytes4 indexed feedId, string caption); + event SettledFeed(address indexed from, bytes4 indexed feedId, string caption, bytes32 radHash); + event SettledFeedSolver(address indexed from, bytes4 indexed feedId, string caption, address solver); + event SettledRadonSLA(address indexed from, bytes32 slaHash); + event UpdatingFeed(address indexed from, bytes4 indexed feedId, bytes32 slaHash, uint256 value); + event UpdatingFeedReward(address indexed from, bytes4 indexed feedId, uint256 value); + + function dataType() external view returns (Witnet.RadonDataTypes); function prefix() external view returns (string memory); function registry() external view returns (WitnetBytecodes); function witnet() external view returns (WitnetRequestBoard); function defaultRadonSLA() external view returns (WitnetV2.RadonSLA memory); - - function estimateUpdateBaseFee(bytes4 feedId, uint256 evmGasPrice, uint256 witEvmPrice) external view returns (uint); - function estimateUpdateBaseFee(bytes4 feedId, uint256 evmGasPrice, uint256 witEvmPrice, bytes32 slaHash) external view returns (uint); + function estimateUpdateBaseFee(uint256 evmGasPrice) external view returns (uint); - function latestResponse(bytes4 feedId) external view returns (Witnet.Response memory); + function latestResponse(bytes4 feedId) external view returns (WitnetV2.Response memory); function latestResult(bytes4 feedId) external view returns (Witnet.Result memory); function latestUpdateQueryId(bytes4 feedId) external view returns (uint256); - function latestUpdateRequest(bytes4 feedId) external view returns (Witnet.Request memory); - function latestUpdateResponse(bytes4 feedId) external view returns (Witnet.Response memory); + function latestUpdateRequest(bytes4 feedId) external view returns (bytes32, WitnetV2.RadonSLA memory); + function latestUpdateResponse(bytes4 feedId) external view returns (WitnetV2.Response memory); function latestUpdateResultError(bytes4 feedId) external view returns (Witnet.ResultError memory); - function latestUpdateResultStatus(bytes4 feedId) external view returns (Witnet.ResultStatus); + function latestUpdateResultStatus(bytes4 feedId) external view returns (WitnetV2.ResultStatus); function lookupBytecode(bytes4 feedId) external view returns (bytes memory); function lookupRadHash(bytes4 feedId) external view returns (bytes32); - function lookupRetrievals(bytes4 feedId) external view returns (WitnetV2.RadonRetrieval[] memory); + function lookupRetrievals(bytes4 feedId) external view returns (Witnet.RadonRetrieval[] memory); function requestUpdate(bytes4 feedId) external payable returns (uint256 usedFunds); - function requestUpdate(bytes4 feedId, bytes32 slaHash) external payable returns (uint256 usedFunds); + function requestUpdate(bytes4 feedId, WitnetV2.RadonSLA calldata updateSLA) external payable returns (uint256 usedFunds); } \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetFeedsAdmin.sol b/contracts/interfaces/V2/IWitnetFeedsAdmin.sol index 92f4694fe..9388cddaa 100644 --- a/contracts/interfaces/V2/IWitnetFeedsAdmin.sol +++ b/contracts/interfaces/V2/IWitnetFeedsAdmin.sol @@ -3,13 +3,17 @@ pragma solidity >=0.8.0 <0.9.0; import "../../libs/WitnetV2.sol"; -import "../../requests/WitnetRequest.sol"; +import "../../WitnetRequest.sol"; interface IWitnetFeedsAdmin { + function acceptOwnership() external; function deleteFeed(string calldata caption) external; + function owner() external view returns (address); + function pendingOwner() external returns (address); function settleDefaultRadonSLA(WitnetV2.RadonSLA calldata) external; function settleFeedRequest(string calldata caption, bytes32 radHash) external; function settleFeedRequest(string calldata caption, WitnetRequest request) external; function settleFeedRequest(string calldata caption, WitnetRequestTemplate template, string[][] calldata) external; function settleFeedSolver(string calldata caption, address solver, string[] calldata deps) external; + function transferOwnership(address) external; } \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetFeedsEvents.sol b/contracts/interfaces/V2/IWitnetFeedsEvents.sol deleted file mode 100644 index f619e98ca..000000000 --- a/contracts/interfaces/V2/IWitnetFeedsEvents.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -interface IWitnetFeedsEvents { - event DeletedFeed(address indexed from, bytes4 indexed feedId, string caption); - event SettledFeed(address indexed from, bytes4 indexed feedId, string caption, bytes32 radHash); - event SettledFeedSolver(address indexed from, bytes4 indexed feedId, string caption, address solver); - event SettledRadonSLA(address indexed from, bytes32 slaHash); - event UpdatingFeed(address indexed from, bytes4 indexed feedId, bytes32 slaHash, uint256 value); - event UpdatingFeedReward(address indexed from, bytes4 indexed feedId, uint256 value); -} \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetPriceSolver.sol b/contracts/interfaces/V2/IWitnetPriceSolver.sol index e6068e60e..9cd5ce030 100644 --- a/contracts/interfaces/V2/IWitnetPriceSolver.sol +++ b/contracts/interfaces/V2/IWitnetPriceSolver.sol @@ -8,11 +8,11 @@ interface IWitnetPriceSolver { struct Price { uint value; uint timestamp; - bytes32 drTxHash; - Witnet.ResultStatus status; + bytes32 tallyHash; + WitnetV2.ResultStatus status; } - function class() external pure returns (bytes4); function delegator() external view returns (address); function solve(bytes4 feedId) external view returns (Price memory); + function specs() external pure returns (bytes4); function validate(bytes4 feedId, string[] calldata initdata) external; } \ No newline at end of file diff --git a/contracts/interfaces/V2/IWitnetRequestBoard.sol b/contracts/interfaces/V2/IWitnetRequestBoard.sol new file mode 100644 index 000000000..aa4ec2d16 --- /dev/null +++ b/contracts/interfaces/V2/IWitnetRequestBoard.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0 <0.9.0; + +import "../../libs/WitnetV2.sol"; + +interface IWitnetRequestBoard { + + /// @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 WitnetBytecodes 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, uint96 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 Retrieves the serialized bytecode of a previously posted Witnet Data Request. + /// @dev Fails if the query does not exist. + /// @param queryId The unique query identifier. + function getQueryBytecode(uint256 queryId) external view returns (bytes memory); + + /// @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 (bytes32, WitnetV2.RadonSLA 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 Retrieves the Witnet-provable CBOR-bytes result of a previously posted request. + /// @param queryId The unique query identifier. + function getQueryResult(uint256 queryId) external view returns (Witnet.Result memory); + + /// @notice Returns reference to the commit/reveal act that took place on the Witnet blockchain. + /// @param queryId The unique query identifier. + /// @return witnetTimestamp Timestamp at which the query was solved by the Witnet blockchain. + /// @return witnetTallyHash Hash of the commit/reveal act that solved the query on the Witnet blockchain. + /// @return witnetEvmFinalityBlock EVM block at which the provided data can be considered to be final. + function getQueryResultAuditTrail(uint256 queryId) external view returns ( + uint256 witnetTimestamp, + bytes32 witnetTallyHash, + uint256 witnetEvmFinalityBlock + ); + + /// @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 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 getQueryResultStatus(uint256 queryId) external view returns (WitnetV2.ResultStatus); + + /// @notice Retrieves the reward currently set for the referred query. + /// @dev Fails if the `queryId` is not valid or, if it has already been reported, delivered, or deleted. + /// @param queryId The unique query identifier. + function getQueryReward(uint256 queryId) external view returns (uint256); + + /// @notice Gets current status of given query. + function getQueryStatus(uint256 queryId) external view returns (WitnetV2.QueryStatus); + + // /// @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 WitnetBytecodes 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 `WitnetResponseDeliveryFailed` + /// @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 WitnetBytecodes 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, + uint96 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 `WitnetResponseDeliveryFailed` + /// @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, + uint96 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 upgradeQueryReward(uint256 queryId) external payable; + +} diff --git a/contracts/interfaces/V2/IWitnetRequestBoardEvents.sol b/contracts/interfaces/V2/IWitnetRequestBoardEvents.sol new file mode 100644 index 000000000..0dce1d9b0 --- /dev/null +++ b/contracts/interfaces/V2/IWitnetRequestBoardEvents.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.0 <0.9.0; + +import "../../libs/WitnetV2.sol"; + +interface IWitnetRequestBoardEvents { + + /// Emitted every time a new query containing some verified data request is posted to the WRB. + event WitnetQuery(uint256 indexed id, uint64 witReward, uint256 evmReward); + + /// Emitted when a query with no callback gets reported into the WRB. + event WitnetQueryReported(uint256 indexed id, uint256 evmGasPrice); + + /// Emitted when the reward of some not-yet reported query is upgraded. + event WitnetQueryRewardUpgraded(uint256 indexed id, uint256 evmReward); + + /// Emitted when a query with a callback gets successfully reported into the WRB. + event WitnetResponseDelivered(uint256 indexed id, uint256 evmGasPrice, uint256 evmCallbackGas); + + /// Emitted when a query with a callback cannot get reported into the WRB. + event WitnetResponseDeliveryFailed( + uint256 indexed id, + bytes resultCborBytes, + uint256 evmGasPrice, + uint256 evmCallbackGas, + string evmCallbackRevertReason + ); +} diff --git a/contracts/interfaces/V2/IWitnetRequestBoardReporter.sol b/contracts/interfaces/V2/IWitnetRequestBoardReporter.sol new file mode 100644 index 000000000..3be90abd4 --- /dev/null +++ b/contracts/interfaces/V2/IWitnetRequestBoardReporter.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; + +/// @title The Witnet Request Board Reporter interface. +/// @author The Witnet Foundation. +interface IWitnetRequestBoardReporter { + + /// @notice Estimates the actual earnings (or loss), in WEI, that a reporter would get by reporting result to given query, + /// @notice based on the gas price of the calling transaction. Data requesters should consider upgrading the reward on + /// @notice queries providing no actual earnings. + /// @dev Fails if the query does not exist, or if deleted. + function estimateQueryEarnings(uint256[] calldata queryIds, uint256 gasPrice) external view returns (int256); + + /// @notice Reports the Witnet-provided result to a previously posted request. + /// @dev Will assume `block.timestamp` as the timestamp at which the request was solved. + /// @dev Fails if: + /// @dev - the `_witnetQueryId` is not in 'Posted' status. + /// @dev - provided `_tallyHash` is zero; + /// @dev - length of provided `_result` is zero. + /// @param witnetQueryId The unique identifier of the data request. + /// @param witnetResultTallyHash The hash of the corresponding data request transaction in Witnet. + /// @param witnetResultCborBytes The result itself as bytes. + function reportResult( + uint256 witnetQueryId, + bytes32 witnetResultTallyHash, + bytes calldata witnetResultCborBytes + ) external returns (uint256); + + /// @notice Reports the Witnet-provided result to a previously posted request. + /// @dev Fails if: + /// @dev - called from unauthorized address; + /// @dev - the `_witnetQueryId` is not in 'Posted' status. + /// @dev - provided `_tallyHash` is zero; + /// @dev - length of provided `_result` is zero. + /// @param witnetQueryId The unique query identifier + /// @param witnetResultTimestamp The timestamp of the solving tally transaction in Witnet. + /// @param witnetResultTallyHash The hash of the corresponding data request transaction in Witnet. + /// @param witnetResultCborBytes The result itself as bytes. + function reportResult( + uint256 witnetQueryId, + uint64 witnetResultTimestamp, + bytes32 witnetResultTallyHash, + bytes calldata witnetResultCborBytes + ) external returns (uint256); + + /// @notice Reports Witnet-provided results to multiple requests within a single EVM tx. + /// @dev Must emit a PostedResult event for every succesfully reported result. + /// @param _batchResults Array of BatchResult structs, every one containing: + /// - unique query identifier; + /// - timestamp of the solving tally txs in Witnet. If zero is provided, EVM-timestamp will be used instead; + /// - hash of the corresponding data request tx at the Witnet side-chain level; + /// - data request result in raw bytes. + /// @param _verbose If true, must emit a BatchReportError event for every failing report, if any. + function reportResultBatch(BatchResult[] calldata _batchResults, bool _verbose) external returns (uint256); + + struct BatchResult { + uint256 queryId; + uint64 timestamp; + bytes32 tallyHash; + bytes cborBytes; + } + + event BatchReportError(uint256 queryId, string reason); +} diff --git a/contracts/interfaces/V2/IWitnetRequestFactory.sol b/contracts/interfaces/V2/IWitnetRequestFactory.sol index d706ae9a7..6a48ff8e1 100644 --- a/contracts/interfaces/V2/IWitnetRequestFactory.sol +++ b/contracts/interfaces/V2/IWitnetRequestFactory.sol @@ -2,16 +2,15 @@ pragma solidity >=0.7.0 <0.9.0; -import "../../WitnetBytecodes.sol"; - interface IWitnetRequestFactory { + event WitnetRequestTemplateBuilt(address template, bool parameterized); + function buildRequestTemplate( bytes32[] memory sourcesIds, bytes32 aggregatorId, bytes32 tallyId, uint16 resultDataMaxSize ) external returns (address template); - function class() external view returns (bytes4); - function registry() external view returns (WitnetBytecodes); + } \ No newline at end of file diff --git a/contracts/libs/Create3.sol b/contracts/libs/Create3.sol new file mode 100644 index 000000000..103f02026 --- /dev/null +++ b/contracts/libs/Create3.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +pragma solidity ^0.8.0; + +/// @notice Deploy to deterministic addresses without an initcode factor. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) +/// @author 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) + +library Create3 { + + //--------------------------------------------------------------------------------// + // Opcode | Opcode + Arguments | Description | Stack View // + //--------------------------------------------------------------------------------// + // 0x36 | 0x36 | CALLDATASIZE | size // + // 0x3d | 0x3d | RETURNDATASIZE | 0 size // + // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // + // 0x37 | 0x37 | CALLDATACOPY | // + // 0x36 | 0x36 | CALLDATASIZE | size // + // 0x3d | 0x3d | RETURNDATASIZE | 0 size // + // 0x34 | 0x34 | CALLVALUE | value 0 size // + // 0xf0 | 0xf0 | CREATE | newContract // + //--------------------------------------------------------------------------------// + // Opcode | Opcode + Arguments | Description | Stack View // + //--------------------------------------------------------------------------------// + // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode // + // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode // + // 0x52 | 0x52 | MSTORE | // + // 0x60 | 0x6008 | PUSH1 08 | 8 // + // 0x60 | 0x6018 | PUSH1 18 | 24 8 // + // 0xf3 | 0xf3 | RETURN | // + //--------------------------------------------------------------------------------// + + bytes internal constant CREATE3_FACTORY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3"; + bytes32 internal constant CREATE3_FACTORY_CODEHASH = keccak256(CREATE3_FACTORY_BYTECODE); + + /// @notice Creates a new contract with given `_creationCode` and `_salt` + /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only + /// @param _creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address + /// @return addr of the deployed contract, reverts on error + function deploy(bytes32 _salt, bytes memory _creationCode) + internal + returns (address) + { + return deploy(_salt, _creationCode, 0); + } + + /// @notice Creates a new contract with given `_creationCode`, `_salt` and `_value`. + /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only + /// @param _creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address + /// @param _value In WEI of ETH to be forwarded to child contract + /// @return _deployed The address of the deployed contract. + function deploy(bytes32 _salt, bytes memory _creationCode, uint256 _value) + internal + returns (address _deployed) + { + // Get target final address + _deployed = determineAddr(_salt); + if (_deployed.code.length != 0) revert("Create3: target already exists"); + + // Create factory + address _factory; + bytes memory _factoryBytecode = CREATE3_FACTORY_BYTECODE; + /// @solidity memory-safe-assembly + assembly { + // Deploy a factory contract with our pre-made bytecode via CREATE2. + // We start 32 bytes into the code to avoid copying the byte length. + _factory := create2(0, add(_factoryBytecode, 32), mload(_factoryBytecode), _salt) + } + require(_factory != address(0), "Create3: error creating factory"); + + // Use factory to deploy target + (bool _success, ) = _factory.call{value: _value}(_creationCode); + require(_success && _deployed.code.length != 0, "Create3: error creating target"); + } + + /// @notice Computes the resulting address of a contract deployed using address(this) and the given `_salt` + /// @param _salt Salt of the contract creation, resulting address will be derivated from this value only + /// @return addr of the deployed contract, reverts on error + /// @dev The address creation formula is: keccak256(rlp([keccak256(0xff ++ address(this) ++ _salt ++ keccak256(childBytecode))[12:], 0x01])) + function determineAddr(bytes32 _salt) internal view returns (address) { + address _factory = address( + uint160( + uint256( + keccak256( + abi.encodePacked( + hex'ff', + address(this), + _salt, + CREATE3_FACTORY_CODEHASH + ) + ) + ) + ) + ); + return address( + uint160( + uint256( + keccak256( + abi.encodePacked( + // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ _factory ++ 0x01) + // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) + hex"d6_94", + _factory, + // _factory's nonce on which the target is created: 0x1 + hex"01" + ) + ) + ) + ) + ); + } + +} \ No newline at end of file diff --git a/contracts/libs/Witnet.sol b/contracts/libs/Witnet.sol index 07e50c786..5b2fcfec9 100644 --- a/contracts/libs/Witnet.sol +++ b/contracts/libs/Witnet.sol @@ -3,7 +3,6 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../interfaces/IWitnetRequest.sol"; import "./WitnetCBOR.sol"; library Witnet { @@ -177,15 +176,318 @@ library Witnet { UnhandledIntercept } + /// 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; + } + /// =============================================================================================================== - /// --- 'Witnet.Result' helper methods ---------------------------------------------------------------------------- + /// --- 'uint*' helper methods ------------------------------------------------------------------------------------ - modifier _isError(Result memory result) { - require(!result.success, "Witnet: no actual errors"); - _; + /// @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 bytecode Raw bytes representing a CBOR-encoded value. + /// @return A `Witnet.Result` instance. + function resultFromCborBytes(bytes memory bytecode) + internal pure + returns (Witnet.Result memory) + { + WitnetCBOR.CBOR memory cborValue = WitnetCBOR.fromBytes(bytecode); + 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.Request' helper methods --------------------------------------------------------------------------- + + // function packRequesterCallbackGasLimit(address requester, uint96 callbackGasLimit) internal pure returns (bytes32) { + // return bytes32(uint(bytes32(bytes20(requester))) | callbackGasLimit); + // } + + // function unpackRequester(Request storage self) internal view returns (address) { + // return address(bytes20(self.fromCallbackGas)); + // } + + // function unpackCallbackGasLimit(Request storage self) internal view returns (uint96) { + // return uint96(uint(self.fromCallbackGas)); + // } + + // function unpackRequesterAndCallbackGasLimit(Request storage self) internal view returns (address, uint96) { + // bytes32 _packed = self.fromCallbackGas; + // return (address(bytes20(_packed)), uint96(uint(_packed))); + // } + + + // /// =============================================================================================================== + // /// --- 'Witnet.Response' helper methods -------------------------------------------------------------------------- + + // function packReporterEvmFinalityBlock(address reporter, uint256 evmFinalityBlock) internal pure returns (bytes32) { + // return bytes32(uint(bytes32(bytes20(reporter))) << 96 | uint96(evmFinalityBlock)); + // } + + // function unpackWitnetReporter(Response storage self) internal view returns (address) { + // return address(bytes20(self.fromFinality)); + // } + + // function unpackEvmFinalityBlock(Response storage self) internal view returns (uint256) { + // return uint(uint96(uint(self.fromFinality))); + // } + + // function unpackEvmFinalityBlock(bytes32 fromFinality) internal pure returns (uint256) { + // return uint(uint96(uint(fromFinality))); + // } + + // function unpackWitnetReporterAndEvmFinalityBlock(Response storage self) internal view returns (address, uint256) { + // bytes32 _packed = self.fromFinality; + // return (address(bytes20(_packed)), uint(uint96(uint(_packed)))); + // } + + + /// =============================================================================================================== + /// --- 'Witnet.Result' helper methods ---------------------------------------------------------------------------- + modifier _isReady(Result memory result) { require(result.success, "Witnet: tried to decode value from errored result."); _; @@ -344,168 +646,60 @@ library Witnet { } - /// =============================================================================================================== - /// --- 'bytes' helper methods ------------------------------------------------------------------------------------ - - /// @dev Transform given bytes into a Witnet.Result instance. - /// @param bytecode Raw bytes representing a CBOR-encoded value. - /// @return A `Witnet.Result` instance. - function resultFromCborBytes(bytes memory bytecode) - internal pure - returns (Witnet.Result memory) - { - WitnetCBOR.CBOR memory cborValue = WitnetCBOR.fromBytes(bytecode); - 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); - } - } - - - /// =============================================================================================================== - /// --- 'uint8' 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); - } + // /// =============================================================================================================== + // /// --- 'Witnet.RadonSLA' helper methods -------------------------------------------------------------------------- + + // /// @notice Returns `true` if all witnessing parameters in `b` have same + // /// @notice value or greater than the ones in `a`. + // function equalOrGreaterThan(RadonSLA memory a, RadonSLA memory b) + // internal pure returns (bool) + // { + // return ( + // a.numWitnesses >= b.numWitnesses + // && a.minConsensusPercentage >= b.minConsensusPercentage + // && a.witnessReward >= b.witnessReward + // && a.witnessCollateral >= b.witnessCollateral + // && a.minerCommitRevealFee >= b.minerCommitRevealFee + // ); + // } + + // function isValid(Witnet.RadonSLA memory sla) + // internal pure returns (bool) + // { + // return ( + // sla.witnessReward > 0 + // && sla.numWitnesses > 0 && sla.numWitnesses <= 127 + // && sla.minConsensusPercentage > 50 && sla.minConsensusPercentage < 100 + // && sla.witnessCollateral > 0 + // && sla.witnessCollateral / sla.witnessReward <= 127 + // ); + // } + + // function toBytes32(RadonSLA memory sla) internal pure returns (bytes32) { + // return bytes32( + // uint(sla.witnessReward) + // | sla.witnessCollateral << 64 + // | sla.minerCommitRevealFee << 128 + // | sla.numWitnesses << 248 + // | sla.minConsensusPercentage << 232 + // ); + // } + + // function toRadonSLA(bytes32 _packed) internal pure returns (RadonSLA memory) { + // return RadonSLA({ + // numWitnesses: uint8(uint(_packed >> 248)), + // minConsensusPercentage: uint8(uint(_packed >> 232) & 0xff), + // witnessReward: uint64(uint(_packed) & 0xffffffffffffffff), + // witnessCollateral: uint64(uint(_packed >> 64) & 0xffffffffffffffff), + // minerCommitRevealFee: uint64(uint(_packed >> 128) & 0xffffffffffffffff) + // }); + // } + + // function witnessingWitTotalReward(Witnet.RadonSLA memory sla) + // internal pure returns (uint64) + // { + // return sla.witnessReward * sla.numWitnesses; + // } /// =============================================================================================================== diff --git a/contracts/libs/WitnetEncodingLib.sol b/contracts/libs/WitnetEncodingLib.sol index 15618f9f3..36065dc3b 100644 --- a/contracts/libs/WitnetEncodingLib.sol +++ b/contracts/libs/WitnetEncodingLib.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; -import "./WitnetV2.sol"; +import "./Witnet.sol"; /// @title A library for encoding Witnet Data Requests. /// @author The Witnet Foundation. @@ -13,25 +13,35 @@ library WitnetEncodingLib { using WitnetCBOR for WitnetCBOR.CBOR[]; bytes internal constant WITNET_RADON_OPCODES_RESULT_TYPES = - hex"10ffffffffffffffffffffffffffffff0401ff010203050406071311ff01ffff07ff02ffffffffffffffffffffffffff0703ffffffffffffffffffffffffffff0405070202ff04040404ffffffffffff05070402040205050505ff04ff04ffffff010203050406070101ffffffffffff02ff050404000106060707ffffffffff"; + hex"10ffffffffffffffffffffffffffffff040100010203050406071311ff0101ff07ff02ffffffffffffffffffffffffff070304ff04ffffffffffffff03ffffff0405070202ff0404040403ffffffffff05070402040205050505ff04ff04ffff07010203050406070101ff06ffff06ff0203050404000106060707070701ffff"; // 10ffffffffffffffffffffffffffffff - // 0401ff000203050406070100ff01ffff + // 040100001203050406070100ff0101ff // 07ff02ffffffffffffffffffffffffff - // 0703ffffffffffffffffffffffffffff - // 0405070202ff04040404ffffffffffff + // 070304ff04ffffffffffffff03ffffff + // 0405070202ff0404040403ffffffffff // 05070402040205050505ff04ff04ffff - // ff010203050406070101ffffffffffff - // 02ff050404000106060707ffffffffff + // 07010203050406070101ff06ffff06ff + // 0203050404000106060707070701ffff + + error UnsupportedDataRequestMethod(uint8 method, string schema, string body, string[2][] headers); + error UnsupportedRadonDataType(uint8 datatype, uint256 maxlength); + error UnsupportedRadonFilterOpcode(uint8 opcode); + error UnsupportedRadonFilterArgs(uint8 opcode, bytes args); + error UnsupportedRadonReducerOpcode(uint8 opcode); + error UnsupportedRadonReducerScript(uint8 opcode, bytes script, uint256 offset); + error UnsupportedRadonScript(bytes script, uint256 offset); + error UnsupportedRadonScriptOpcode(bytes script, uint256 cursor, uint8 opcode); + error UnsupportedRadonTallyScript(bytes32 hash); /// =============================================================================================================== - /// --- WitnetLib internal methods -------------------------------------------------------------------------------- + /// --- WitnetEncodingLib internal methods -------------------------------------------------------------------------------- - function size(WitnetV2.RadonDataTypes _type) internal pure returns (uint16) { - if (_type == WitnetV2.RadonDataTypes.Integer - || _type == WitnetV2.RadonDataTypes.Float + function size(Witnet.RadonDataTypes _type) internal pure returns (uint16) { + if (_type == Witnet.RadonDataTypes.Integer + || _type == Witnet.RadonDataTypes.Float ) { return 9; - } else if (_type == WitnetV2.RadonDataTypes.Bool) { + } else if (_type == Witnet.RadonDataTypes.Bool) { return 1; } else { // undetermined @@ -41,7 +51,7 @@ library WitnetEncodingLib { /// =============================================================================================================== - /// --- WitnetLib public methods (if used library will have to linked to calling contracts) ----------------------- + /// --- WitnetEncodingLib public methods (if used library will have to linked to calling contracts) ----------------------- /// @notice Encode bytes array into given major type (UTF-8 not yet supported) /// @param buf Bytes array @@ -131,7 +141,7 @@ library WitnetEncodingLib { } } - function encode(WitnetV2.RadonRetrieval memory source) + function encode(Witnet.RadonRetrieval memory source) public pure returns (bytes memory) { @@ -191,7 +201,7 @@ library WitnetEncodingLib { } function encode( - WitnetV2.RadonRetrieval[] memory sources, + Witnet.RadonRetrieval[] memory sources, string[][] memory args, bytes memory aggregatorInnerBytecode, bytes memory tallyInnerBytecode, @@ -218,11 +228,11 @@ library WitnetEncodingLib { ); } - function encode(WitnetV2.RadonReducer memory reducer) + function encode(Witnet.RadonReducer memory reducer) public pure returns (bytes memory bytecode) { - if (reducer.script.length == 0) { + // if (reducer.script.length == 0) { for (uint ix = 0; ix < reducer.filters.length; ix ++) { bytecode = abi.encodePacked( bytecode, @@ -233,15 +243,15 @@ library WitnetEncodingLib { bytecode, encode(reducer.opcode) ); - } else { - return abi.encodePacked( - encode(uint64(reducer.script.length), bytes1(0x18)), - reducer.script - ); - } + // } else { + // return abi.encodePacked( + // encode(uint64(reducer.script.length), bytes1(0x18)), + // reducer.script + // ); + // } } - function encode(WitnetV2.RadonFilter memory filter) + function encode(Witnet.RadonFilter memory filter) public pure returns (bytes memory bytecode) { @@ -259,7 +269,7 @@ library WitnetEncodingLib { ); } - function encode(WitnetV2.RadonReducerOpcodes opcode) + function encode(Witnet.RadonReducerOpcodes opcode) public pure returns (bytes memory) { @@ -267,7 +277,7 @@ library WitnetEncodingLib { return encode(uint64(opcode), bytes1(0x10)); } - function encode(WitnetV2.RadonSLA memory sla) + function encode(Witnet.RadonSLA memory sla) public pure returns (bytes memory) { @@ -299,7 +309,7 @@ library WitnetEncodingLib { return cbor.buffer.data; } - function replaceWildcards(WitnetV2.RadonRetrieval memory self, string[] memory args) + function replaceWildcards(Witnet.RadonRetrieval memory self, string[] memory args) public pure { self.url = WitnetBuffer.replace(self.url, args); @@ -311,7 +321,7 @@ library WitnetEncodingLib { } function validate( - WitnetV2.DataRequestMethods method, + Witnet.RadonDataRequestMethods method, string memory url, string memory body, string[2][] memory headers, @@ -323,16 +333,16 @@ library WitnetEncodingLib { if (!( bytes(url).length > 0 && ( - method == WitnetV2.DataRequestMethods.HttpGet - || method == WitnetV2.DataRequestMethods.HttpPost - || method == WitnetV2.DataRequestMethods.HttpHead + method == Witnet.RadonDataRequestMethods.HttpGet + || method == Witnet.RadonDataRequestMethods.HttpPost + || method == Witnet.RadonDataRequestMethods.HttpHead ) - || method == WitnetV2.DataRequestMethods.Rng + || method == Witnet.RadonDataRequestMethods.Rng && bytes(url).length == 0 && headers.length == 0 && script.length >= 1 )) { - revert WitnetV2.UnsupportedDataRequestMethod( + revert UnsupportedDataRequestMethod( uint8(method), url, body, @@ -340,170 +350,121 @@ library WitnetEncodingLib { ); } return keccak256(abi.encode(method, url, body, headers, script)); - } - - function validate( - WitnetV2.DataRequestMethods method, - string memory schema, - string memory authority, - string memory path, - string memory query, - string memory body, - string[2][] memory headers, - bytes memory script - ) - public pure - returns (bytes32) - { - if (!( - (method == WitnetV2.DataRequestMethods.HttpGet - || method == WitnetV2.DataRequestMethods.HttpPost - || method == WitnetV2.DataRequestMethods.HttpHead - ) - && bytes(authority).length > 0 - && ( - bytes(schema).length == 0 - || keccak256(bytes(schema)) == keccak256(bytes("https://")) - || keccak256(bytes(schema)) == keccak256(bytes("http://")) - ) - || method == WitnetV2.DataRequestMethods.Rng - && bytes(schema).length == 0 - && bytes(authority).length == 0 - && bytes(path).length == 0 - && bytes(query).length == 0 - && bytes(body).length == 0 - && headers.length == 0 - && script.length >= 1 - )) { - revert WitnetV2.UnsupportedDataRequestMethod( - uint8(method), - schema, - body, - headers - ); - } - return keccak256(abi.encode( - method, - schema, - authority, - path, - query, - body, - headers, - script - )); } function validate( - WitnetV2.RadonDataTypes dataType, + Witnet.RadonDataTypes dataType, uint16 maxDataSize ) public pure returns (uint16) { if ( - dataType == WitnetV2.RadonDataTypes.Any - || dataType == WitnetV2.RadonDataTypes.String - || dataType == WitnetV2.RadonDataTypes.Bytes - || dataType == WitnetV2.RadonDataTypes.Array - || dataType == WitnetV2.RadonDataTypes.Map + dataType == Witnet.RadonDataTypes.Any + || dataType == Witnet.RadonDataTypes.String + || dataType == Witnet.RadonDataTypes.Bytes + || dataType == Witnet.RadonDataTypes.Array + || dataType == Witnet.RadonDataTypes.Map ) { - if (/*maxDataSize == 0 ||*/maxDataSize > 2048) { - revert WitnetV2.UnsupportedRadonDataType( + if (maxDataSize == 0) { + revert UnsupportedRadonDataType( uint8(dataType), maxDataSize ); } - return maxDataSize; + return maxDataSize + 3; // TODO: determine CBOR-encoding length overhead } else if ( - dataType == WitnetV2.RadonDataTypes.Integer - || dataType == WitnetV2.RadonDataTypes.Float - || dataType == WitnetV2.RadonDataTypes.Bool + dataType == Witnet.RadonDataTypes.Integer + || dataType == Witnet.RadonDataTypes.Float + || dataType == Witnet.RadonDataTypes.Bool ) { - return 0; // TBD: size(dataType); + return 9; } else { - revert WitnetV2.UnsupportedRadonDataType( + revert UnsupportedRadonDataType( uint8(dataType), size(dataType) ); } } - function validate(WitnetV2.RadonFilter memory filter) + function validate(Witnet.RadonFilter memory filter) public pure { if ( - filter.opcode == WitnetV2.RadonFilterOpcodes.StandardDeviation + filter.opcode == Witnet.RadonFilterOpcodes.StandardDeviation ) { // check filters that require arguments if (filter.args.length == 0) { - revert WitnetV2.RadonFilterMissingArgs(uint8(filter.opcode)); + revert UnsupportedRadonFilterArgs(uint8(filter.opcode), filter.args); } } else if ( - filter.opcode == WitnetV2.RadonFilterOpcodes.Mode + filter.opcode == Witnet.RadonFilterOpcodes.Mode ) { // check filters that don't require any arguments if (filter.args.length > 0) { - revert WitnetV2.UnsupportedRadonFilterArgs(uint8(filter.opcode), filter.args); + revert UnsupportedRadonFilterArgs(uint8(filter.opcode), filter.args); } } else { // reject unsupported opcodes - revert WitnetV2.UnsupportedRadonFilterOpcode(uint8(filter.opcode)); + revert UnsupportedRadonFilterOpcode(uint8(filter.opcode)); } } - function validate(WitnetV2.RadonReducer memory reducer) + function validate(Witnet.RadonReducer memory reducer) public pure { - if (reducer.script.length == 0) { + // if (reducer.script.length == 0) { if (!( - reducer.opcode == WitnetV2.RadonReducerOpcodes.AverageMean - || reducer.opcode == WitnetV2.RadonReducerOpcodes.StandardDeviation - || reducer.opcode == WitnetV2.RadonReducerOpcodes.Mode - || reducer.opcode == WitnetV2.RadonReducerOpcodes.ConcatenateAndHash - || reducer.opcode == WitnetV2.RadonReducerOpcodes.AverageMedian + reducer.opcode == Witnet.RadonReducerOpcodes.AverageMean + || reducer.opcode == Witnet.RadonReducerOpcodes.StandardDeviation + || reducer.opcode == Witnet.RadonReducerOpcodes.Mode + || reducer.opcode == Witnet.RadonReducerOpcodes.ConcatenateAndHash + || reducer.opcode == Witnet.RadonReducerOpcodes.AverageMedian )) { - revert WitnetV2.UnsupportedRadonReducerOpcode(uint8(reducer.opcode)); + revert UnsupportedRadonReducerOpcode(uint8(reducer.opcode)); } for (uint ix = 0; ix < reducer.filters.length; ix ++) { validate(reducer.filters[ix]); } - } else { - if (uint8(reducer.opcode) != 0xff || reducer.filters.length > 0) { - revert WitnetV2.UnsupportedRadonReducerScript( - uint8(reducer.opcode), - reducer.script, - 0 - ); - } - } + // } else { + // if (uint8(reducer.opcode) != 0xff || reducer.filters.length > 0) { + // revert UnsupportedRadonReducerScript( + // uint8(reducer.opcode), + // reducer.script, + // 0 + // ); + // } + // } } - function validate(WitnetV2.RadonSLA memory sla) + function validate(Witnet.RadonSLA memory sla) public pure { if (sla.witnessReward == 0) { - revert WitnetV2.RadonSlaNoReward(); + revert("WitnetEncodingLib: invalid SLA: no reward"); } if (sla.numWitnesses == 0) { - revert WitnetV2.RadonSlaNoWitnesses(); + revert("WitnetEncodingLib: invalid SLA: no witnesses"); } else if (sla.numWitnesses > 127) { - revert WitnetV2.RadonSlaTooManyWitnesses(sla.numWitnesses); + revert("WitnetEncodingLib: invalid SLA: too many witnesses (>127)"); } if ( sla.minConsensusPercentage < 51 || sla.minConsensusPercentage > 99 ) { - revert WitnetV2.RadonSlaConsensusOutOfRange(sla.minConsensusPercentage); + revert("WitnetEncodingLib: invalid SLA: consensus percentage out of range"); + } + if (sla.witnessCollateral > 0) { + revert("WitnetEncodingLib: invalid SLA: no collateral"); } - if (sla.witnessCollateral < 10 ** 9) { - revert WitnetV2.RadonSlaLowCollateral(sla.witnessCollateral); + if (sla.witnessCollateral / sla.witnessReward > 127) { + revert("WitnetEncodingLib: invalid SLA: collateral/reward ratio too high (>127)"); } } function verifyRadonScriptResultDataType(bytes memory script) public pure - returns (WitnetV2.RadonDataTypes) + returns (Witnet.RadonDataTypes) { return _verifyRadonScriptResultDataType( WitnetCBOR.fromBytes(script), @@ -513,7 +474,7 @@ library WitnetEncodingLib { /// =============================================================================================================== - /// --- WitnetLib private methods --------------------------------------------------------------------------------- + /// --- WitnetEncodingLib private methods --------------------------------------------------------------------------------- function _replaceCborWildcards( WitnetCBOR.CBOR memory self, @@ -538,7 +499,7 @@ library WitnetEncodingLib { function _verifyRadonScriptResultDataType(WitnetCBOR.CBOR memory self, bool flip) private pure - returns (WitnetV2.RadonDataTypes) + returns (Witnet.RadonDataTypes) { if (self.majorType == WitnetCBOR.MAJOR_TYPE_ARRAY) { WitnetCBOR.CBOR[] memory items = self.readArray(); @@ -548,7 +509,7 @@ library WitnetEncodingLib { : _verifyRadonScriptResultDataType(items[items.length - 2], true) ; } else { - return WitnetV2.RadonDataTypes.Any; + return Witnet.RadonDataTypes.Any; } } else if (self.majorType == WitnetCBOR.MAJOR_TYPE_INT) { uint cursor = self.buffer.cursor; @@ -557,14 +518,14 @@ library WitnetEncodingLib { ? 0xff : uint8(WITNET_RADON_OPCODES_RESULT_TYPES[opcode]) ); - if (dataType > uint8(type(WitnetV2.RadonDataTypes).max)) { - revert WitnetV2.UnsupportedRadonScriptOpcode( + if (dataType > uint8(type(Witnet.RadonDataTypes).max)) { + revert UnsupportedRadonScriptOpcode( self.buffer.data, cursor, uint8(opcode) ); } - return WitnetV2.RadonDataTypes(dataType); + return Witnet.RadonDataTypes(dataType); } else { revert WitnetCBOR.UnexpectedMajorType( WitnetCBOR.MAJOR_TYPE_INT, diff --git a/contracts/libs/WitnetErrorsLib.sol b/contracts/libs/WitnetErrorsLib.sol index 54c017569..d32ee65e5 100644 --- a/contracts/libs/WitnetErrorsLib.sol +++ b/contracts/libs/WitnetErrorsLib.sol @@ -3,7 +3,7 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "./Witnet.sol"; +import "./WitnetV2.sol"; /// @title A library for interpreting Witnet resolution errors /// @author The Witnet Foundation. @@ -28,6 +28,25 @@ library WitnetErrorsLib { ); } + function asResultError(WitnetV2.ResultStatus _status, bytes memory _cborBytes) + public pure + returns (Witnet.ResultError memory) + { + if (_status == WitnetV2.ResultStatus.Awaiting) { + return Witnet.ResultError({ + code: Witnet.ResultErrorCodes.Unknown, + reason: "WitnetRequestBoard: not yet solved" + }); + } else if (_status == WitnetV2.ResultStatus.Void) { + return Witnet.ResultError({ + code: Witnet.ResultErrorCodes.Unknown, + reason: "WitnetRequestBoard: unknown query" + }); + } else { + return resultErrorFromCborBytes(_cborBytes); + } + } + /// @notice Extract error code and description string from given CBOR-encoded value. /// @dev Client contracts should wrap this function into a try-catch foreseeing potential parsing errors. /// @return _error Witnet.ResultError data struct containing error code and description. diff --git a/contracts/libs/WitnetPriceFeedsLib.sol b/contracts/libs/WitnetPriceFeedsLib.sol index 44ed75b09..b16bf2ce5 100644 --- a/contracts/libs/WitnetPriceFeedsLib.sol +++ b/contracts/libs/WitnetPriceFeedsLib.sol @@ -6,9 +6,9 @@ pragma experimental ABIEncoderV2; import "../interfaces/V2/IWitnetPriceSolver.sol"; import "../interfaces/V2/IWitnetPriceSolverDeployer.sol"; -import "./Slices.sol"; +import "../libs/Slices.sol"; -/// @title Ancillary external library for WitnetPriceFeeds implementations. +/// @title Ancillary deployable library for WitnetPriceFeeds. /// @dev Features: /// @dev - deployment of counter-factual IWitnetPriceSolver instances. /// @dev - validation of feed caption strings. @@ -39,7 +39,7 @@ library WitnetPriceFeedsLib { } assert(_solver == _createdContract); require( - IWitnetPriceSolver(_solver).class() == type(IWitnetPriceSolver).interfaceId, + IWitnetPriceSolver(_solver).specs() == type(IWitnetPriceSolver).interfaceId, "WitnetPriceFeedsLib: uncompliant solver implementation" ); } diff --git a/contracts/libs/WitnetV2.sol b/contracts/libs/WitnetV2.sol index 4b9c0912c..13e0f1285 100644 --- a/contracts/libs/WitnetV2.sol +++ b/contracts/libs/WitnetV2.sol @@ -6,208 +6,182 @@ import "./Witnet.sol"; library WitnetV2 { - error IndexOutOfBounds(uint256 index, uint256 range); - error InsufficientBalance(uint256 weiBalance, uint256 weiExpected); - error InsufficientFee(uint256 weiProvided, uint256 weiExpected); - error Unauthorized(address violator); + /// Struct containing both request and response data related to every query posted to the Witnet Request Board + struct Query { + Request request; + Response response; + } - error RadonFilterMissingArgs(uint8 opcode); + /// Possible status of a Witnet query. + enum QueryStatus { + Unknown, + Posted, + Reported, + Undeliverable, + Finalized + } - error RadonRequestNoSources(); - error RadonRequestSourcesArgsMismatch(uint expected, uint actual); - error RadonRequestMissingArgs(uint index, uint expected, uint actual); - error RadonRequestResultsMismatch(uint index, uint8 read, uint8 expected); - error RadonRequestTooHeavy(bytes bytecode, uint weight); + /// Data kept in EVM-storage for every Request posted to the Witnet Request Board. + struct Request { + bytes32 fromCallbackGas; // Packed: contains requester address in most significant bytes20, + // and max callback gas limit if a callback is required. + bytes32 SLA; // Packed: Service-Level Aggreement parameters upon which the data request + // will be solved by the Witnet blockchain. + bytes32 RAD; // Verified hash of the actual data request to be solved by the Witnet blockchain. + uint256 reserved1; // Reserved uint256 slot. + uint256 evmReward; // EVM reward to be paid to the relayer of the Witnet resolution to the data request. + bytes bytecode; // Raw bytecode of the data request to be solved by the Witnet blockchain (only if not yet verified). + } - error RadonSlaNoReward(); - error RadonSlaNoWitnesses(); - error RadonSlaTooManyWitnesses(uint256 numWitnesses); - error RadonSlaConsensusOutOfRange(uint256 percentage); - error RadonSlaLowCollateral(uint256 witnessCollateral); + /// Data kept in EVM-storage containing Witnet-provided response metadata and result. + struct Response { + bytes32 fromFinality; // Packed: contains address from which the result to the data request was reported, and + // the EVM block at which the provided result can be considered to be final. + uint256 timestamp; // Timestamp at which data from data sources were retrieved by the Witnet blockchain. + bytes32 tallyHash; // Hash of the Witnet commit/reveal act that solved the data request. + bytes cborBytes; // CBOR-encoded result to the data request, as resolved by the Witnet blockchain. + } - error UnsupportedDataRequestMethod(uint8 method, string schema, string body, string[2][] headers); - error UnsupportedRadonDataType(uint8 datatype, uint256 maxlength); - error UnsupportedRadonFilterOpcode(uint8 opcode); - error UnsupportedRadonFilterArgs(uint8 opcode, bytes args); - error UnsupportedRadonReducerOpcode(uint8 opcode); - error UnsupportedRadonReducerScript(uint8 opcode, bytes script, uint256 offset); - error UnsupportedRadonScript(bytes script, uint256 offset); - error UnsupportedRadonScriptOpcode(bytes script, uint256 cursor, uint8 opcode); - error UnsupportedRadonTallyScript(bytes32 hash); + /// Final query's result status from a requester's point of view. + enum ResultStatus { + Void, + Awaiting, + Ready, + Error, + AwaitingReady, + AwaitingError + } - function toEpoch(uint _timestamp) internal pure returns (uint) { - return 1 + (_timestamp - 11111) / 15; + struct RadonSLA { + /// @dev Number of witnessing nodes that will take part in the resolution + /// @dev of a data request within the Witnet blockchain: + uint8 witnessingCommitteeSize; + + /// @dev Total reward in $nanoWIT that will be equally distributed to all nodes + /// @dev involved in the resolution of a data request in the Witnet blockchain: + uint64 witnessingWitTotalReward; } - function toTimestamp(uint _epoch) internal pure returns (uint) { - return 111111+ _epoch * 15; + /// =============================================================================================================== + /// --- 'WitnetV2.Request' helper methods ------------------------------------------------------------------------- + + function packRequesterCallbackGasLimit(address requester, uint96 callbackGasLimit) internal pure returns (bytes32) { + return bytes32(uint(bytes32(bytes20(requester))) | callbackGasLimit); } - struct Beacon { - uint256 escrow; - uint256 evmBlock; - uint256 gasprice; - address relayer; - address slasher; - uint256 superblockIndex; - uint256 superblockRoot; + function unpackRequester(Request storage self) internal view returns (address) { + return address(bytes20(self.fromCallbackGas)); } - enum BeaconStatus { - Idle + function unpackCallbackGasLimit(Request storage self) internal view returns (uint96) { + return uint96(uint(self.fromCallbackGas)); } - struct Block { - bytes32 blockHash; - bytes32 drTxsRoot; - bytes32 drTallyTxsRoot; + function unpackRequesterAndCallbackGasLimit(Request storage self) internal view returns (address, uint96) { + bytes32 _packed = self.fromCallbackGas; + return (address(bytes20(_packed)), uint96(uint(_packed))); } + - enum BlockStatus { - Idle + /// =============================================================================================================== + /// --- 'WitnetV2.Response' helper methods ------------------------------------------------------------------------ + + function packReporterEvmFinalityBlock(address reporter, uint256 evmFinalityBlock) internal pure returns (bytes32) { + return bytes32(uint(bytes32(bytes20(reporter))) << 96 | uint96(evmFinalityBlock)); } - struct DrPost { - uint256 block; - DrPostStatus status; - DrPostRequest request; - DrPostResponse response; + function unpackWitnetReporter(Response storage self) internal view returns (address) { + return address(bytes20(self.fromFinality)); } - - /// Data kept in EVM-storage for every Request posted to the Witnet Request Board. - struct DrPostRequest { - uint256 epoch; - address requester; - address reporter; - bytes32 radHash; - bytes32 slaHash; - uint256 weiReward; + + function unpackEvmFinalityBlock(Response storage self) internal view returns (uint256) { + return uint(uint96(uint(self.fromFinality))); } - /// Data kept in EVM-storage containing Witnet-provided response metadata and result. - struct DrPostResponse { - address disputer; - address reporter; - uint256 escrowed; - uint256 drCommitTxEpoch; - uint256 drTallyTxEpoch; - bytes32 drTallyTxHash; - bytes drTallyResultCborBytes; + function unpackEvmFinalityBlock(bytes32 fromFinality) internal pure returns (uint256) { + return uint(uint96(uint(fromFinality))); } - enum DrPostStatus { - Void, - Deleted, - Expired, - Posted, - Disputed, - Reported, - Finalized, - Accepted, - Rejected - } - - struct DataProvider { - string authority; - uint256 totalEndpoints; - mapping (uint256 => bytes32) endpoints; - } - - enum DataRequestMethods { - /* 0 */ Unknown, - /* 1 */ HttpGet, - /* 2 */ Rng, - /* 3 */ HttpPost, - /* 4 */ HttpHead - } - - 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 - } - - struct RadonFilter { - RadonFilterOpcodes opcode; - bytes args; - } - - enum RadonFilterOpcodes { - /* 0x00 */ GreaterThan, - /* 0x01 */ LessThan, - /* 0x02 */ Equals, - /* 0x03 */ AbsoluteDeviation, - /* 0x04 */ RelativeDeviation, - /* 0x05 */ StandardDeviation, - /* 0x06 */ Top, - /* 0x07 */ Bottom, - /* 0x08 */ Mode, - /* 0x09 */ LessOrEqualThan - } - - struct RadonReducer { - RadonReducerOpcodes opcode; - RadonFilter[] filters; - bytes script; - } - - enum RadonReducerOpcodes { - /* 0x00 */ Minimum, - /* 0x01 */ Maximum, - /* 0x02 */ Mode, - /* 0x03 */ AverageMean, - /* 0x04 */ AverageMeanWeighted, - /* 0x05 */ AverageMedian, - /* 0x06 */ AverageMedianWeighted, - /* 0x07 */ StandardDeviation, - /* 0x08 */ AverageDeviation, - /* 0x09 */ MedianDeviation, - /* 0x0A */ MaximumDeviation, - /* 0x0B */ ConcatenateAndHash - } - - struct RadonRetrieval { - uint8 argsCount; - DataRequestMethods method; - RadonDataTypes resultDataType; - string url; - string body; - string[2][] headers; - bytes script; + function unpackWitnetReporterAndEvmFinalityBlock(Response storage self) internal view returns (address, uint256) { + bytes32 _packed = self.fromFinality; + return (address(bytes20(_packed)), uint(uint96(uint(_packed)))); } - struct RadonSLA { - uint numWitnesses; - uint minConsensusPercentage; - uint witnessReward; - uint witnessCollateral; - uint minerCommitRevealFee; - } - - /// @notice Returns `true` if all witnessing parameters in `b` have same - /// @notice value or greater than the ones in `a`. - function equalOrGreaterThan(RadonSLA memory a, RadonSLA memory b) - internal pure - returns (bool) + + /// =============================================================================================================== + /// --- 'WitnetV2.RadonSLA' helper methods ------------------------------------------------------------------------ + + function equalOrGreaterThan(RadonSLA memory a, RadonSLA memory b) + internal pure returns (bool) { + return (a.witnessingCommitteeSize >= b.witnessingCommitteeSize); + } + + function isValid(RadonSLA calldata sla) internal pure returns (bool) { return ( - a.numWitnesses >= b.numWitnesses - && a.minConsensusPercentage >= b.minConsensusPercentage - && a.witnessReward >= b.witnessReward - && a.witnessCollateral >= b.witnessCollateral - && a.minerCommitRevealFee >= b.minerCommitRevealFee + sla.witnessingWitTotalReward > 0 + && sla.witnessingCommitteeSize > 0 && sla.witnessingCommitteeSize <= 127 ); } + function toBytes32(RadonSLA memory sla) internal pure returns (bytes32) { + return bytes32( + uint(sla.witnessingCommitteeSize) << 248 + // | uint(sla.witnessingCollateralRatio) << 240 + // | uint(sla.witnessingNotBeforeTimestamp) << 64 + | uint(sla.witnessingWitTotalReward) + ); + } + + function toRadonSLA(bytes32 _packed) + internal pure returns (RadonSLA memory) + { + return RadonSLA({ + witnessingCommitteeSize: uint8(uint(_packed) >> 248), + // witnessingCollateralRatio: uint8(uint(_packed) >> 240), + // witnessingNotBeforeTimestamp: uint64(uint(_packed) >> 64), + witnessingWitTotalReward: uint64(uint(_packed)) + }); + } + + function witnessingWitTotalReward(bytes32 _packed) internal pure returns (uint64) { + return uint64(uint(_packed)); + } + + uint256 internal constant _WITNET_GENESIS_TIMESTAMP = 1602666045; + uint256 internal constant _WITNET_GENESIS_EPOCH_SECONDS = 45; + + uint256 internal constant _WITNET_2_0_EPOCH = 1234567; + uint256 internal constant _WITNET_2_0_EPOCH_SECONDS = 30; + uint256 internal constant _WITNET_2_0_TIMESTAMP = _WITNET_GENESIS_TIMESTAMP + _WITNET_2_0_EPOCH * _WITNET_GENESIS_EPOCH_SECONDS; + + function timestampToWitnetEpoch(uint _timestamp) internal pure returns (uint) { + if (_timestamp > _WITNET_2_0_TIMESTAMP ) { + return ( + _WITNET_2_0_EPOCH + ( + _timestamp - _WITNET_2_0_TIMESTAMP + ) / _WITNET_2_0_EPOCH_SECONDS + ); + } else if (_timestamp > _WITNET_GENESIS_TIMESTAMP) { + return ( + 1 + ( + _timestamp - _WITNET_GENESIS_TIMESTAMP + ) / _WITNET_GENESIS_EPOCH_SECONDS + ); + } else { + return 0; + } + } + + function witnetEpochToTimestamp(uint _epoch) internal pure returns (uint) { + if (_epoch >= _WITNET_2_0_EPOCH) { + return ( + _WITNET_2_0_TIMESTAMP + ( + _epoch - _WITNET_2_0_EPOCH + ) * _WITNET_2_0_EPOCH_SECONDS + ); + } else { + return (_WITNET_GENESIS_TIMESTAMP + _epoch * _WITNET_GENESIS_EPOCH_SECONDS); + } + } } \ No newline at end of file diff --git a/contracts/mocks/WitnetMockedBytecodes.sol b/contracts/mocks/WitnetMockedBytecodes.sol new file mode 100644 index 000000000..144738cbd --- /dev/null +++ b/contracts/mocks/WitnetMockedBytecodes.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../core/defaults/WitnetBytecodesDefault.sol"; + +/// @title Mocked implementation of `WitnetBytecodes`. +/// @dev TO BE USED ONLY ON DEVELOPMENT ENVIRONMENTS. +/// @dev ON SUPPORTED TESTNETS AND MAINNETS, PLEASE USE +/// @dev THE `WitnetBytecodes` CONTRACT ADDRESS PROVIDED +/// @dev BY THE WITNET FOUNDATION. +contract WitnetMockedBytecodes is WitnetBytecodesDefault { + constructor() + WitnetBytecodesDefault( + false, + bytes32("mocked") + ) + {} +} diff --git a/contracts/mocks/WitnetMockedPriceFeeds.sol b/contracts/mocks/WitnetMockedPriceFeeds.sol new file mode 100644 index 000000000..b16e883a0 --- /dev/null +++ b/contracts/mocks/WitnetMockedPriceFeeds.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../apps/WitnetPriceFeeds.sol"; + +/// @title Mocked implementation of `WitnetPriceFeeds`. +/// @dev TO BE USED ONLY ON DEVELOPMENT ENVIRONMENTS. +/// @dev ON SUPPORTED TESTNETS AND MAINNETS, PLEASE USE +/// @dev THE `WitnetPriceFeeds` CONTRACT ADDRESS PROVIDED +/// @dev BY THE WITNET FOUNDATION. +contract WitnetMockedPriceFeeds is WitnetPriceFeeds { + constructor(WitnetRequestBoard _wrb) + WitnetPriceFeeds( + msg.sender, + _wrb + ) + {} +} diff --git a/contracts/impls/mocks/WitnetRandomnessMock.sol b/contracts/mocks/WitnetMockedRandomness.sol similarity index 85% rename from contracts/impls/mocks/WitnetRandomnessMock.sol rename to contracts/mocks/WitnetMockedRandomness.sol index 3a5232eb9..e77d04c55 100644 --- a/contracts/impls/mocks/WitnetRandomnessMock.sol +++ b/contracts/mocks/WitnetMockedRandomness.sol @@ -3,23 +3,22 @@ pragma solidity >=0.7.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../apps/WitnetRandomnessProxiable.sol"; +import "../apps/WitnetRandomness.sol"; -/// @title WitnetRandomness mock contract implementation. +/// @title Mocked implementation of `WitnetRandomness`. /// @dev TO BE USED ONLY ON DEVELOPMENT ENVIRONMENTS. -/// @dev ON SUPPORTED TESTNETS, PLEASE USE THE `WitnetRandomness` -/// @dev CONTRACT ADDRESS PROVIDED BY THE WITNET FOUNDATION. -/// @dev SEE: https://docs.witnet.io/smart-contracts/witnet-randomness-oracle/contract-addresses -/// @author Witnet Foundation. -contract WitnetRandomnessMock +/// @dev ON SUPPORTED TESTNETS AND MAINNETS, PLEASE USE +/// @dev THE `WitnetRandomness` CONTRACT ADDRESS PROVIDED +/// @dev BY THE WITNET FOUNDATION. +contract WitnetMockedRandomness is - WitnetRandomnessProxiable + WitnetRandomness { uint8 internal __mockRandomizeLatencyBlocks; uint256 internal __mockRandomizeFee; uint256 internal __mockRandomizeLatestId; - /// Constructor: new WitnetRandomnessMock contract + /// Constructor: new WitnetMockedRandomness contract /// @param _mockRandomizeLatencyBlocks Mocked number of blocks in which a new randomness will be provided after `randomize()` /// @param _mockRandomizeFee Mocked randomize fee (will be constant no matter what tx gas price is provided). constructor ( @@ -27,10 +26,7 @@ contract WitnetRandomnessMock uint8 _mockRandomizeLatencyBlocks, uint256 _mockRandomizeFee ) - WitnetRandomnessProxiable( - _wrb, - bytes32("mocked") - ) + WitnetRandomness(msg.sender, _wrb) { __mockRandomizeLatencyBlocks = _mockRandomizeLatencyBlocks; __mockRandomizeFee = _mockRandomizeFee; @@ -48,7 +44,6 @@ contract WitnetRandomnessMock /// Retrieves data of a randomization request that got successfully posted to the WRB within a given block. /// @dev Returns zero values if no randomness request was actually posted within a given block. /// @param _block Block number whose randomness request is being queried for. - /// @return _from Address from which the latest randomness request was posted. /// @return _id Unique request identifier as provided by the WRB. /// @return _prevBlock Block number in which a randomness request got posted just before this one. 0 if none. /// @return _nextBlock Block number in which a randomness request got posted just after this one, 0 if none. @@ -56,7 +51,6 @@ contract WitnetRandomnessMock external view virtual override returns ( - address _from, uint256 _id, uint256 _prevBlock, uint256 _nextBlock @@ -64,7 +58,6 @@ contract WitnetRandomnessMock { RandomizeData storage _data = __randomize_[_block]; _id = _data.witnetQueryId; - _from = _data.from; _prevBlock = _data.prevBlock; _nextBlock = _data.nextBlock; } @@ -83,12 +76,12 @@ contract WitnetRandomnessMock virtual override returns (bytes32) { - if (__randomize_[_block].from == address(0)) { + if (__randomize_[_block].witnetQueryId == 0) { _block = getRandomnessNextBlock(_block); } uint256 _queryId = __randomize_[_block].witnetQueryId; - require(_queryId != 0, "WitnetRandomnessMock: not randomized"); - require(block.number >= _block + __mockRandomizeLatencyBlocks, "WitnetRandomnessMock: pending randomize"); + require(_queryId != 0, "WitnetMockedRandomness: not randomized"); + require(block.number >= _block + __mockRandomizeLatencyBlocks, "WitnetMockedRandomness: pending randomize"); return blockhash(_block); } @@ -121,12 +114,11 @@ contract WitnetRandomnessMock _usedFunds = __mockRandomizeFee; require( msg.value >= _usedFunds, - "WitnetRandomnessMock: reward too low" + "WitnetMockedRandomness: insufficient reward" ); // Post the Witnet Randomness request: uint _queryId = ++ __mockRandomizeLatestId; RandomizeData storage _data = __randomize_[block.number]; - _data.from = msg.sender; _data.witnetQueryId = _queryId; // Update block links: uint256 _prevBlock = latestRandomizeBlock; diff --git a/contracts/mocks/WitnetMockedRequestBoard.sol b/contracts/mocks/WitnetMockedRequestBoard.sol new file mode 100644 index 000000000..f429060b6 --- /dev/null +++ b/contracts/mocks/WitnetMockedRequestBoard.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./WitnetMockedBytecodes.sol"; +import "./WitnetMockedRequestFactory.sol"; +import "../core/defaults/WitnetRequestBoardTrustableDefault.sol"; + +import "./WitnetMockedPriceFeeds.sol"; + +/// @title Mocked implementation of `WitnetRequestBoard`. +/// @dev TO BE USED ONLY ON DEVELOPMENT ENVIRONMENTS. +/// @dev ON SUPPORTED TESTNETS AND MAINNETS, PLEASE USE +/// @dev THE `WitnetRequestBoard` CONTRACT ADDRESS PROVIDED +/// @dev BY THE WITNET FOUNDATION. +contract WitnetMockedRequestBoard + is + WitnetRequestBoardTrustableDefault +{ + WitnetRequestFactory private __factory; + + constructor(WitnetMockedBytecodes _registry) + WitnetRequestBoardTrustableDefault( + WitnetRequestFactory(address(0)), + WitnetBytecodes(address(_registry)), + false, + bytes32("mocked"), + 60000, 65000, 70000, 20000 + ) + { + __acls().isReporter_[msg.sender] = true; + } + + function factory() override public view returns (WitnetRequestFactory) { + return __factory; + } + + function setFactory(WitnetMockedRequestFactory _factory) external onlyOwner { + __factory = WitnetRequestFactory(address(_factory)); + } +} \ No newline at end of file diff --git a/contracts/mocks/WitnetMockedRequestFactory.sol b/contracts/mocks/WitnetMockedRequestFactory.sol new file mode 100644 index 000000000..bfabbba44 --- /dev/null +++ b/contracts/mocks/WitnetMockedRequestFactory.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./WitnetMockedRequestBoard.sol"; +import "../core/defaults/WitnetRequestFactoryDefault.sol"; + +/// @title Mocked implementation of `WitnetRequestFactory`. +/// @dev TO BE USED ONLY ON DEVELOPMENT ENVIRONMENTS. +/// @dev ON SUPPORTED TESTNETS AND MAINNETS, PLEASE USE +/// @dev THE `WitnetRequestFactory` CONTRACT ADDRESS PROVIDED +/// @dev BY THE WITNET FOUNDATION. +contract WitnetMockedRequestFactory + is + WitnetRequestFactoryDefault +{ + constructor (WitnetMockedRequestBoard _wrb) + WitnetRequestFactoryDefault( + WitnetRequestBoard(address(_wrb)), + WitnetBytecodes(_wrb.registry()), + false, + bytes32("mocked") + ) + {} +} \ No newline at end of file diff --git a/contracts/patterns/Create2Factory.sol b/contracts/patterns/Create2Factory.sol deleted file mode 100644 index 8456e590a..000000000 --- a/contracts/patterns/Create2Factory.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.0 <0.9.0; - -/// @title Based on Singleton Factory (EIP-2470), authored by Guilherme Schmidt (Status Research & Development GmbH) -/// @notice Exposes CREATE2 (EIP-1014) to deploy bytecode on deterministic addresses based on initialization code and salt. - -contract Create2Factory { - - /// @notice Deploys `_initCode` using `_salt` for defining the deterministic address. - /// @param _initCode Initialization code. - /// @param _salt Arbitrary value to modify resulting address. - /// @return createdContract Created contract address. - function deploy(bytes memory _initCode, bytes32 _salt) - public - returns (address payable createdContract) - { - assembly { - createdContract := create2(0, add(_initCode, 0x20), mload(_initCode), _salt) - } - } - - /// @notice Determine singleton contract address that might be created from this factory, given its `_initCode` and a `_salt`. - /// @param _initCode Initialization code. - /// @param _salt Arbitrary value to modify resulting address. - /// @return expectedAddr Expected contract address. - function determineAddr(bytes memory _initCode, bytes32 _salt) - public - view - returns (address) - { - return address( - uint160(uint(keccak256( - abi.encodePacked( - bytes1(0xff), - address(this), - _salt, - keccak256(_initCode) - ) - ))) - ); - } - -} \ No newline at end of file diff --git a/contracts/patterns/Destructible.sol b/contracts/patterns/Destructible.sol deleted file mode 100644 index 08b5f0669..000000000 --- a/contracts/patterns/Destructible.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.0 <0.9.0; - -interface Destructible { - /// @dev Self-destruct the whole contract. - function destruct() external; -} diff --git a/contracts/patterns/Payable.sol b/contracts/patterns/Payable.sol index 6ff570307..8313a0c71 100644 --- a/contracts/patterns/Payable.sol +++ b/contracts/patterns/Payable.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT - pragma solidity >=0.6.0 <0.9.0; -import "../interfaces/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; abstract contract Payable { IERC20 public immutable currency; @@ -21,5 +20,5 @@ abstract contract Payable { function _getMsgValue() internal view virtual returns (uint256); /// Perform safe transfer or whatever token is used for paying rewards. - function _safeTransferTo(address payable, uint256) internal virtual; + function __safeTransferTo(address payable, uint256) internal virtual; } diff --git a/migrations/abis/WitnetBytecodes.json b/migrations/abis/WitnetBytecodes.json new file mode 100644 index 000000000..3641108bd --- /dev/null +++ b/migrations/abis/WitnetBytecodes.json @@ -0,0 +1,954 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "UnknownRadonReducer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "UnknownRadonRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "UnknownRadonRetrieval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "UnknownRadonSLA", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "NewDataProvider", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "NewRadHash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "NewRadonReducerHash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "NewRadonRetrievalHash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "NewSlaHash", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "slahHash", + "type": "bytes32" + } + ], + "name": "bytecodeOf", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "bytecodeOf", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "hashOf", + "outputs": [ + { + "internalType": "bytes32", + "name": "drQueryHash", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "sources", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "aggregator", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tally", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "resultMaxSize", + "type": "uint16" + }, + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "hashOf", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "hashWeightWitsOf", + "outputs": [ + { + "internalType": "bytes32", + "name": "drQueryHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "drQueryWeight", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "drQueryWits", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "lookupDataProvider", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "authority", + "type": "string" + } + ], + "name": "lookupDataProviderIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "lookupDataProviderSources", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "lookupRadonReducer", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestAggregator", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestResultDataType", + "outputs": [ + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestResultMaxSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestSources", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestSourcesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "lookupRadonRequestTally", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "lookupRadonRetrieval", + "outputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "argsCount", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "method", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "resultDataType", + "type": "uint8" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "body", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "headers", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonRetrieval", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "lookupRadonRetrievalArgsCount", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "lookupRadonRetrievalResultDataType", + "outputs": [ + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "lookupRadonSLA", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "lookupRadonSLAReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDataProviders", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "reducer", + "type": "tuple" + } + ], + "name": "verifyRadonReducer", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "sources", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "aggregator", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tally", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "resultMaxSize", + "type": "uint16" + }, + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "verifyRadonRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "requestMethod", + "type": "uint8" + }, + { + "internalType": "string", + "name": "requestSchema", + "type": "string" + }, + { + "internalType": "string", + "name": "requestAuthority", + "type": "string" + }, + { + "internalType": "string", + "name": "requestPath", + "type": "string" + }, + { + "internalType": "string", + "name": "requestQuery", + "type": "string" + }, + { + "internalType": "string", + "name": "requestBody", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "requestHeaders", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "requestRadonScript", + "type": "bytes" + } + ], + "name": "verifyRadonRetrieval", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "requestMethod", + "type": "uint8" + }, + { + "internalType": "string", + "name": "requestURL", + "type": "string" + }, + { + "internalType": "string", + "name": "requestBody", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "requestHeaders", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "requestRadonScript", + "type": "bytes" + } + ], + "name": "verifyRadonRetrieval", + "outputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "sla", + "type": "tuple" + } + ], + "name": "verifyRadonSLA", + "outputs": [ + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "class", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/migrations/abis/WitnetPriceFeeds.json b/migrations/abis/WitnetPriceFeeds.json new file mode 100644 index 000000000..421f539bb --- /dev/null +++ b/migrations/abis/WitnetPriceFeeds.json @@ -0,0 +1,1359 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "contract WitnetRequestBoard", + "name": "_wrb", + "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": "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "string", + "name": "caption", + "type": "string" + } + ], + "name": "DeletedFeed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "SettledFeed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "solver", + "type": "address" + } + ], + "name": "SettledFeedSolver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "SettledRadonSLA", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "UpdatingFeed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "UpdatingFeedReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "solver", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "codehash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "constructorParams", + "type": "bytes" + } + ], + "name": "WitnetPriceSolverDeployed", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "dataType", + "outputs": [ + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prefix", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "witnet", + "outputs": [ + { + "internalType": "contract IWitnetRequestBoard", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + } + ], + "name": "hash", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupCaption", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supportedFeeds", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "_ids", + "type": "bytes4[]" + }, + { + "internalType": "string[]", + "name": "_captions", + "type": "string[]" + }, + { + "internalType": "bytes32[]", + "name": "_solvers", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + } + ], + "name": "supportsCaption", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalFeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultRadonSLA", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_evmGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "estimateUpdateBaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_evmGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "estimateUpdateBaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestResponse", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "reporter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "cborBytes", + "type": "bytes" + } + ], + "internalType": "struct Witnet.Response", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestResult", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestUpdateQueryId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestUpdateRequest", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "gasprice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "internalType": "struct Witnet.Request", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestUpdateResponse", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "reporter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "cborBytes", + "type": "bytes" + } + ], + "internalType": "struct Witnet.Response", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestUpdateResultError", + "outputs": [ + { + "components": [ + { + "internalType": "enum Witnet.ResultErrorCodes", + "name": "code", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "internalType": "struct Witnet.ResultError", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestUpdateResultStatus", + "outputs": [ + { + "internalType": "enum Witnet.ResultStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupBytecode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupRadHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupRetrievals", + "outputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "argsCount", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "method", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "resultDataType", + "type": "uint8" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "body", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "headers", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonRetrieval[]", + "name": "_retrievals", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract IWitnetBytecodes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + }, + { + "internalType": "bytes32", + "name": "_slaHash", + "type": "bytes32" + } + ], + "name": "requestUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "_usedFunds", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "requestUpdate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + } + ], + "name": "deleteFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "sla", + "type": "tuple" + } + ], + "name": "settleDefaultRadonSLA", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + } + ], + "name": "settleFeedRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "internalType": "contract WitnetRequest", + "name": "request", + "type": "address" + } + ], + "name": "settleFeedRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "internalType": "contract WitnetRequestTemplate", + "name": "template", + "type": "address" + }, + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "settleFeedRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "caption", + "type": "string" + }, + { + "internalType": "address", + "name": "solver", + "type": "address" + }, + { + "internalType": "string[]", + "name": "deps", + "type": "string[]" + } + ], + "name": "settleFeedSolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupDecimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "lookupPriceSolver", + "outputs": [ + { + "internalType": "contract IWitnetPriceSolver", + "name": "_solverAddress", + "type": "address" + }, + { + "internalType": "string[]", + "name": "_solverDeps", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feedId", + "type": "bytes4" + } + ], + "name": "latestPrice", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "enum Witnet.ResultStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct IWitnetPriceSolver.Price", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4[]", + "name": "feedIds", + "type": "bytes4[]" + } + ], + "name": "latestPrices", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "enum Witnet.ResultStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct IWitnetPriceSolver.Price[]", + "name": "_prices", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initcode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "constructorParams", + "type": "bytes" + } + ], + "name": "deployPriceSolver", + "outputs": [ + { + "internalType": "address", + "name": "_solver", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initcode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "constructorParams", + "type": "bytes" + } + ], + "name": "determinePriceSolverAddress", + "outputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "valueFor", + "outputs": [ + { + "internalType": "int256", + "name": "_value", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_status", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/migrations/abis/WitnetProxy.json b/migrations/abis/WitnetProxy.json deleted file mode 100644 index 8aa75fc01..000000000 --- a/migrations/abis/WitnetProxy.json +++ /dev/null @@ -1,7310 +0,0 @@ -{ - "contractName": "WitnetProxy", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback", - "payable": true - }, - { - "stateMutability": "payable", - "type": "receive", - "payable": true - }, - { - "inputs": [], - "name": "implementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function", - "constant": true - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_newImplementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_initData", - "type": "bytes" - } - ], - "name": "upgradeTo", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_initData\",\"type\":\"bytes\"}],\"name\":\"upgradeTo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"The Witnet Foundation.\",\"kind\":\"dev\",\"methods\":{\"upgradeTo(address,bytes)\":{\"params\":{\"_initData\":\"Raw data with which new implementation will be initialized.\",\"_newImplementation\":\"New implementation address.\"},\"returns\":{\"_0\":\"Returns whether new implementation would be further upgradable, or not.\"}}},\"title\":\"WitnetProxy: upgradable delegate-proxy contract. \",\"version\":1},\"userdoc\":{\"events\":{\"Upgraded(address)\":{\"notice\":\"Event emitted every time the implementation gets updated.\"}},\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470).\"},\"implementation()\":{\"notice\":\"Returns proxy's current implementation address.\"},\"upgradeTo(address,bytes)\":{\"notice\":\"Upgrades the `implementation` address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project:/contracts/impls/WitnetProxy.sol\":\"WitnetProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0xe798cadb41e2da274913e4b3183a80f50fb057a42238fe8467e077268100ec27\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://899f850f7df5a270bccfb765d70069959ca1c20d3a7381c1c3bda8a3ffee1935\",\"dweb:/ipfs/QmVdnAqwyX2L3nX2HDA5WKGtVBFyH1nKE9A1k7fZnPBkhP\"]},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06\",\"dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879\"]},\"project:/contracts/impls/WitnetProxy.sol\":{\"keccak256\":\"0x1c779834ad2643469ffdaa70da075bd4617326663539b018e3a2756873997e3d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://142b32cd3be904194a8b370e6e1e5c961d9e70674903a47c6a3aac6aea770cfa\",\"dweb:/ipfs/Qme3UTCXqJFAdA7MJBKfQc3kUQjAoTuaMoifU8encsJU9P\"]},\"project:/contracts/patterns/Initializable.sol\":{\"keccak256\":\"0xaac470e87f361cf15d68d1618d6eb7d4913885d33ccc39c797841a9591d44296\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ef3760b2039feda8715d4bd9f8de8e3885f25573d12ba92f52d626ba880a08bf\",\"dweb:/ipfs/QmP2mfHPBKkjTAKft95sPDb4PBsjfmAwc47Kdcv3xYSf3g\"]},\"project:/contracts/patterns/Proxiable.sol\":{\"keccak256\":\"0xe1b1bb7ba2e2fc799b33648f6f89a1b0e82a75dd275071215b3fd8c82327a2cb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a025a64d64d46c7ced3c1c99f4380841ec495a0bb6fbe4426ff9b32e16fa4769\",\"dweb:/ipfs/QmRuUrv285bTD9pPCppUGNMTQkCqqceXSXEJrEnpN2H778\"]},\"project:/contracts/patterns/Upgradeable.sol\":{\"keccak256\":\"0x27ca1e658f13f0128d17ff27e9640670b22afdab6163c0daa14f2ec0853b5954\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f2eceac1ee77596a31e7ee2f11145ce188eef649e3095b2a26d746a250df2b81\",\"dweb:/ipfs/QmcEh2umA5McbU9VHY319XW8rw4Fs79a7dKGC3F2no8biL\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610912806100206000396000f3fe60806040526004361061002d5760003560e01c80635c60da1b146100655780636fbc15e91461009757610034565b3661003457005b600061003e6100c7565b905060405136600082376000803683855af43d806000843e818015610061578184f35b8184fd5b34801561007157600080fd5b5061007a6100c7565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100a357600080fd5b506100b76100b2366004610757565b6100f5565b604051901515815260200161008e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60006001600160a01b0383166101525760405162461bcd60e51b815260206004820181905260248201527f5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e60448201526064015b60405180910390fd5b600061015c6100c7565b90506001600160a01b0381161561053857806001600160a01b0316846001600160a01b0316036101ce5760405162461bcd60e51b815260206004820152601f60248201527f5769746e657450726f78793a206e6f7468696e6720746f2075706772616465006044820152606401610149565b806001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610228575060408051601f3d908101601f1916820190925261022591810190610827565b60015b6102875760405162461bcd60e51b815260206004820152602a60248201527f5769746e657450726f78793a20756e61626c6520746f20636865636b207570676044820152697261646162696c69747960b01b6064820152608401610149565b806102d45760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f742075706772616461626c6500000000006044820152606401610149565b5060405133602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166335ac4b0560e11b179052516103269190610874565b600060405180830381855af49150503d8060008114610361576040519150601f19603f3d011682016040523d82523d6000602084013e610366565b606091505b5091509150816103b85760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610149565b808060200190518101906103cc9190610827565b6104185760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f7420617574686f72697a656400000000006044820152606401610149565b856001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047a9190610890565b836001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104dc9190610890565b146105355760405162461bcd60e51b8152602060048201526024808201527f5769746e657450726f78793a2070726f786961626c655555494473206d69736d6044820152630c2e8c6d60e31b6064820152608401610149565b50505b6000846001600160a01b03168460405160240161055591906108a9565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161058a9190610874565b600060405180830381855af49150503d80600081146105c5576040519150601f19603f3d011682016040523d82523d6000602084013e6105ca565b606091505b50509050806106255760405162461bcd60e51b815260206004820152602160248201527f5769746e657450726f78793a20756e61626c6520746f20696e697469616c697a6044820152606560f81b6064820152608401610149565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0387169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2846001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156106e5575060408051601f3d908101601f191682019092526106e291810190610827565b60015b6107315760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610149565b925061073b915050565b92915050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561076a57600080fd5b82356001600160a01b038116811461078157600080fd5b9150602083013567ffffffffffffffff8082111561079e57600080fd5b818501915085601f8301126107b257600080fd5b8135818111156107c4576107c4610741565b604051601f8201601f19908116603f011681019083821181831017156107ec576107ec610741565b8160405282815288602084870101111561080557600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561083957600080fd5b8151801515811461084957600080fd5b9392505050565b60005b8381101561086b578181015183820152602001610853565b50506000910152565b60008251610886818460208701610850565b9190910192915050565b6000602082840312156108a257600080fd5b5051919050565b60208152600082518060208401526108c8816040850160208701610850565b601f01601f1916919091016040019291505056fea26469706673582212200771bc4bad015c089efb2351eb3266c8aad36c8daccf86bbf3421605ef5fc23c64736f6c63430008110033", - "deployedBytecode": "0x60806040526004361061002d5760003560e01c80635c60da1b146100655780636fbc15e91461009757610034565b3661003457005b600061003e6100c7565b905060405136600082376000803683855af43d806000843e818015610061578184f35b8184fd5b34801561007157600080fd5b5061007a6100c7565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100a357600080fd5b506100b76100b2366004610757565b6100f5565b604051901515815260200161008e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b60006001600160a01b0383166101525760405162461bcd60e51b815260206004820181905260248201527f5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e60448201526064015b60405180910390fd5b600061015c6100c7565b90506001600160a01b0381161561053857806001600160a01b0316846001600160a01b0316036101ce5760405162461bcd60e51b815260206004820152601f60248201527f5769746e657450726f78793a206e6f7468696e6720746f2075706772616465006044820152606401610149565b806001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610228575060408051601f3d908101601f1916820190925261022591810190610827565b60015b6102875760405162461bcd60e51b815260206004820152602a60248201527f5769746e657450726f78793a20756e61626c6520746f20636865636b207570676044820152697261646162696c69747960b01b6064820152608401610149565b806102d45760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f742075706772616461626c6500000000006044820152606401610149565b5060405133602482015260009081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166335ac4b0560e11b179052516103269190610874565b600060405180830381855af49150503d8060008114610361576040519150601f19603f3d011682016040523d82523d6000602084013e610366565b606091505b5091509150816103b85760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610149565b808060200190518101906103cc9190610827565b6104185760405162461bcd60e51b815260206004820152601b60248201527f5769746e657450726f78793a206e6f7420617574686f72697a656400000000006044820152606401610149565b856001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610456573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047a9190610890565b836001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104dc9190610890565b146105355760405162461bcd60e51b8152602060048201526024808201527f5769746e657450726f78793a2070726f786961626c655555494473206d69736d6044820152630c2e8c6d60e31b6064820152608401610149565b50505b6000846001600160a01b03168460405160240161055591906108a9565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161058a9190610874565b600060405180830381855af49150503d80600081146105c5576040519150601f19603f3d011682016040523d82523d6000602084013e6105ca565b606091505b50509050806106255760405162461bcd60e51b815260206004820152602160248201527f5769746e657450726f78793a20756e61626c6520746f20696e697469616c697a6044820152606560f81b6064820152608401610149565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0387169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2846001600160a01b0316635479d9406040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156106e5575060408051601f3d908101601f191682019092526106e291810190610827565b60015b6107315760405162461bcd60e51b815260206004820152601a60248201527f5769746e657450726f78793a206e6f7420636f6d706c69616e740000000000006044820152606401610149565b925061073b915050565b92915050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561076a57600080fd5b82356001600160a01b038116811461078157600080fd5b9150602083013567ffffffffffffffff8082111561079e57600080fd5b818501915085601f8301126107b257600080fd5b8135818111156107c4576107c4610741565b604051601f8201601f19908116603f011681019083821181831017156107ec576107ec610741565b8160405282815288602084870101111561080557600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60006020828403121561083957600080fd5b8151801515811461084957600080fd5b9392505050565b60005b8381101561086b578181015183820152602001610853565b50506000910152565b60008251610886818460208701610850565b9190910192915050565b6000602082840312156108a257600080fd5b5051919050565b60208152600082518060208401526108c8816040850160208701610850565b601f01601f1916919091016040019291505056fea26469706673582212200771bc4bad015c089efb2351eb3266c8aad36c8daccf86bbf3421605ef5fc23c64736f6c63430008110033", - "immutableReferences": {}, - "generatedSources": [], - "deployedGeneratedSources": [ - { - "ast": { - "nodeType": "YulBlock", - "src": "0:6066:84", - "statements": [ - { - "nodeType": "YulBlock", - "src": "6:3:84", - "statements": [] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "115:102:84", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "125:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "137:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "148:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "133:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "133:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "125:4:84" - } - ] - }, - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "167:9:84" - }, - { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "182:6:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "198:3:84", - "type": "", - "value": "160" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "203:1:84", - "type": "", - "value": "1" - } - ], - "functionName": { - "name": "shl", - "nodeType": "YulIdentifier", - "src": "194:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "194:11:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "207:1:84", - "type": "", - "value": "1" - } - ], - "functionName": { - "name": "sub", - "nodeType": "YulIdentifier", - "src": "190:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "190:19:84" - } - ], - "functionName": { - "name": "and", - "nodeType": "YulIdentifier", - "src": "178:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "178:32:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "160:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "160:51:84" - }, - "nodeType": "YulExpressionStatement", - "src": "160:51:84" - } - ] - }, - "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "84:9:84", - "type": "" - }, - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "95:6:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "106:4:84", - "type": "" - } - ], - "src": "14:203:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "254:95:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "271:1:84", - "type": "", - "value": "0" - }, - { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "278:3:84", - "type": "", - "value": "224" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "283:10:84", - "type": "", - "value": "0x4e487b71" - } - ], - "functionName": { - "name": "shl", - "nodeType": "YulIdentifier", - "src": "274:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "274:20:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "264:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "264:31:84" - }, - "nodeType": "YulExpressionStatement", - "src": "264:31:84" - }, - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "311:1:84", - "type": "", - "value": "4" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "314:4:84", - "type": "", - "value": "0x41" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "304:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "304:15:84" - }, - "nodeType": "YulExpressionStatement", - "src": "304:15:84" - }, - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "335:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "338:4:84", - "type": "", - "value": "0x24" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "328:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "328:15:84" - }, - "nodeType": "YulExpressionStatement", - "src": "328:15:84" - } - ] - }, - "name": "panic_error_0x41", - "nodeType": "YulFunctionDefinition", - "src": "222:127:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "450:999:84", - "statements": [ - { - "body": { - "nodeType": "YulBlock", - "src": "496:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "505:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "508:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "498:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "498:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "498:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "dataEnd", - "nodeType": "YulIdentifier", - "src": "471:7:84" - }, - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "480:9:84" - } - ], - "functionName": { - "name": "sub", - "nodeType": "YulIdentifier", - "src": "467:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "467:23:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "492:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "slt", - "nodeType": "YulIdentifier", - "src": "463:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "463:32:84" - }, - "nodeType": "YulIf", - "src": "460:52:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "521:36:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "547:9:84" - } - ], - "functionName": { - "name": "calldataload", - "nodeType": "YulIdentifier", - "src": "534:12:84" - }, - "nodeType": "YulFunctionCall", - "src": "534:23:84" - }, - "variables": [ - { - "name": "value", - "nodeType": "YulTypedName", - "src": "525:5:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "620:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "629:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "632:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "622:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "622:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "622:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "value", - "nodeType": "YulIdentifier", - "src": "579:5:84" - }, - { - "arguments": [ - { - "name": "value", - "nodeType": "YulIdentifier", - "src": "590:5:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "605:3:84", - "type": "", - "value": "160" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "610:1:84", - "type": "", - "value": "1" - } - ], - "functionName": { - "name": "shl", - "nodeType": "YulIdentifier", - "src": "601:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "601:11:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "614:1:84", - "type": "", - "value": "1" - } - ], - "functionName": { - "name": "sub", - "nodeType": "YulIdentifier", - "src": "597:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "597:19:84" - } - ], - "functionName": { - "name": "and", - "nodeType": "YulIdentifier", - "src": "586:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "586:31:84" - } - ], - "functionName": { - "name": "eq", - "nodeType": "YulIdentifier", - "src": "576:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "576:42:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "569:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "569:50:84" - }, - "nodeType": "YulIf", - "src": "566:70:84" - }, - { - "nodeType": "YulAssignment", - "src": "645:15:84", - "value": { - "name": "value", - "nodeType": "YulIdentifier", - "src": "655:5:84" - }, - "variableNames": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "645:6:84" - } - ] - }, - { - "nodeType": "YulVariableDeclaration", - "src": "669:46:84", - "value": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "700:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "711:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "696:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "696:18:84" - } - ], - "functionName": { - "name": "calldataload", - "nodeType": "YulIdentifier", - "src": "683:12:84" - }, - "nodeType": "YulFunctionCall", - "src": "683:32:84" - }, - "variables": [ - { - "name": "offset", - "nodeType": "YulTypedName", - "src": "673:6:84", - "type": "" - } - ] - }, - { - "nodeType": "YulVariableDeclaration", - "src": "724:28:84", - "value": { - "kind": "number", - "nodeType": "YulLiteral", - "src": "734:18:84", - "type": "", - "value": "0xffffffffffffffff" - }, - "variables": [ - { - "name": "_1", - "nodeType": "YulTypedName", - "src": "728:2:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "779:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "788:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "791:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "781:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "781:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "781:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "name": "offset", - "nodeType": "YulIdentifier", - "src": "767:6:84" - }, - { - "name": "_1", - "nodeType": "YulIdentifier", - "src": "775:2:84" - } - ], - "functionName": { - "name": "gt", - "nodeType": "YulIdentifier", - "src": "764:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "764:14:84" - }, - "nodeType": "YulIf", - "src": "761:34:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "804:32:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "818:9:84" - }, - { - "name": "offset", - "nodeType": "YulIdentifier", - "src": "829:6:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "814:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "814:22:84" - }, - "variables": [ - { - "name": "_2", - "nodeType": "YulTypedName", - "src": "808:2:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "884:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "893:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "896:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "886:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "886:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "886:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "arguments": [ - { - "name": "_2", - "nodeType": "YulIdentifier", - "src": "863:2:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "867:4:84", - "type": "", - "value": "0x1f" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "859:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "859:13:84" - }, - { - "name": "dataEnd", - "nodeType": "YulIdentifier", - "src": "874:7:84" - } - ], - "functionName": { - "name": "slt", - "nodeType": "YulIdentifier", - "src": "855:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "855:27:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "848:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "848:35:84" - }, - "nodeType": "YulIf", - "src": "845:55:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "909:26:84", - "value": { - "arguments": [ - { - "name": "_2", - "nodeType": "YulIdentifier", - "src": "932:2:84" - } - ], - "functionName": { - "name": "calldataload", - "nodeType": "YulIdentifier", - "src": "919:12:84" - }, - "nodeType": "YulFunctionCall", - "src": "919:16:84" - }, - "variables": [ - { - "name": "_3", - "nodeType": "YulTypedName", - "src": "913:2:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "958:22:84", - "statements": [ - { - "expression": { - "arguments": [], - "functionName": { - "name": "panic_error_0x41", - "nodeType": "YulIdentifier", - "src": "960:16:84" - }, - "nodeType": "YulFunctionCall", - "src": "960:18:84" - }, - "nodeType": "YulExpressionStatement", - "src": "960:18:84" - } - ] - }, - "condition": { - "arguments": [ - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "950:2:84" - }, - { - "name": "_1", - "nodeType": "YulIdentifier", - "src": "954:2:84" - } - ], - "functionName": { - "name": "gt", - "nodeType": "YulIdentifier", - "src": "947:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "947:10:84" - }, - "nodeType": "YulIf", - "src": "944:36:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "989:17:84", - "value": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1003:2:84", - "type": "", - "value": "31" - } - ], - "functionName": { - "name": "not", - "nodeType": "YulIdentifier", - "src": "999:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "999:7:84" - }, - "variables": [ - { - "name": "_4", - "nodeType": "YulTypedName", - "src": "993:2:84", - "type": "" - } - ] - }, - { - "nodeType": "YulVariableDeclaration", - "src": "1015:23:84", - "value": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1035:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "1029:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "1029:9:84" - }, - "variables": [ - { - "name": "memPtr", - "nodeType": "YulTypedName", - "src": "1019:6:84", - "type": "" - } - ] - }, - { - "nodeType": "YulVariableDeclaration", - "src": "1047:71:84", - "value": { - "arguments": [ - { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1069:6:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "arguments": [ - { - "arguments": [ - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "1093:2:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1097:4:84", - "type": "", - "value": "0x1f" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1089:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1089:13:84" - }, - { - "name": "_4", - "nodeType": "YulIdentifier", - "src": "1104:2:84" - } - ], - "functionName": { - "name": "and", - "nodeType": "YulIdentifier", - "src": "1085:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1085:22:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1109:2:84", - "type": "", - "value": "63" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1081:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1081:31:84" - }, - { - "name": "_4", - "nodeType": "YulIdentifier", - "src": "1114:2:84" - } - ], - "functionName": { - "name": "and", - "nodeType": "YulIdentifier", - "src": "1077:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1077:40:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1065:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1065:53:84" - }, - "variables": [ - { - "name": "newFreePtr", - "nodeType": "YulTypedName", - "src": "1051:10:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "1177:22:84", - "statements": [ - { - "expression": { - "arguments": [], - "functionName": { - "name": "panic_error_0x41", - "nodeType": "YulIdentifier", - "src": "1179:16:84" - }, - "nodeType": "YulFunctionCall", - "src": "1179:18:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1179:18:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "newFreePtr", - "nodeType": "YulIdentifier", - "src": "1136:10:84" - }, - { - "name": "_1", - "nodeType": "YulIdentifier", - "src": "1148:2:84" - } - ], - "functionName": { - "name": "gt", - "nodeType": "YulIdentifier", - "src": "1133:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "1133:18:84" - }, - { - "arguments": [ - { - "name": "newFreePtr", - "nodeType": "YulIdentifier", - "src": "1156:10:84" - }, - { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1168:6:84" - } - ], - "functionName": { - "name": "lt", - "nodeType": "YulIdentifier", - "src": "1153:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "1153:22:84" - } - ], - "functionName": { - "name": "or", - "nodeType": "YulIdentifier", - "src": "1130:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "1130:46:84" - }, - "nodeType": "YulIf", - "src": "1127:72:84" - }, - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1215:2:84", - "type": "", - "value": "64" - }, - { - "name": "newFreePtr", - "nodeType": "YulIdentifier", - "src": "1219:10:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1208:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1208:22:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1208:22:84" - }, - { - "expression": { - "arguments": [ - { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1246:6:84" - }, - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "1254:2:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1239:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1239:18:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1239:18:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "1303:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1312:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1315:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "1305:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1305:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1305:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "arguments": [ - { - "name": "_2", - "nodeType": "YulIdentifier", - "src": "1280:2:84" - }, - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "1284:2:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1276:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1276:11:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1289:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1272:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1272:20:84" - }, - { - "name": "dataEnd", - "nodeType": "YulIdentifier", - "src": "1294:7:84" - } - ], - "functionName": { - "name": "gt", - "nodeType": "YulIdentifier", - "src": "1269:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "1269:33:84" - }, - "nodeType": "YulIf", - "src": "1266:53:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1345:6:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1353:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1341:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1341:15:84" - }, - { - "arguments": [ - { - "name": "_2", - "nodeType": "YulIdentifier", - "src": "1362:2:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1366:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1358:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1358:11:84" - }, - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "1371:2:84" - } - ], - "functionName": { - "name": "calldatacopy", - "nodeType": "YulIdentifier", - "src": "1328:12:84" - }, - "nodeType": "YulFunctionCall", - "src": "1328:46:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1328:46:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "arguments": [ - { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1398:6:84" - }, - { - "name": "_3", - "nodeType": "YulIdentifier", - "src": "1406:2:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1394:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1394:15:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1411:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1390:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1390:24:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1416:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1383:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1383:35:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1383:35:84" - }, - { - "nodeType": "YulAssignment", - "src": "1427:16:84", - "value": { - "name": "memPtr", - "nodeType": "YulIdentifier", - "src": "1437:6:84" - }, - "variableNames": [ - { - "name": "value1", - "nodeType": "YulIdentifier", - "src": "1427:6:84" - } - ] - } - ] - }, - "name": "abi_decode_tuple_t_addresst_bytes_memory_ptr", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "408:9:84", - "type": "" - }, - { - "name": "dataEnd", - "nodeType": "YulTypedName", - "src": "419:7:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "431:6:84", - "type": "" - }, - { - "name": "value1", - "nodeType": "YulTypedName", - "src": "439:6:84", - "type": "" - } - ], - "src": "354:1095:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "1549:92:84", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "1559:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1571:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1582:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1567:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1567:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "1559:4:84" - } - ] - }, - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1601:9:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "1626:6:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "1619:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1619:14:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "1612:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1612:22:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1594:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1594:41:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1594:41:84" - } - ] - }, - "name": "abi_encode_tuple_t_bool__to_t_bool__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "1518:9:84", - "type": "" - }, - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "1529:6:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "1540:4:84", - "type": "" - } - ], - "src": "1454:187:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "1820:182:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1837:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1848:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1830:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1830:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1830:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1871:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1882:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1867:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1867:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1887:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1860:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1860:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1860:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1910:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1921:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1906:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1906:18:84" - }, - { - "hexValue": "5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e", - "kind": "string", - "nodeType": "YulLiteral", - "src": "1926:34:84", - "type": "", - "value": "WitnetProxy: null implementation" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "1899:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "1899:62:84" - }, - "nodeType": "YulExpressionStatement", - "src": "1899:62:84" - }, - { - "nodeType": "YulAssignment", - "src": "1970:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "1982:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1993:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "1978:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "1978:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "1970:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_d599eaa5e68d91d75c142446490ab9a15fd0284a41ce949219b5b4d8f267239a__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "1797:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "1811:4:84", - "type": "" - } - ], - "src": "1646:356:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "2181:181:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2198:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2209:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2191:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2191:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2191:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2232:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2243:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2228:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2228:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2248:2:84", - "type": "", - "value": "31" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2221:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2221:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2221:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2271:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2282:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2267:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2267:18:84" - }, - { - "hexValue": "5769746e657450726f78793a206e6f7468696e6720746f2075706772616465", - "kind": "string", - "nodeType": "YulLiteral", - "src": "2287:33:84", - "type": "", - "value": "WitnetProxy: nothing to upgrade" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2260:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2260:61:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2260:61:84" - }, - { - "nodeType": "YulAssignment", - "src": "2330:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2342:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2353:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2338:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2338:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "2330:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_e332eab1bae45430d1201a30c0d80d8fcb5570f9e70201a9eb7b229e17fd2084__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "2158:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "2172:4:84", - "type": "" - } - ], - "src": "2007:355:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "2445:199:84", - "statements": [ - { - "body": { - "nodeType": "YulBlock", - "src": "2491:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2500:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2503:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "2493:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2493:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2493:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "dataEnd", - "nodeType": "YulIdentifier", - "src": "2466:7:84" - }, - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2475:9:84" - } - ], - "functionName": { - "name": "sub", - "nodeType": "YulIdentifier", - "src": "2462:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2462:23:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2487:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "slt", - "nodeType": "YulIdentifier", - "src": "2458:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2458:32:84" - }, - "nodeType": "YulIf", - "src": "2455:52:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "2516:29:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2535:9:84" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "2529:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "2529:16:84" - }, - "variables": [ - { - "name": "value", - "nodeType": "YulTypedName", - "src": "2520:5:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "2598:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2607:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2610:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "2600:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2600:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2600:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "value", - "nodeType": "YulIdentifier", - "src": "2567:5:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "name": "value", - "nodeType": "YulIdentifier", - "src": "2588:5:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "2581:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2581:13:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "2574:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2574:21:84" - } - ], - "functionName": { - "name": "eq", - "nodeType": "YulIdentifier", - "src": "2564:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "2564:32:84" - } - ], - "functionName": { - "name": "iszero", - "nodeType": "YulIdentifier", - "src": "2557:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2557:40:84" - }, - "nodeType": "YulIf", - "src": "2554:60:84" - }, - { - "nodeType": "YulAssignment", - "src": "2623:15:84", - "value": { - "name": "value", - "nodeType": "YulIdentifier", - "src": "2633:5:84" - }, - "variableNames": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "2623:6:84" - } - ] - } - ] - }, - "name": "abi_decode_tuple_t_bool_fromMemory", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "2411:9:84", - "type": "" - }, - { - "name": "dataEnd", - "nodeType": "YulTypedName", - "src": "2422:7:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "2434:6:84", - "type": "" - } - ], - "src": "2367:277:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "2823:232:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2840:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2851:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2833:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2833:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2833:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2874:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2885:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2870:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2870:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2890:2:84", - "type": "", - "value": "42" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2863:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2863:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2863:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2913:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2924:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2909:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2909:18:84" - }, - { - "hexValue": "5769746e657450726f78793a20756e61626c6520746f20636865636b20757067", - "kind": "string", - "nodeType": "YulLiteral", - "src": "2929:34:84", - "type": "", - "value": "WitnetProxy: unable to check upg" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2902:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2902:62:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2902:62:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "2984:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "2995:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "2980:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "2980:18:84" - }, - { - "hexValue": "7261646162696c697479", - "kind": "string", - "nodeType": "YulLiteral", - "src": "3000:12:84", - "type": "", - "value": "radability" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "2973:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "2973:40:84" - }, - "nodeType": "YulExpressionStatement", - "src": "2973:40:84" - }, - { - "nodeType": "YulAssignment", - "src": "3022:27:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "3034:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3045:3:84", - "type": "", - "value": "128" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3030:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3030:19:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "3022:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_7f859058ad3ee4e192700ff813ed67dc892a0c7de91510ee584a0ac25fc982fc__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "2800:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "2814:4:84", - "type": "" - } - ], - "src": "2649:406:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "3234:177:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "3251:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3262:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "3244:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "3244:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3244:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "3285:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3296:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3281:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3281:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3301:2:84", - "type": "", - "value": "27" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "3274:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "3274:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3274:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "3324:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3335:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3320:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3320:18:84" - }, - { - "hexValue": "5769746e657450726f78793a206e6f742075706772616461626c65", - "kind": "string", - "nodeType": "YulLiteral", - "src": "3340:29:84", - "type": "", - "value": "WitnetProxy: not upgradable" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "3313:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "3313:57:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3313:57:84" - }, - { - "nodeType": "YulAssignment", - "src": "3379:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "3391:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3402:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3387:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3387:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "3379:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_d96132834a96bae5cb2f32cb07f13985dcde0f2358055c198eb3065af6c5aa7f__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "3211:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "3225:4:84", - "type": "" - } - ], - "src": "3060:351:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "3482:184:84", - "statements": [ - { - "nodeType": "YulVariableDeclaration", - "src": "3492:10:84", - "value": { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3501:1:84", - "type": "", - "value": "0" - }, - "variables": [ - { - "name": "i", - "nodeType": "YulTypedName", - "src": "3496:1:84", - "type": "" - } - ] - }, - { - "body": { - "nodeType": "YulBlock", - "src": "3561:63:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "dst", - "nodeType": "YulIdentifier", - "src": "3586:3:84" - }, - { - "name": "i", - "nodeType": "YulIdentifier", - "src": "3591:1:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3582:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3582:11:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "name": "src", - "nodeType": "YulIdentifier", - "src": "3605:3:84" - }, - { - "name": "i", - "nodeType": "YulIdentifier", - "src": "3610:1:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3601:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3601:11:84" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "3595:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "3595:18:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "3575:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "3575:39:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3575:39:84" - } - ] - }, - "condition": { - "arguments": [ - { - "name": "i", - "nodeType": "YulIdentifier", - "src": "3522:1:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "3525:6:84" - } - ], - "functionName": { - "name": "lt", - "nodeType": "YulIdentifier", - "src": "3519:2:84" - }, - "nodeType": "YulFunctionCall", - "src": "3519:13:84" - }, - "nodeType": "YulForLoop", - "post": { - "nodeType": "YulBlock", - "src": "3533:19:84", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "3535:15:84", - "value": { - "arguments": [ - { - "name": "i", - "nodeType": "YulIdentifier", - "src": "3544:1:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3547:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3540:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3540:10:84" - }, - "variableNames": [ - { - "name": "i", - "nodeType": "YulIdentifier", - "src": "3535:1:84" - } - ] - } - ] - }, - "pre": { - "nodeType": "YulBlock", - "src": "3515:3:84", - "statements": [] - }, - "src": "3511:113:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "dst", - "nodeType": "YulIdentifier", - "src": "3644:3:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "3649:6:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3640:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3640:16:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3658:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "3633:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "3633:27:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3633:27:84" - } - ] - }, - "name": "copy_memory_to_memory_with_cleanup", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "src", - "nodeType": "YulTypedName", - "src": "3460:3:84", - "type": "" - }, - { - "name": "dst", - "nodeType": "YulTypedName", - "src": "3465:3:84", - "type": "" - }, - { - "name": "length", - "nodeType": "YulTypedName", - "src": "3470:6:84", - "type": "" - } - ], - "src": "3416:250:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "3808:150:84", - "statements": [ - { - "nodeType": "YulVariableDeclaration", - "src": "3818:27:84", - "value": { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "3838:6:84" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "3832:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "3832:13:84" - }, - "variables": [ - { - "name": "length", - "nodeType": "YulTypedName", - "src": "3822:6:84", - "type": "" - } - ] - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "3893:6:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "3901:4:84", - "type": "", - "value": "0x20" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3889:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3889:17:84" - }, - { - "name": "pos", - "nodeType": "YulIdentifier", - "src": "3908:3:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "3913:6:84" - } - ], - "functionName": { - "name": "copy_memory_to_memory_with_cleanup", - "nodeType": "YulIdentifier", - "src": "3854:34:84" - }, - "nodeType": "YulFunctionCall", - "src": "3854:66:84" - }, - "nodeType": "YulExpressionStatement", - "src": "3854:66:84" - }, - { - "nodeType": "YulAssignment", - "src": "3929:23:84", - "value": { - "arguments": [ - { - "name": "pos", - "nodeType": "YulIdentifier", - "src": "3940:3:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "3945:6:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "3936:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "3936:16:84" - }, - "variableNames": [ - { - "name": "end", - "nodeType": "YulIdentifier", - "src": "3929:3:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_packed_t_bytes_memory_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "pos", - "nodeType": "YulTypedName", - "src": "3784:3:84", - "type": "" - }, - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "3789:6:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "end", - "nodeType": "YulTypedName", - "src": "3800:3:84", - "type": "" - } - ], - "src": "3671:287:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "4137:176:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4154:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4165:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4147:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4147:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4147:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4188:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4199:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4184:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4184:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4204:2:84", - "type": "", - "value": "26" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4177:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4177:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4177:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4227:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4238:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4223:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4223:18:84" - }, - { - "hexValue": "5769746e657450726f78793a206e6f7420636f6d706c69616e74", - "kind": "string", - "nodeType": "YulLiteral", - "src": "4243:28:84", - "type": "", - "value": "WitnetProxy: not compliant" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4216:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4216:56:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4216:56:84" - }, - { - "nodeType": "YulAssignment", - "src": "4281:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4293:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4304:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4289:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4289:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "4281:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "4114:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "4128:4:84", - "type": "" - } - ], - "src": "3963:350:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "4492:177:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4509:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4520:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4502:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4502:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4502:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4543:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4554:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4539:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4539:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4559:2:84", - "type": "", - "value": "27" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4532:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4532:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4532:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4582:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4593:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4578:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4578:18:84" - }, - { - "hexValue": "5769746e657450726f78793a206e6f7420617574686f72697a6564", - "kind": "string", - "nodeType": "YulLiteral", - "src": "4598:29:84", - "type": "", - "value": "WitnetProxy: not authorized" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "4571:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4571:57:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4571:57:84" - }, - { - "nodeType": "YulAssignment", - "src": "4637:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4649:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4660:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "4645:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4645:18:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "4637:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_ba8d4d661ce88eb2915ba133e6cad533938b754d7b66d8253879ef2c2193ecb2__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "4469:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "4483:4:84", - "type": "" - } - ], - "src": "4318:351:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "4755:103:84", - "statements": [ - { - "body": { - "nodeType": "YulBlock", - "src": "4801:16:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4810:1:84", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4813:1:84", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "4803:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "4803:12:84" - }, - "nodeType": "YulExpressionStatement", - "src": "4803:12:84" - } - ] - }, - "condition": { - "arguments": [ - { - "arguments": [ - { - "name": "dataEnd", - "nodeType": "YulIdentifier", - "src": "4776:7:84" - }, - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4785:9:84" - } - ], - "functionName": { - "name": "sub", - "nodeType": "YulIdentifier", - "src": "4772:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4772:23:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4797:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "slt", - "nodeType": "YulIdentifier", - "src": "4768:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "4768:32:84" - }, - "nodeType": "YulIf", - "src": "4765:52:84" - }, - { - "nodeType": "YulAssignment", - "src": "4826:26:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "4842:9:84" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "4836:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "4836:16:84" - }, - "variableNames": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "4826:6:84" - } - ] - } - ] - }, - "name": "abi_decode_tuple_t_bytes32_fromMemory", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "4721:9:84", - "type": "" - }, - { - "name": "dataEnd", - "nodeType": "YulTypedName", - "src": "4732:7:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "4744:6:84", - "type": "" - } - ], - "src": "4674:184:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "5037:226:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5054:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5065:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5047:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5047:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5047:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5088:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5099:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5084:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5084:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5104:2:84", - "type": "", - "value": "36" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5077:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5077:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5077:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5127:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5138:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5123:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5123:18:84" - }, - { - "hexValue": "5769746e657450726f78793a2070726f786961626c655555494473206d69736d", - "kind": "string", - "nodeType": "YulLiteral", - "src": "5143:34:84", - "type": "", - "value": "WitnetProxy: proxiableUUIDs mism" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5116:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5116:62:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5116:62:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5198:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5209:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5194:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5194:18:84" - }, - { - "hexValue": "61746368", - "kind": "string", - "nodeType": "YulLiteral", - "src": "5214:6:84", - "type": "", - "value": "atch" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5187:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5187:34:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5187:34:84" - }, - { - "nodeType": "YulAssignment", - "src": "5230:27:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5242:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5253:3:84", - "type": "", - "value": "128" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5238:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5238:19:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "5230:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_f3c1ad1fa1688d47e62cc4dd5b4be101315ef47e38e05aa3a37a4ef2e1cec0a8__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "5014:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "5028:4:84", - "type": "" - } - ], - "src": "4863:400:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "5387:275:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5404:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5415:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5397:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5397:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5397:21:84" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "5427:27:84", - "value": { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "5447:6:84" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "5441:5:84" - }, - "nodeType": "YulFunctionCall", - "src": "5441:13:84" - }, - "variables": [ - { - "name": "length", - "nodeType": "YulTypedName", - "src": "5431:6:84", - "type": "" - } - ] - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5474:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5485:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5470:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5470:18:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "5490:6:84" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5463:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5463:34:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5463:34:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "5545:6:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5553:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5541:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5541:15:84" - }, - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5562:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5573:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5558:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5558:18:84" - }, - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "5578:6:84" - } - ], - "functionName": { - "name": "copy_memory_to_memory_with_cleanup", - "nodeType": "YulIdentifier", - "src": "5506:34:84" - }, - "nodeType": "YulFunctionCall", - "src": "5506:79:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5506:79:84" - }, - { - "nodeType": "YulAssignment", - "src": "5594:62:84", - "value": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5610:9:84" - }, - { - "arguments": [ - { - "arguments": [ - { - "name": "length", - "nodeType": "YulIdentifier", - "src": "5629:6:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5637:2:84", - "type": "", - "value": "31" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5625:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5625:15:84" - }, - { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5646:2:84", - "type": "", - "value": "31" - } - ], - "functionName": { - "name": "not", - "nodeType": "YulIdentifier", - "src": "5642:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5642:7:84" - } - ], - "functionName": { - "name": "and", - "nodeType": "YulIdentifier", - "src": "5621:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5621:29:84" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5606:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5606:45:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5653:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5602:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5602:54:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "5594:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_bytes_memory_ptr__to_t_bytes_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "5356:9:84", - "type": "" - }, - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "5367:6:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "5378:4:84", - "type": "" - } - ], - "src": "5268:394:84" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "5841:223:84", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5858:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5869:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5851:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5851:21:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5851:21:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5892:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5903:2:84", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5888:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5888:18:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5908:2:84", - "type": "", - "value": "33" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5881:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5881:30:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5881:30:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "5931:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "5942:2:84", - "type": "", - "value": "64" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5927:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5927:18:84" - }, - { - "hexValue": "5769746e657450726f78793a20756e61626c6520746f20696e697469616c697a", - "kind": "string", - "nodeType": "YulLiteral", - "src": "5947:34:84", - "type": "", - "value": "WitnetProxy: unable to initializ" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5920:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5920:62:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5920:62:84" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "6002:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "6013:2:84", - "type": "", - "value": "96" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "5998:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "5998:18:84" - }, - { - "hexValue": "65", - "kind": "string", - "nodeType": "YulLiteral", - "src": "6018:3:84", - "type": "", - "value": "e" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "5991:6:84" - }, - "nodeType": "YulFunctionCall", - "src": "5991:31:84" - }, - "nodeType": "YulExpressionStatement", - "src": "5991:31:84" - }, - { - "nodeType": "YulAssignment", - "src": "6031:27:84", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "6043:9:84" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "6054:3:84", - "type": "", - "value": "128" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "6039:3:84" - }, - "nodeType": "YulFunctionCall", - "src": "6039:19:84" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "6031:4:84" - } - ] - } - ] - }, - "name": "abi_encode_tuple_t_stringliteral_55e9f07b665adf0e8c084720fbd831f583a2d75f5997894b64a77e28a0171f3c__to_t_string_memory_ptr__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "5818:9:84", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "5832:4:84", - "type": "" - } - ], - "src": "5667:397:84" - } - ] - }, - "contents": "{\n { }\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, sub(shl(160, 1), 1)))\n }\n function panic_error_0x41()\n {\n mstore(0, shl(224, 0x4e487b71))\n mstore(4, 0x41)\n revert(0, 0x24)\n }\n function abi_decode_tuple_t_addresst_bytes_memory_ptr(headStart, dataEnd) -> value0, value1\n {\n if slt(sub(dataEnd, headStart), 64) { revert(0, 0) }\n let value := calldataload(headStart)\n if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) }\n value0 := value\n let offset := calldataload(add(headStart, 32))\n let _1 := 0xffffffffffffffff\n if gt(offset, _1) { revert(0, 0) }\n let _2 := add(headStart, offset)\n if iszero(slt(add(_2, 0x1f), dataEnd)) { revert(0, 0) }\n let _3 := calldataload(_2)\n if gt(_3, _1) { panic_error_0x41() }\n let _4 := not(31)\n let memPtr := mload(64)\n let newFreePtr := add(memPtr, and(add(and(add(_3, 0x1f), _4), 63), _4))\n if or(gt(newFreePtr, _1), lt(newFreePtr, memPtr)) { panic_error_0x41() }\n mstore(64, newFreePtr)\n mstore(memPtr, _3)\n if gt(add(add(_2, _3), 32), dataEnd) { revert(0, 0) }\n calldatacopy(add(memPtr, 32), add(_2, 32), _3)\n mstore(add(add(memPtr, _3), 32), 0)\n value1 := memPtr\n }\n function abi_encode_tuple_t_bool__to_t_bool__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, iszero(iszero(value0)))\n }\n function abi_encode_tuple_t_stringliteral_d599eaa5e68d91d75c142446490ab9a15fd0284a41ce949219b5b4d8f267239a__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 32)\n mstore(add(headStart, 64), \"WitnetProxy: null implementation\")\n tail := add(headStart, 96)\n }\n function abi_encode_tuple_t_stringliteral_e332eab1bae45430d1201a30c0d80d8fcb5570f9e70201a9eb7b229e17fd2084__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 31)\n mstore(add(headStart, 64), \"WitnetProxy: nothing to upgrade\")\n tail := add(headStart, 96)\n }\n function abi_decode_tuple_t_bool_fromMemory(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n let value := mload(headStart)\n if iszero(eq(value, iszero(iszero(value)))) { revert(0, 0) }\n value0 := value\n }\n function abi_encode_tuple_t_stringliteral_7f859058ad3ee4e192700ff813ed67dc892a0c7de91510ee584a0ac25fc982fc__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 42)\n mstore(add(headStart, 64), \"WitnetProxy: unable to check upg\")\n mstore(add(headStart, 96), \"radability\")\n tail := add(headStart, 128)\n }\n function abi_encode_tuple_t_stringliteral_d96132834a96bae5cb2f32cb07f13985dcde0f2358055c198eb3065af6c5aa7f__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 27)\n mstore(add(headStart, 64), \"WitnetProxy: not upgradable\")\n tail := add(headStart, 96)\n }\n function copy_memory_to_memory_with_cleanup(src, dst, length)\n {\n let i := 0\n for { } lt(i, length) { i := add(i, 32) }\n {\n mstore(add(dst, i), mload(add(src, i)))\n }\n mstore(add(dst, length), 0)\n }\n function abi_encode_tuple_packed_t_bytes_memory_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed(pos, value0) -> end\n {\n let length := mload(value0)\n copy_memory_to_memory_with_cleanup(add(value0, 0x20), pos, length)\n end := add(pos, length)\n }\n function abi_encode_tuple_t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 26)\n mstore(add(headStart, 64), \"WitnetProxy: not compliant\")\n tail := add(headStart, 96)\n }\n function abi_encode_tuple_t_stringliteral_ba8d4d661ce88eb2915ba133e6cad533938b754d7b66d8253879ef2c2193ecb2__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 27)\n mstore(add(headStart, 64), \"WitnetProxy: not authorized\")\n tail := add(headStart, 96)\n }\n function abi_decode_tuple_t_bytes32_fromMemory(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n value0 := mload(headStart)\n }\n function abi_encode_tuple_t_stringliteral_f3c1ad1fa1688d47e62cc4dd5b4be101315ef47e38e05aa3a37a4ef2e1cec0a8__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 36)\n mstore(add(headStart, 64), \"WitnetProxy: proxiableUUIDs mism\")\n mstore(add(headStart, 96), \"atch\")\n tail := add(headStart, 128)\n }\n function abi_encode_tuple_t_bytes_memory_ptr__to_t_bytes_memory_ptr__fromStack_reversed(headStart, value0) -> tail\n {\n mstore(headStart, 32)\n let length := mload(value0)\n mstore(add(headStart, 32), length)\n copy_memory_to_memory_with_cleanup(add(value0, 32), add(headStart, 64), length)\n tail := add(add(headStart, and(add(length, 31), not(31))), 64)\n }\n function abi_encode_tuple_t_stringliteral_55e9f07b665adf0e8c084720fbd831f583a2d75f5997894b64a77e28a0171f3c__to_t_string_memory_ptr__fromStack_reversed(headStart) -> tail\n {\n mstore(headStart, 32)\n mstore(add(headStart, 32), 33)\n mstore(add(headStart, 64), \"WitnetProxy: unable to initializ\")\n mstore(add(headStart, 96), \"e\")\n tail := add(headStart, 128)\n }\n}", - "id": 84, - "language": "Yul", - "name": "#utility.yul" - } - ], - "sourceMap": "244:4800:28:-:0;;;500:17;;;;;;;;;;244:4800;;;;;;", - "deployedSourceMap": "244:4800:28:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;726:23;752:16;:14;:16::i;:::-;726:42;;1116:4;1110:11;1156:14;1153:1;1148:3;1135:36;1260:1;1257;1241:14;1236:3;1219:15;1212:5;1199:63;1288:16;1341:4;1338:1;1333:3;1318:28;1367:6;1391:119;;;;1653:4;1648:3;1641:17;1391:119;1485:4;1480:3;1473:17;1761:110;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;178:32:84;;;160:51;;148:2;133:18;1761:110:28;;;;;;;;2165:2454;;;;;;;;;;-1:-1:-1;2165:2454:28;;;;;:::i;:::-;;:::i;:::-;;;1619:14:84;;1612:22;1594:41;;1582:2;1567:18;2165:2454:28;1454:187:84;1761:110:28;4955:66;1835:28;-1:-1:-1;;;;;1835:28:28;;1761:110::o;2165:2454::-;2261:4;-1:-1:-1;;;;;2338:32:28;;2330:77;;;;-1:-1:-1;;;2330:77:28;;1848:2:84;2330:77:28;;;1830:21:84;;;1867:18;;;1860:30;1926:34;1906:18;;;1899:62;1978:18;;2330:77:28;;;;;;;;;2420:26;2449:16;:14;:16::i;:::-;2420:45;-1:-1:-1;;;;;;2480:32:28;;;2476:1285;;2632:18;-1:-1:-1;;;;;2610:40:28;:18;-1:-1:-1;;;;;2610:40:28;;2602:84;;;;-1:-1:-1;;;2602:84:28;;2209:2:84;2602:84:28;;;2191:21:84;2248:2;2228:18;;;2221:30;2287:33;2267:18;;;2260:61;2338:18;;2602:84:28;2007:355:84;2602:84:28;2802:18;-1:-1:-1;;;;;2790:44:28;;:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2790:46:28;;;;;;;;-1:-1:-1;;2790:46:28;;;;;;;;;;;;:::i;:::-;;;2786:262;;2980:52;;-1:-1:-1;;;2980:52:28;;2851:2:84;2980:52:28;;;2833:21:84;2890:2;2870:18;;;2863:30;2929:34;2909:18;;;2902:62;-1:-1:-1;;;2980:18:84;;;2973:40;3030:19;;2980:52:28;2649:406:84;2786:262:28;2893:13;2885:53;;;;-1:-1:-1;;;2885:53:28;;3262:2:84;2885:53:28;;;3244:21:84;3301:2;3281:18;;;3274:30;3340:29;3320:18;;;3313:57;3387:18;;2885:53:28;3060:351:84;2885:53:28;-1:-1:-1;3252:125:28;;3348:10;3252:125;;;160:51:84;3161:15:28;;;;-1:-1:-1;;;;;3202:31:28;;;133:18:84;;3252:125:28;;;-1:-1:-1;;3252:125:28;;;;;;;;;;;;;;-1:-1:-1;;;;;3252:125:28;-1:-1:-1;;;3252:125:28;;;3202:190;;;3252:125;3202:190;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3160:232;;;;3415:10;3407:49;;;;-1:-1:-1;;;3407:49:28;;4165:2:84;3407:49:28;;;4147:21:84;4204:2;4184:18;;;4177:30;4243:28;4223:18;;;4216:56;4289:18;;3407:49:28;3963:350:84;3407:49:28;3490:7;3479:27;;;;;;;;;;;;:::i;:::-;3471:67;;;;-1:-1:-1;;;3471:67:28;;4520:2:84;3471:67:28;;;4502:21:84;4559:2;4539:18;;;4532:30;4598:29;4578:18;;;4571:57;4645:18;;3471:67:28;4318:351:84;3471:67:28;3642:18;-1:-1:-1;;;;;3630:45:28;;:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3591:18;-1:-1:-1;;;;;3579:45:28;;:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:98;3553:196;;;;-1:-1:-1;;;3553:196:28;;5065:2:84;3553:196:28;;;5047:21:84;5104:2;5084:18;;;5077:30;5143:34;5123:18;;;5116:62;-1:-1:-1;;;5194:18:84;;;5187:34;5238:19;;3553:196:28;4863:400:84;3553:196:28;2514:1247;;2476:1285;3846:20;3871:18;-1:-1:-1;;;;;3871:31:28;3997:9;3917:104;;;;;;;;:::i;:::-;;;;-1:-1:-1;;3917:104:28;;;;;;;;;;;;;;-1:-1:-1;;;;;3917:104:28;-1:-1:-1;;;3917:104:28;;;3871:161;;;3917:104;3871:161;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3845:187;;;4051:15;4043:61;;;;-1:-1:-1;;;4043:61:28;;5869:2:84;4043:61:28;;;5851:21:84;5908:2;5888:18;;;5881:30;5947:34;5927:18;;;5920:62;-1:-1:-1;;;5998:18:84;;;5991:31;6039:19;;4043:61:28;5667:397:84;4043:61:28;4955:66;4199:49;;-1:-1:-1;;;;;;4199:49:28;-1:-1:-1;;;;;4199:49:28;;;;;;;;4264:28;;;;-1:-1:-1;;4264:28:28;4421:18;-1:-1:-1;;;;;4409:44:28;;:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4409:46:28;;;;;;;;-1:-1:-1;;4409:46:28;;;;;;;;;;;;:::i;:::-;;;4405:207;;4563:37;;-1:-1:-1;;;4563:37:28;;4165:2:84;4563:37:28;;;4147:21:84;4204:2;4184:18;;;4177:30;4243:28;4223:18;;;4216:56;4289:18;;4563:37:28;3963:350:84;4405:207:28;4507:13;-1:-1:-1;4500:20:28;;-1:-1:-1;;4500:20:28;2165:2454;;;;;:::o;222:127:84:-;283:10;278:3;274:20;271:1;264:31;314:4;311:1;304:15;338:4;335:1;328:15;354:1095;431:6;439;492:2;480:9;471:7;467:23;463:32;460:52;;;508:1;505;498:12;460:52;534:23;;-1:-1:-1;;;;;586:31:84;;576:42;;566:70;;632:1;629;622:12;566:70;655:5;-1:-1:-1;711:2:84;696:18;;683:32;734:18;764:14;;;761:34;;;791:1;788;781:12;761:34;829:6;818:9;814:22;804:32;;874:7;867:4;863:2;859:13;855:27;845:55;;896:1;893;886:12;845:55;932:2;919:16;954:2;950;947:10;944:36;;;960:18;;:::i;:::-;1035:2;1029:9;1003:2;1089:13;;-1:-1:-1;;1085:22:84;;;1109:2;1081:31;1077:40;1065:53;;;1133:18;;;1153:22;;;1130:46;1127:72;;;1179:18;;:::i;:::-;1219:10;1215:2;1208:22;1254:2;1246:6;1239:18;1294:7;1289:2;1284;1280;1276:11;1272:20;1269:33;1266:53;;;1315:1;1312;1305:12;1266:53;1371:2;1366;1362;1358:11;1353:2;1345:6;1341:15;1328:46;1416:1;1411:2;1406;1398:6;1394:15;1390:24;1383:35;1437:6;1427:16;;;;;;;354:1095;;;;;:::o;2367:277::-;2434:6;2487:2;2475:9;2466:7;2462:23;2458:32;2455:52;;;2503:1;2500;2493:12;2455:52;2535:9;2529:16;2588:5;2581:13;2574:21;2567:5;2564:32;2554:60;;2610:1;2607;2600:12;2554:60;2633:5;2367:277;-1:-1:-1;;;2367:277:84:o;3416:250::-;3501:1;3511:113;3525:6;3522:1;3519:13;3511:113;;;3601:11;;;3595:18;3582:11;;;3575:39;3547:2;3540:10;3511:113;;;-1:-1:-1;;3658:1:84;3640:16;;3633:27;3416:250::o;3671:287::-;3800:3;3838:6;3832:13;3854:66;3913:6;3908:3;3901:4;3893:6;3889:17;3854:66;:::i;:::-;3936:16;;;;;3671:287;-1:-1:-1;;3671:287:84:o;4674:184::-;4744:6;4797:2;4785:9;4776:7;4772:23;4768:32;4765:52;;;4813:1;4810;4803:12;4765:52;-1:-1:-1;4836:16:84;;4674:184;-1:-1:-1;4674:184:84:o;5268:394::-;5415:2;5404:9;5397:21;5378:4;5447:6;5441:13;5490:6;5485:2;5474:9;5470:18;5463:34;5506:79;5578:6;5573:2;5562:9;5558:18;5553:2;5545:6;5541:15;5506:79;:::i;:::-;5646:2;5625:15;-1:-1:-1;;5621:29:84;5606:45;;;;5653:2;5602:54;;5268:394;-1:-1:-1;;5268:394:84:o", - "source": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity >=0.7.0 <0.9.0;\r\npragma experimental ABIEncoderV2;\r\n\r\nimport \"../patterns/Upgradeable.sol\";\r\n\r\n/// @title WitnetProxy: upgradable delegate-proxy contract. \r\n/// @author The Witnet Foundation.\r\ncontract WitnetProxy {\r\n\r\n /// Event emitted every time the implementation gets updated.\r\n event Upgraded(address indexed implementation); \r\n\r\n /// Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470).\r\n constructor () {}\r\n\r\n receive() virtual external payable {}\r\n\r\n /// Payable fallback accepts delegating calls to payable functions. \r\n fallback() external payable { /* solhint-disable no-complex-fallback */\r\n address _implementation = implementation();\r\n assembly { /* solhint-disable avoid-low-level-calls */\r\n // Gas optimized delegate call to 'implementation' contract.\r\n // Note: `msg.data`, `msg.sender` and `msg.value` will be passed over \r\n // to actual implementation of `msg.sig` within `implementation` contract.\r\n let ptr := mload(0x40)\r\n calldatacopy(ptr, 0, calldatasize())\r\n let result := delegatecall(gas(), _implementation, ptr, calldatasize(), 0, 0)\r\n let size := returndatasize()\r\n returndatacopy(ptr, 0, size)\r\n switch result\r\n case 0 { \r\n // pass back revert message:\r\n revert(ptr, size) \r\n }\r\n default {\r\n // pass back same data as returned by 'implementation' contract:\r\n return(ptr, size) \r\n }\r\n }\r\n }\r\n\r\n /// Returns proxy's current implementation address.\r\n function implementation() public view returns (address) {\r\n return __proxySlot().implementation;\r\n }\r\n\r\n /// Upgrades the `implementation` address.\r\n /// @param _newImplementation New implementation address.\r\n /// @param _initData Raw data with which new implementation will be initialized.\r\n /// @return Returns whether new implementation would be further upgradable, or not.\r\n function upgradeTo(address _newImplementation, bytes memory _initData)\r\n public returns (bool)\r\n {\r\n // New implementation cannot be null:\r\n require(_newImplementation != address(0), \"WitnetProxy: null implementation\");\r\n\r\n address _oldImplementation = implementation();\r\n if (_oldImplementation != address(0)) {\r\n // New implementation address must differ from current one:\r\n require(_newImplementation != _oldImplementation, \"WitnetProxy: nothing to upgrade\");\r\n\r\n // Assert whether current implementation is intrinsically upgradable:\r\n try Upgradeable(_oldImplementation).isUpgradable() returns (bool _isUpgradable) {\r\n require(_isUpgradable, \"WitnetProxy: not upgradable\");\r\n } catch {\r\n revert(\"WitnetProxy: unable to check upgradability\");\r\n }\r\n\r\n // Assert whether current implementation allows `msg.sender` to upgrade the proxy:\r\n (bool _wasCalled, bytes memory _result) = _oldImplementation.delegatecall(\r\n abi.encodeWithSignature(\r\n \"isUpgradableFrom(address)\",\r\n msg.sender\r\n )\r\n );\r\n require(_wasCalled, \"WitnetProxy: not compliant\");\r\n require(abi.decode(_result, (bool)), \"WitnetProxy: not authorized\");\r\n require(\r\n Upgradeable(_oldImplementation).proxiableUUID() == Upgradeable(_newImplementation).proxiableUUID(),\r\n \"WitnetProxy: proxiableUUIDs mismatch\"\r\n );\r\n }\r\n\r\n // Initialize new implementation within proxy-context storage:\r\n (bool _wasInitialized,) = _newImplementation.delegatecall(\r\n abi.encodeWithSignature(\r\n \"initialize(bytes)\",\r\n _initData\r\n )\r\n );\r\n require(_wasInitialized, \"WitnetProxy: unable to initialize\");\r\n\r\n // If all checks and initialization pass, update implementation address:\r\n __proxySlot().implementation = _newImplementation;\r\n emit Upgraded(_newImplementation);\r\n\r\n // Asserts new implementation complies w/ minimal implementation of Upgradeable interface:\r\n try Upgradeable(_newImplementation).isUpgradable() returns (bool _isUpgradable) {\r\n return _isUpgradable;\r\n }\r\n catch {\r\n revert (\"WitnetProxy: not compliant\");\r\n }\r\n }\r\n\r\n /// @dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address.\r\n function __proxySlot() private pure returns (Proxiable.ProxiableSlot storage _slot) {\r\n assembly {\r\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\r\n _slot.slot := 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc\r\n }\r\n }\r\n\r\n}\r\n", - "sourcePath": "C:\\Users\\guill\\github\\guidiaz\\witnet-solidity-bridge\\contracts\\impls\\WitnetProxy.sol", - "ast": { - "absolutePath": "project:/contracts/impls/WitnetProxy.sol", - "exportedSymbols": { - "AddressUpgradeable": [ - 452 - ], - "Initializable": [ - 168 - ], - "Proxiable": [ - 23471 - ], - "Upgradeable": [ - 23590 - ], - "WitnetProxy": [ - 6719 - ] - }, - "id": 6720, - "license": "MIT", - "nodeType": "SourceUnit", - "nodes": [ - { - "id": 6517, - "literals": [ - "solidity", - ">=", - "0.7", - ".0", - "<", - "0.9", - ".0" - ], - "nodeType": "PragmaDirective", - "src": "35:31:28" - }, - { - "id": 6518, - "literals": [ - "experimental", - "ABIEncoderV2" - ], - "nodeType": "PragmaDirective", - "src": "68:33:28" - }, - { - "absolutePath": "project:/contracts/patterns/Upgradeable.sol", - "file": "../patterns/Upgradeable.sol", - "id": 6519, - "nameLocation": "-1:-1:-1", - "nodeType": "ImportDirective", - "scope": 6720, - "sourceUnit": 23591, - "src": "105:37:28", - "symbolAliases": [], - "unitAlias": "" - }, - { - "abstract": false, - "baseContracts": [], - "canonicalName": "WitnetProxy", - "contractDependencies": [], - "contractKind": "contract", - "documentation": { - "id": 6520, - "nodeType": "StructuredDocumentation", - "src": "146:98:28", - "text": "@title WitnetProxy: upgradable delegate-proxy contract. \n @author The Witnet Foundation." - }, - "fullyImplemented": true, - "id": 6719, - "linearizedBaseContracts": [ - 6719 - ], - "name": "WitnetProxy", - "nameLocation": "253:11:28", - "nodeType": "ContractDefinition", - "nodes": [ - { - "anonymous": false, - "documentation": { - "id": 6521, - "nodeType": "StructuredDocumentation", - "src": "274:61:28", - "text": "Event emitted every time the implementation gets updated." - }, - "eventSelector": "bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", - "id": 6525, - "name": "Upgraded", - "nameLocation": "347:8:28", - "nodeType": "EventDefinition", - "parameters": { - "id": 6524, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6523, - "indexed": true, - "mutability": "mutable", - "name": "implementation", - "nameLocation": "372:14:28", - "nodeType": "VariableDeclaration", - "scope": 6525, - "src": "356:30:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 6522, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "356:7:28", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "355:32:28" - }, - "src": "341:47:28" - }, - { - "body": { - "id": 6529, - "nodeType": "Block", - "src": "515:2:28", - "statements": [] - }, - "documentation": { - "id": 6526, - "nodeType": "StructuredDocumentation", - "src": "398:96:28", - "text": "Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470)." - }, - "id": 6530, - "implemented": true, - "kind": "constructor", - "modifiers": [], - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6527, - "nodeType": "ParameterList", - "parameters": [], - "src": "512:2:28" - }, - "returnParameters": { - "id": 6528, - "nodeType": "ParameterList", - "parameters": [], - "src": "515:0:28" - }, - "scope": 6719, - "src": "500:17:28", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "public" - }, - { - "body": { - "id": 6533, - "nodeType": "Block", - "src": "560:2:28", - "statements": [] - }, - "id": 6534, - "implemented": true, - "kind": "receive", - "modifiers": [], - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6531, - "nodeType": "ParameterList", - "parameters": [], - "src": "532:2:28" - }, - "returnParameters": { - "id": 6532, - "nodeType": "ParameterList", - "parameters": [], - "src": "560:0:28" - }, - "scope": 6719, - "src": "525:37:28", - "stateMutability": "payable", - "virtual": true, - "visibility": "external" - }, - { - "body": { - "id": 6544, - "nodeType": "Block", - "src": "673:1023:28", - "statements": [ - { - "assignments": [ - 6539 - ], - "declarations": [ - { - "constant": false, - "id": 6539, - "mutability": "mutable", - "name": "_implementation", - "nameLocation": "734:15:28", - "nodeType": "VariableDeclaration", - "scope": 6544, - "src": "726:23:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 6538, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "726:7:28", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "id": 6542, - "initialValue": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 6540, - "name": "implementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6556, - "src": "752:14:28", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", - "typeString": "function () view returns (address)" - } - }, - "id": 6541, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "752:16:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "726:42:28" - }, - { - "AST": { - "nodeType": "YulBlock", - "src": "788:901:28", - "statements": [ - { - "nodeType": "YulVariableDeclaration", - "src": "1099:22:28", - "value": { - "arguments": [ - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1116:4:28", - "type": "", - "value": "0x40" - } - ], - "functionName": { - "name": "mload", - "nodeType": "YulIdentifier", - "src": "1110:5:28" - }, - "nodeType": "YulFunctionCall", - "src": "1110:11:28" - }, - "variables": [ - { - "name": "ptr", - "nodeType": "YulTypedName", - "src": "1103:3:28", - "type": "" - } - ] - }, - { - "expression": { - "arguments": [ - { - "name": "ptr", - "nodeType": "YulIdentifier", - "src": "1148:3:28" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1153:1:28", - "type": "", - "value": "0" - }, - { - "arguments": [], - "functionName": { - "name": "calldatasize", - "nodeType": "YulIdentifier", - "src": "1156:12:28" - }, - "nodeType": "YulFunctionCall", - "src": "1156:14:28" - } - ], - "functionName": { - "name": "calldatacopy", - "nodeType": "YulIdentifier", - "src": "1135:12:28" - }, - "nodeType": "YulFunctionCall", - "src": "1135:36:28" - }, - "nodeType": "YulExpressionStatement", - "src": "1135:36:28" - }, - { - "nodeType": "YulVariableDeclaration", - "src": "1185:77:28", - "value": { - "arguments": [ - { - "arguments": [], - "functionName": { - "name": "gas", - "nodeType": "YulIdentifier", - "src": "1212:3:28" - }, - "nodeType": "YulFunctionCall", - "src": "1212:5:28" - }, - { - "name": "_implementation", - "nodeType": "YulIdentifier", - "src": "1219:15:28" - }, - { - "name": "ptr", - "nodeType": "YulIdentifier", - "src": "1236:3:28" - }, - { - "arguments": [], - "functionName": { - "name": "calldatasize", - "nodeType": "YulIdentifier", - "src": "1241:12:28" - }, - "nodeType": "YulFunctionCall", - "src": "1241:14:28" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1257:1:28", - "type": "", - "value": "0" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1260:1:28", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "delegatecall", - "nodeType": "YulIdentifier", - "src": "1199:12:28" - }, - "nodeType": "YulFunctionCall", - "src": "1199:63:28" - }, - "variables": [ - { - "name": "result", - "nodeType": "YulTypedName", - "src": "1189:6:28", - "type": "" - } - ] - }, - { - "nodeType": "YulVariableDeclaration", - "src": "1276:28:28", - "value": { - "arguments": [], - "functionName": { - "name": "returndatasize", - "nodeType": "YulIdentifier", - "src": "1288:14:28" - }, - "nodeType": "YulFunctionCall", - "src": "1288:16:28" - }, - "variables": [ - { - "name": "size", - "nodeType": "YulTypedName", - "src": "1280:4:28", - "type": "" - } - ] - }, - { - "expression": { - "arguments": [ - { - "name": "ptr", - "nodeType": "YulIdentifier", - "src": "1333:3:28" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1338:1:28", - "type": "", - "value": "0" - }, - { - "name": "size", - "nodeType": "YulIdentifier", - "src": "1341:4:28" - } - ], - "functionName": { - "name": "returndatacopy", - "nodeType": "YulIdentifier", - "src": "1318:14:28" - }, - "nodeType": "YulFunctionCall", - "src": "1318:28:28" - }, - "nodeType": "YulExpressionStatement", - "src": "1318:28:28" - }, - { - "cases": [ - { - "body": { - "nodeType": "YulBlock", - "src": "1399:111:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "ptr", - "nodeType": "YulIdentifier", - "src": "1480:3:28" - }, - { - "name": "size", - "nodeType": "YulIdentifier", - "src": "1485:4:28" - } - ], - "functionName": { - "name": "revert", - "nodeType": "YulIdentifier", - "src": "1473:6:28" - }, - "nodeType": "YulFunctionCall", - "src": "1473:17:28" - }, - "nodeType": "YulExpressionStatement", - "src": "1473:17:28" - } - ] - }, - "nodeType": "YulCase", - "src": "1391:119:28", - "value": { - "kind": "number", - "nodeType": "YulLiteral", - "src": "1396:1:28", - "type": "", - "value": "0" - } - }, - { - "body": { - "nodeType": "YulBlock", - "src": "1536:142:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "ptr", - "nodeType": "YulIdentifier", - "src": "1648:3:28" - }, - { - "name": "size", - "nodeType": "YulIdentifier", - "src": "1653:4:28" - } - ], - "functionName": { - "name": "return", - "nodeType": "YulIdentifier", - "src": "1641:6:28" - }, - "nodeType": "YulFunctionCall", - "src": "1641:17:28" - }, - "nodeType": "YulExpressionStatement", - "src": "1641:17:28" - } - ] - }, - "nodeType": "YulCase", - "src": "1528:150:28", - "value": "default" - } - ], - "expression": { - "name": "result", - "nodeType": "YulIdentifier", - "src": "1367:6:28" - }, - "nodeType": "YulSwitch", - "src": "1360:318:28" - } - ] - }, - "evmVersion": "london", - "externalReferences": [ - { - "declaration": 6539, - "isOffset": false, - "isSlot": false, - "src": "1219:15:28", - "valueSize": 1 - } - ], - "id": 6543, - "nodeType": "InlineAssembly", - "src": "779:910:28" - } - ] - }, - "documentation": { - "id": 6535, - "nodeType": "StructuredDocumentation", - "src": "570:69:28", - "text": "Payable fallback accepts delegating calls to payable functions. " - }, - "id": 6545, - "implemented": true, - "kind": "fallback", - "modifiers": [], - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6536, - "nodeType": "ParameterList", - "parameters": [], - "src": "653:2:28" - }, - "returnParameters": { - "id": 6537, - "nodeType": "ParameterList", - "parameters": [], - "src": "673:0:28" - }, - "scope": 6719, - "src": "645:1051:28", - "stateMutability": "payable", - "virtual": false, - "visibility": "external" - }, - { - "body": { - "id": 6555, - "nodeType": "Block", - "src": "1817:54:28", - "statements": [ - { - "expression": { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 6551, - "name": "__proxySlot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6718, - "src": "1835:11:28", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_ProxiableSlot_$23442_storage_ptr_$", - "typeString": "function () pure returns (struct Proxiable.ProxiableSlot storage pointer)" - } - }, - "id": 6552, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "1835:13:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_ProxiableSlot_$23442_storage_ptr", - "typeString": "struct Proxiable.ProxiableSlot storage pointer" - } - }, - "id": 6553, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": false, - "memberLocation": "1849:14:28", - "memberName": "implementation", - "nodeType": "MemberAccess", - "referencedDeclaration": 23439, - "src": "1835:28:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "functionReturnParameters": 6550, - "id": 6554, - "nodeType": "Return", - "src": "1828:35:28" - } - ] - }, - "documentation": { - "id": 6546, - "nodeType": "StructuredDocumentation", - "src": "1704:51:28", - "text": "Returns proxy's current implementation address." - }, - "functionSelector": "5c60da1b", - "id": 6556, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "implementation", - "nameLocation": "1770:14:28", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6547, - "nodeType": "ParameterList", - "parameters": [], - "src": "1784:2:28" - }, - "returnParameters": { - "id": 6550, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6549, - "mutability": "mutable", - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "VariableDeclaration", - "scope": 6556, - "src": "1808:7:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 6548, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "1808:7:28", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "src": "1807:9:28" - }, - "scope": 6719, - "src": "1761:110:28", - "stateMutability": "view", - "virtual": false, - "visibility": "public" - }, - { - "body": { - "id": 6708, - "nodeType": "Block", - "src": "2272:2347:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "commonType": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "id": 6572, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 6567, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "2338:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "arguments": [ - { - "hexValue": "30", - "id": 6570, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2368:1:28", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 6569, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "2360:7:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 6568, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "2360:7:28", - "typeDescriptions": {} - } - }, - "id": 6571, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2360:10:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "2338:32:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a206e756c6c20696d706c656d656e746174696f6e", - "id": 6573, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2372:34:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_d599eaa5e68d91d75c142446490ab9a15fd0284a41ce949219b5b4d8f267239a", - "typeString": "literal_string \"WitnetProxy: null implementation\"" - }, - "value": "WitnetProxy: null implementation" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_d599eaa5e68d91d75c142446490ab9a15fd0284a41ce949219b5b4d8f267239a", - "typeString": "literal_string \"WitnetProxy: null implementation\"" - } - ], - "id": 6566, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "2330:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6574, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2330:77:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6575, - "nodeType": "ExpressionStatement", - "src": "2330:77:28" - }, - { - "assignments": [ - 6577 - ], - "declarations": [ - { - "constant": false, - "id": 6577, - "mutability": "mutable", - "name": "_oldImplementation", - "nameLocation": "2428:18:28", - "nodeType": "VariableDeclaration", - "scope": 6708, - "src": "2420:26:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 6576, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "2420:7:28", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - } - ], - "id": 6580, - "initialValue": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 6578, - "name": "implementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6556, - "src": "2449:14:28", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", - "typeString": "function () view returns (address)" - } - }, - "id": 6579, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2449:16:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "2420:45:28" - }, - { - "condition": { - "commonType": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "id": 6586, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 6581, - "name": "_oldImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6577, - "src": "2480:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "arguments": [ - { - "hexValue": "30", - "id": 6584, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2510:1:28", - "typeDescriptions": { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - }, - "value": "0" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_rational_0_by_1", - "typeString": "int_const 0" - } - ], - "id": 6583, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "2502:7:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_address_$", - "typeString": "type(address)" - }, - "typeName": { - "id": 6582, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "2502:7:28", - "typeDescriptions": {} - } - }, - "id": 6585, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2502:10:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "2480:32:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 6662, - "nodeType": "IfStatement", - "src": "2476:1285:28", - "trueBody": { - "id": 6661, - "nodeType": "Block", - "src": "2514:1247:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "commonType": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "id": 6590, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "id": 6588, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "2610:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "BinaryOperation", - "operator": "!=", - "rightExpression": { - "id": 6589, - "name": "_oldImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6577, - "src": "2632:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "2610:40:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a206e6f7468696e6720746f2075706772616465", - "id": 6591, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2652:33:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_e332eab1bae45430d1201a30c0d80d8fcb5570f9e70201a9eb7b229e17fd2084", - "typeString": "literal_string \"WitnetProxy: nothing to upgrade\"" - }, - "value": "WitnetProxy: nothing to upgrade" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_e332eab1bae45430d1201a30c0d80d8fcb5570f9e70201a9eb7b229e17fd2084", - "typeString": "literal_string \"WitnetProxy: nothing to upgrade\"" - } - ], - "id": 6587, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "2602:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6592, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2602:84:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6593, - "nodeType": "ExpressionStatement", - "src": "2602:84:28" - }, - { - "clauses": [ - { - "block": { - "id": 6607, - "nodeType": "Block", - "src": "2866:88:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "id": 6603, - "name": "_isUpgradable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6600, - "src": "2893:13:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a206e6f742075706772616461626c65", - "id": 6604, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2908:29:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_d96132834a96bae5cb2f32cb07f13985dcde0f2358055c198eb3065af6c5aa7f", - "typeString": "literal_string \"WitnetProxy: not upgradable\"" - }, - "value": "WitnetProxy: not upgradable" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_d96132834a96bae5cb2f32cb07f13985dcde0f2358055c198eb3065af6c5aa7f", - "typeString": "literal_string \"WitnetProxy: not upgradable\"" - } - ], - "id": 6602, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "2885:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6605, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2885:53:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6606, - "nodeType": "ExpressionStatement", - "src": "2885:53:28" - } - ] - }, - "errorName": "", - "id": 6608, - "nodeType": "TryCatchClause", - "parameters": { - "id": 6601, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6600, - "mutability": "mutable", - "name": "_isUpgradable", - "nameLocation": "2851:13:28", - "nodeType": "VariableDeclaration", - "scope": 6608, - "src": "2846:18:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 6599, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "2846:4:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "2845:20:28" - }, - "src": "2837:117:28" - }, - { - "block": { - "id": 6613, - "nodeType": "Block", - "src": "2961:87:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "hexValue": "5769746e657450726f78793a20756e61626c6520746f20636865636b207570677261646162696c697479", - "id": 6610, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "2987:44:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_7f859058ad3ee4e192700ff813ed67dc892a0c7de91510ee584a0ac25fc982fc", - "typeString": "literal_string \"WitnetProxy: unable to check upgradability\"" - }, - "value": "WitnetProxy: unable to check upgradability" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_7f859058ad3ee4e192700ff813ed67dc892a0c7de91510ee584a0ac25fc982fc", - "typeString": "literal_string \"WitnetProxy: unable to check upgradability\"" - } - ], - "id": 6609, - "name": "revert", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967277, - 4294967277 - ], - "referencedDeclaration": 4294967277, - "src": "2980:6:28", - "typeDescriptions": { - "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", - "typeString": "function (string memory) pure" - } - }, - "id": 6611, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2980:52:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6612, - "nodeType": "ExpressionStatement", - "src": "2980:52:28" - } - ] - }, - "errorName": "", - "id": 6614, - "nodeType": "TryCatchClause", - "src": "2955:93:28" - } - ], - "externalCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "expression": { - "arguments": [ - { - "id": 6595, - "name": "_oldImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6577, - "src": "2802:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 6594, - "name": "Upgradeable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 23590, - "src": "2790:11:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Upgradeable_$23590_$", - "typeString": "type(contract Upgradeable)" - } - }, - "id": 6596, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2790:31:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_Upgradeable_$23590", - "typeString": "contract Upgradeable" - } - }, - "id": 6597, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "2822:12:28", - "memberName": "isUpgradable", - "nodeType": "MemberAccess", - "referencedDeclaration": 23569, - "src": "2790:44:28", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$__$returns$_t_bool_$", - "typeString": "function () view external returns (bool)" - } - }, - "id": 6598, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "2790:46:28", - "tryCall": true, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 6615, - "nodeType": "TryStatement", - "src": "2786:262:28" - }, - { - "assignments": [ - 6617, - 6619 - ], - "declarations": [ - { - "constant": false, - "id": 6617, - "mutability": "mutable", - "name": "_wasCalled", - "nameLocation": "3166:10:28", - "nodeType": "VariableDeclaration", - "scope": 6661, - "src": "3161:15:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 6616, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "3161:4:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 6619, - "mutability": "mutable", - "name": "_result", - "nameLocation": "3191:7:28", - "nodeType": "VariableDeclaration", - "scope": 6661, - "src": "3178:20:28", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 6618, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "3178:5:28", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "id": 6629, - "initialValue": { - "arguments": [ - { - "arguments": [ - { - "hexValue": "697355706772616461626c6546726f6d286164647265737329", - "id": 6624, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "3298:27:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_6b58960af5008b519145bb1cb07a67ee0927d8e642573c92f5babc4d0c2721d7", - "typeString": "literal_string \"isUpgradableFrom(address)\"" - }, - "value": "isUpgradableFrom(address)" - }, - { - "expression": { - "id": 6625, - "name": "msg", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 4294967281, - "src": "3348:3:28", - "typeDescriptions": { - "typeIdentifier": "t_magic_message", - "typeString": "msg" - } - }, - "id": 6626, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "3352:6:28", - "memberName": "sender", - "nodeType": "MemberAccess", - "src": "3348:10:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_6b58960af5008b519145bb1cb07a67ee0927d8e642573c92f5babc4d0c2721d7", - "typeString": "literal_string \"isUpgradableFrom(address)\"" - }, - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "expression": { - "id": 6622, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 4294967295, - "src": "3252:3:28", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 6623, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "3256:19:28", - "memberName": "encodeWithSignature", - "nodeType": "MemberAccess", - "src": "3252:23:28", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", - "typeString": "function (string memory) pure returns (bytes memory)" - } - }, - "id": 6627, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3252:125:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 6620, - "name": "_oldImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6577, - "src": "3202:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 6621, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "3221:12:28", - "memberName": "delegatecall", - "nodeType": "MemberAccess", - "src": "3202:31:28", - "typeDescriptions": { - "typeIdentifier": "t_function_baredelegatecall_nonpayable$_t_bytes_memory_ptr_$returns$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "function (bytes memory) returns (bool,bytes memory)" - } - }, - "id": 6628, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3202:190:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "tuple(bool,bytes memory)" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "3160:232:28" - }, - { - "expression": { - "arguments": [ - { - "id": 6631, - "name": "_wasCalled", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6617, - "src": "3415:10:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a206e6f7420636f6d706c69616e74", - "id": 6632, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "3427:28:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65", - "typeString": "literal_string \"WitnetProxy: not compliant\"" - }, - "value": "WitnetProxy: not compliant" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65", - "typeString": "literal_string \"WitnetProxy: not compliant\"" - } - ], - "id": 6630, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "3407:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6633, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3407:49:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6634, - "nodeType": "ExpressionStatement", - "src": "3407:49:28" - }, - { - "expression": { - "arguments": [ - { - "arguments": [ - { - "id": 6638, - "name": "_result", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6619, - "src": "3490:7:28", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - }, - { - "components": [ - { - "id": 6640, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "ElementaryTypeNameExpression", - "src": "3500:4:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_bool_$", - "typeString": "type(bool)" - }, - "typeName": { - "id": 6639, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "3500:4:28", - "typeDescriptions": {} - } - } - ], - "id": 6641, - "isConstant": false, - "isInlineArray": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "nodeType": "TupleExpression", - "src": "3499:6:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_bool_$", - "typeString": "type(bool)" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - }, - { - "typeIdentifier": "t_type$_t_bool_$", - "typeString": "type(bool)" - } - ], - "expression": { - "id": 6636, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 4294967295, - "src": "3479:3:28", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 6637, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "3483:6:28", - "memberName": "decode", - "nodeType": "MemberAccess", - "src": "3479:10:28", - "typeDescriptions": { - "typeIdentifier": "t_function_abidecode_pure$__$returns$__$", - "typeString": "function () pure" - } - }, - "id": 6642, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3479:27:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a206e6f7420617574686f72697a6564", - "id": 6643, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "3508:29:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_ba8d4d661ce88eb2915ba133e6cad533938b754d7b66d8253879ef2c2193ecb2", - "typeString": "literal_string \"WitnetProxy: not authorized\"" - }, - "value": "WitnetProxy: not authorized" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_ba8d4d661ce88eb2915ba133e6cad533938b754d7b66d8253879ef2c2193ecb2", - "typeString": "literal_string \"WitnetProxy: not authorized\"" - } - ], - "id": 6635, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "3471:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6644, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3471:67:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6645, - "nodeType": "ExpressionStatement", - "src": "3471:67:28" - }, - { - "expression": { - "arguments": [ - { - "commonType": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - }, - "id": 6657, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftExpression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "expression": { - "arguments": [ - { - "id": 6648, - "name": "_oldImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6577, - "src": "3591:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 6647, - "name": "Upgradeable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 23590, - "src": "3579:11:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Upgradeable_$23590_$", - "typeString": "type(contract Upgradeable)" - } - }, - "id": 6649, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3579:31:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_Upgradeable_$23590", - "typeString": "contract Upgradeable" - } - }, - "id": 6650, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "3611:13:28", - "memberName": "proxiableUUID", - "nodeType": "MemberAccess", - "referencedDeclaration": 23437, - "src": "3579:45:28", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$__$returns$_t_bytes32_$", - "typeString": "function () view external returns (bytes32)" - } - }, - "id": 6651, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3579:47:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "nodeType": "BinaryOperation", - "operator": "==", - "rightExpression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "expression": { - "arguments": [ - { - "id": 6653, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "3642:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 6652, - "name": "Upgradeable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 23590, - "src": "3630:11:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Upgradeable_$23590_$", - "typeString": "type(contract Upgradeable)" - } - }, - "id": 6654, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3630:31:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_Upgradeable_$23590", - "typeString": "contract Upgradeable" - } - }, - "id": 6655, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "3662:13:28", - "memberName": "proxiableUUID", - "nodeType": "MemberAccess", - "referencedDeclaration": 23437, - "src": "3630:45:28", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$__$returns$_t_bytes32_$", - "typeString": "function () view external returns (bytes32)" - } - }, - "id": 6656, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3630:47:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes32", - "typeString": "bytes32" - } - }, - "src": "3579:98:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a2070726f786961626c655555494473206d69736d61746368", - "id": 6658, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "3696:38:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_f3c1ad1fa1688d47e62cc4dd5b4be101315ef47e38e05aa3a37a4ef2e1cec0a8", - "typeString": "literal_string \"WitnetProxy: proxiableUUIDs mismatch\"" - }, - "value": "WitnetProxy: proxiableUUIDs mismatch" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_f3c1ad1fa1688d47e62cc4dd5b4be101315ef47e38e05aa3a37a4ef2e1cec0a8", - "typeString": "literal_string \"WitnetProxy: proxiableUUIDs mismatch\"" - } - ], - "id": 6646, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "3553:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6659, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3553:196:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6660, - "nodeType": "ExpressionStatement", - "src": "3553:196:28" - } - ] - } - }, - { - "assignments": [ - 6664, - null - ], - "declarations": [ - { - "constant": false, - "id": 6664, - "mutability": "mutable", - "name": "_wasInitialized", - "nameLocation": "3851:15:28", - "nodeType": "VariableDeclaration", - "scope": 6708, - "src": "3846:20:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 6663, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "3846:4:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - }, - null - ], - "id": 6673, - "initialValue": { - "arguments": [ - { - "arguments": [ - { - "hexValue": "696e697469616c697a6528627974657329", - "id": 6669, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "3959:19:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_439fab91f8ccf5be59586b9cf7bb7786c67a661a95ce1cfc146c1ed62922ae26", - "typeString": "literal_string \"initialize(bytes)\"" - }, - "value": "initialize(bytes)" - }, - { - "id": 6670, - "name": "_initData", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6561, - "src": "3997:9:28", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_439fab91f8ccf5be59586b9cf7bb7786c67a661a95ce1cfc146c1ed62922ae26", - "typeString": "literal_string \"initialize(bytes)\"" - }, - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 6667, - "name": "abi", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 4294967295, - "src": "3917:3:28", - "typeDescriptions": { - "typeIdentifier": "t_magic_abi", - "typeString": "abi" - } - }, - "id": 6668, - "isConstant": false, - "isLValue": false, - "isPure": true, - "lValueRequested": false, - "memberLocation": "3921:19:28", - "memberName": "encodeWithSignature", - "nodeType": "MemberAccess", - "src": "3917:23:28", - "typeDescriptions": { - "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", - "typeString": "function (string memory) pure returns (bytes memory)" - } - }, - "id": 6671, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3917:104:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes memory" - } - ], - "expression": { - "id": 6665, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "3871:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 6666, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "3890:12:28", - "memberName": "delegatecall", - "nodeType": "MemberAccess", - "src": "3871:31:28", - "typeDescriptions": { - "typeIdentifier": "t_function_baredelegatecall_nonpayable$_t_bytes_memory_ptr_$returns$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "function (bytes memory) returns (bool,bytes memory)" - } - }, - "id": 6672, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "3871:161:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$_t_bool_$_t_bytes_memory_ptr_$", - "typeString": "tuple(bool,bytes memory)" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "3845:187:28" - }, - { - "expression": { - "arguments": [ - { - "id": 6675, - "name": "_wasInitialized", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6664, - "src": "4051:15:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - { - "hexValue": "5769746e657450726f78793a20756e61626c6520746f20696e697469616c697a65", - "id": 6676, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "4068:35:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_55e9f07b665adf0e8c084720fbd831f583a2d75f5997894b64a77e28a0171f3c", - "typeString": "literal_string \"WitnetProxy: unable to initialize\"" - }, - "value": "WitnetProxy: unable to initialize" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - { - "typeIdentifier": "t_stringliteral_55e9f07b665adf0e8c084720fbd831f583a2d75f5997894b64a77e28a0171f3c", - "typeString": "literal_string \"WitnetProxy: unable to initialize\"" - } - ], - "id": 6674, - "name": "require", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967278, - 4294967278 - ], - "referencedDeclaration": 4294967278, - "src": "4043:7:28", - "typeDescriptions": { - "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", - "typeString": "function (bool,string memory) pure" - } - }, - "id": 6677, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4043:61:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6678, - "nodeType": "ExpressionStatement", - "src": "4043:61:28" - }, - { - "expression": { - "id": 6683, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "expression": { - "arguments": [], - "expression": { - "argumentTypes": [], - "id": 6679, - "name": "__proxySlot", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6718, - "src": "4199:11:28", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_pure$__$returns$_t_struct$_ProxiableSlot_$23442_storage_ptr_$", - "typeString": "function () pure returns (struct Proxiable.ProxiableSlot storage pointer)" - } - }, - "id": 6680, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4199:13:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_struct$_ProxiableSlot_$23442_storage_ptr", - "typeString": "struct Proxiable.ProxiableSlot storage pointer" - } - }, - "id": 6681, - "isConstant": false, - "isLValue": true, - "isPure": false, - "lValueRequested": true, - "memberLocation": "4213:14:28", - "memberName": "implementation", - "nodeType": "MemberAccess", - "referencedDeclaration": 23439, - "src": "4199:28:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "id": 6682, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "4230:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "src": "4199:49:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "id": 6684, - "nodeType": "ExpressionStatement", - "src": "4199:49:28" - }, - { - "eventCall": { - "arguments": [ - { - "id": 6686, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "4273:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 6685, - "name": "Upgraded", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6525, - "src": "4264:8:28", - "typeDescriptions": { - "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", - "typeString": "function (address)" - } - }, - "id": 6687, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4264:28:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6688, - "nodeType": "EmitStatement", - "src": "4259:33:28" - }, - { - "clauses": [ - { - "block": { - "id": 6699, - "nodeType": "Block", - "src": "4485:47:28", - "statements": [ - { - "expression": { - "id": 6697, - "name": "_isUpgradable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6695, - "src": "4507:13:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "functionReturnParameters": 6565, - "id": 6698, - "nodeType": "Return", - "src": "4500:20:28" - } - ] - }, - "errorName": "", - "id": 6700, - "nodeType": "TryCatchClause", - "parameters": { - "id": 6696, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6695, - "mutability": "mutable", - "name": "_isUpgradable", - "nameLocation": "4470:13:28", - "nodeType": "VariableDeclaration", - "scope": 6700, - "src": "4465:18:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 6694, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "4465:4:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "4464:20:28" - }, - "src": "4456:76:28" - }, - { - "block": { - "id": 6705, - "nodeType": "Block", - "src": "4548:64:28", - "statements": [ - { - "expression": { - "arguments": [ - { - "hexValue": "5769746e657450726f78793a206e6f7420636f6d706c69616e74", - "id": 6702, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "string", - "lValueRequested": false, - "nodeType": "Literal", - "src": "4571:28:28", - "typeDescriptions": { - "typeIdentifier": "t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65", - "typeString": "literal_string \"WitnetProxy: not compliant\"" - }, - "value": "WitnetProxy: not compliant" - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_stringliteral_fe0c5d56f2e637bc6ae9d29f1058c00159080f3dd6202013ecdbcca6e4740a65", - "typeString": "literal_string \"WitnetProxy: not compliant\"" - } - ], - "id": 6701, - "name": "revert", - "nodeType": "Identifier", - "overloadedDeclarations": [ - 4294967277, - 4294967277 - ], - "referencedDeclaration": 4294967277, - "src": "4563:6:28", - "typeDescriptions": { - "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", - "typeString": "function (string memory) pure" - } - }, - "id": 6703, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4563:37:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 6704, - "nodeType": "ExpressionStatement", - "src": "4563:37:28" - } - ] - }, - "errorName": "", - "id": 6706, - "nodeType": "TryCatchClause", - "src": "4542:70:28" - } - ], - "externalCall": { - "arguments": [], - "expression": { - "argumentTypes": [], - "expression": { - "arguments": [ - { - "id": 6690, - "name": "_newImplementation", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6559, - "src": "4421:18:28", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 6689, - "name": "Upgradeable", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 23590, - "src": "4409:11:28", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Upgradeable_$23590_$", - "typeString": "type(contract Upgradeable)" - } - }, - "id": 6691, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "typeConversion", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4409:31:28", - "tryCall": false, - "typeDescriptions": { - "typeIdentifier": "t_contract$_Upgradeable_$23590", - "typeString": "contract Upgradeable" - } - }, - "id": 6692, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberLocation": "4441:12:28", - "memberName": "isUpgradable", - "nodeType": "MemberAccess", - "referencedDeclaration": 23569, - "src": "4409:44:28", - "typeDescriptions": { - "typeIdentifier": "t_function_external_view$__$returns$_t_bool_$", - "typeString": "function () view external returns (bool)" - } - }, - "id": 6693, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "nameLocations": [], - "names": [], - "nodeType": "FunctionCall", - "src": "4409:46:28", - "tryCall": true, - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "id": 6707, - "nodeType": "TryStatement", - "src": "4405:207:28" - } - ] - }, - "documentation": { - "id": 6557, - "nodeType": "StructuredDocumentation", - "src": "1879:280:28", - "text": "Upgrades the `implementation` address.\n @param _newImplementation New implementation address.\n @param _initData Raw data with which new implementation will be initialized.\n @return Returns whether new implementation would be further upgradable, or not." - }, - "functionSelector": "6fbc15e9", - "id": 6709, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "upgradeTo", - "nameLocation": "2174:9:28", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6562, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6559, - "mutability": "mutable", - "name": "_newImplementation", - "nameLocation": "2192:18:28", - "nodeType": "VariableDeclaration", - "scope": 6709, - "src": "2184:26:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 6558, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "2184:7:28", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "visibility": "internal" - }, - { - "constant": false, - "id": 6561, - "mutability": "mutable", - "name": "_initData", - "nameLocation": "2225:9:28", - "nodeType": "VariableDeclaration", - "scope": 6709, - "src": "2212:22:28", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_bytes_memory_ptr", - "typeString": "bytes" - }, - "typeName": { - "id": 6560, - "name": "bytes", - "nodeType": "ElementaryTypeName", - "src": "2212:5:28", - "typeDescriptions": { - "typeIdentifier": "t_bytes_storage_ptr", - "typeString": "bytes" - } - }, - "visibility": "internal" - } - ], - "src": "2183:52:28" - }, - "returnParameters": { - "id": 6565, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6564, - "mutability": "mutable", - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "VariableDeclaration", - "scope": 6709, - "src": "2261:4:28", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - }, - "typeName": { - "id": 6563, - "name": "bool", - "nodeType": "ElementaryTypeName", - "src": "2261:4:28", - "typeDescriptions": { - "typeIdentifier": "t_bool", - "typeString": "bool" - } - }, - "visibility": "internal" - } - ], - "src": "2260:6:28" - }, - "scope": 6719, - "src": "2165:2454:28", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "public" - }, - { - "body": { - "id": 6717, - "nodeType": "Block", - "src": "4826:213:28", - "statements": [ - { - "AST": { - "nodeType": "YulBlock", - "src": "4846:186:28", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "4941:80:28", - "value": { - "kind": "number", - "nodeType": "YulLiteral", - "src": "4955:66:28", - "type": "", - "value": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - }, - "variableNames": [ - { - "name": "_slot.slot", - "nodeType": "YulIdentifier", - "src": "4941:10:28" - } - ] - } - ] - }, - "evmVersion": "london", - "externalReferences": [ - { - "declaration": 6714, - "isOffset": false, - "isSlot": true, - "src": "4941:10:28", - "suffix": "slot", - "valueSize": 1 - } - ], - "id": 6716, - "nodeType": "InlineAssembly", - "src": "4837:195:28" - } - ] - }, - "documentation": { - "id": 6710, - "nodeType": "StructuredDocumentation", - "src": "4627:109:28", - "text": "@dev Complying with EIP-1967, retrieves storage struct containing proxy's current implementation address." - }, - "id": 6718, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "__proxySlot", - "nameLocation": "4751:11:28", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 6711, - "nodeType": "ParameterList", - "parameters": [], - "src": "4762:2:28" - }, - "returnParameters": { - "id": 6715, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 6714, - "mutability": "mutable", - "name": "_slot", - "nameLocation": "4819:5:28", - "nodeType": "VariableDeclaration", - "scope": 6718, - "src": "4787:37:28", - "stateVariable": false, - "storageLocation": "storage", - "typeDescriptions": { - "typeIdentifier": "t_struct$_ProxiableSlot_$23442_storage_ptr", - "typeString": "struct Proxiable.ProxiableSlot" - }, - "typeName": { - "id": 6713, - "nodeType": "UserDefinedTypeName", - "pathNode": { - "id": 6712, - "name": "Proxiable.ProxiableSlot", - "nameLocations": [ - "4787:9:28", - "4797:13:28" - ], - "nodeType": "IdentifierPath", - "referencedDeclaration": 23442, - "src": "4787:23:28" - }, - "referencedDeclaration": 23442, - "src": "4787:23:28", - "typeDescriptions": { - "typeIdentifier": "t_struct$_ProxiableSlot_$23442_storage_ptr", - "typeString": "struct Proxiable.ProxiableSlot" - } - }, - "visibility": "internal" - } - ], - "src": "4786:39:28" - }, - "scope": 6719, - "src": "4742:297:28", - "stateMutability": "pure", - "virtual": false, - "visibility": "private" - } - ], - "scope": 6720, - "src": "244:4800:28", - "usedErrors": [] - } - ], - "src": "35:5011:28" - }, - "compiler": { - "name": "solc", - "version": "0.8.17+commit.8df45f5f.Emscripten.clang" - }, - "networks": {}, - "schemaVersion": "3.4.13", - "updatedAt": "2023-04-25T18:38:54.596Z", - "networkType": "ethereum", - "devdoc": { - "author": "The Witnet Foundation.", - "kind": "dev", - "methods": { - "upgradeTo(address,bytes)": { - "params": { - "_initData": "Raw data with which new implementation will be initialized.", - "_newImplementation": "New implementation address." - }, - "returns": { - "_0": "Returns whether new implementation would be further upgradable, or not." - } - } - }, - "title": "WitnetProxy: upgradable delegate-proxy contract. ", - "version": 1 - }, - "userdoc": { - "events": { - "Upgraded(address)": { - "notice": "Event emitted every time the implementation gets updated." - } - }, - "kind": "user", - "methods": { - "constructor": { - "notice": "Constructor with no params as to ease eventual support of Singleton pattern (i.e. ERC-2470)." - }, - "implementation()": { - "notice": "Returns proxy's current implementation address." - }, - "upgradeTo(address,bytes)": { - "notice": "Upgrades the `implementation` address." - } - }, - "version": 1 - } -} \ No newline at end of file diff --git a/migrations/abis/WitnetRandomness.json b/migrations/abis/WitnetRandomness.json new file mode 100644 index 000000000..622be3e19 --- /dev/null +++ b/migrations/abis/WitnetRandomness.json @@ -0,0 +1,649 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "contract WitnetRequestBoard", + "name": "_wrb", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "uint256", + "name": "read", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "UnexpectedMajorType", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "by", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "self", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "clone", + "type": "address" + } + ], + "name": "Cloned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "prevBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "witnetQueryId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "witnetRequestHash", + "type": "bytes32" + } + ], + "name": "Randomized", + "type": "event" + }, + { + "inputs": [], + "name": "cloned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRandomizeBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "self", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "witnetRandomnessRequest", + "outputs": [ + { + "internalType": "contract WitnetRequest", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clone", + "outputs": [ + { + "internalType": "contract WitnetRandomness", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + } + ], + "name": "cloneDeterministic", + "outputs": [ + { + "internalType": "contract WitnetRandomness", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_initData", + "type": "bytes" + } + ], + "name": "initializeClone", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "_radonSLA", + "type": "tuple" + } + ], + "name": "settleWitnetRandomnessSLA", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "estimateRandomizeFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "getRandomizeData", + "outputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_prevBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_nextBlock", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "getRandomnessAfter", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "getRandomnessNextBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "getRandomnessPrevBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "isRandomized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_range", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "random", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_range", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_seed", + "type": "bytes32" + } + ], + "name": "random", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "randomize", + "outputs": [ + { + "internalType": "uint256", + "name": "_usedFunds", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_block", + "type": "uint256" + } + ], + "name": "upgradeRandomizeFee", + "outputs": [ + { + "internalType": "uint256", + "name": "_usedFunds", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "witnet", + "outputs": [ + { + "internalType": "contract WitnetRequestBoard", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "witnetRandomnessSLA", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/migrations/abis/WitnetRequest.json b/migrations/abis/WitnetRequest.json new file mode 100644 index 000000000..153fa6057 --- /dev/null +++ b/migrations/abis/WitnetRequest.json @@ -0,0 +1,400 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "request", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "WitnetRequestBuilt", + "type": "event" + }, + { + "inputs": [], + "name": "aggregator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "buildRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "class", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "contract WitnetRequestFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonAggregator", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getRadonRetrievalByIndex", + "outputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "argsCount", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "method", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "resultDataType", + "type": "uint8" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "body", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "headers", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonRetrieval", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonRetrievalsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonTally", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "parameterized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract WitnetBytecodes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resultDataMaxSize", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resultDataType", + "outputs": [ + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "retrievals", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tally", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "verifyRadonRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "template", + "outputs": [ + { + "internalType": "contract WitnetRequestTemplate", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "args", + "outputs": [ + { + "internalType": "string[][]", + "name": "", + "type": "string[][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bytecode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "radHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ] \ No newline at end of file diff --git a/migrations/abis/WitnetRequestBoard.json b/migrations/abis/WitnetRequestBoard.json new file mode 100644 index 000000000..e01c5649f --- /dev/null +++ b/migrations/abis/WitnetRequestBoard.json @@ -0,0 +1,1088 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "queryId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "DeletedQuery", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "queryId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "PostedRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "queryId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "PostedResult", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "_result", + "type": "tuple" + } + ], + "name": "asBytes32", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "_result", + "type": "tuple" + } + ], + "name": "asErrorMessage", + "outputs": [ + { + "internalType": "enum Witnet.ResultErrorCodes", + "name": "", + "type": "uint8" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "_result", + "type": "tuple" + } + ], + "name": "asUint64", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "checkResultError", + "outputs": [ + { + "components": [ + { + "internalType": "enum Witnet.ResultErrorCodes", + "name": "code", + "type": "uint8" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "internalType": "struct Witnet.ResultError", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "checkResultStatus", + "outputs": [ + { + "internalType": "enum Witnet.ResultStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "deleteQuery", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "reporter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "cborBytes", + "type": "bytes" + } + ], + "internalType": "struct Witnet.Response", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "estimateReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextQueryId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "getQueryData", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "gasprice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "internalType": "struct Witnet.Request", + "name": "request", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "reporter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "cborBytes", + "type": "bytes" + } + ], + "internalType": "struct Witnet.Response", + "name": "response", + "type": "tuple" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "internalType": "struct Witnet.Query", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "getQueryStatus", + "outputs": [ + { + "internalType": "enum Witnet.QueryStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "_result", + "type": "tuple" + } + ], + "name": "isOk", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + } + ], + "name": "postRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IWitnetRequest", + "name": "addr", + "type": "address" + } + ], + "name": "postRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "numWitnesses", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minConsensusPercentage", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "witnessCollateral", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minerCommitRevealFee", + "type": "uint256" + } + ], + "internalType": "struct WitnetV2.RadonSLA", + "name": "slaParams", + "type": "tuple" + } + ], + "name": "postRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readRequest", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "slaHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "gasprice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "internalType": "struct Witnet.Request", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readRequestBytecode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readRequestGasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readRequestReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readResponse", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "reporter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "drTxHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "cborBytes", + "type": "bytes" + } + ], + "internalType": "struct Witnet.Response", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readResponseDrTxHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readResponseReporter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readResponseResult", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "readResponseTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_cborBytes", + "type": "bytes" + } + ], + "name": "resultFromCborBytes", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "cursor", + "type": "uint256" + } + ], + "internalType": "struct WitnetBuffer.Buffer", + "name": "buffer", + "type": "tuple" + }, + { + "internalType": "uint8", + "name": "initialByte", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "majorType", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "additionalInformation", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "len", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "tag", + "type": "uint64" + } + ], + "internalType": "struct WitnetCBOR.CBOR", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct Witnet.Result", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_queryId", + "type": "uint256" + } + ], + "name": "upgradeReward", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "class", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "contract WitnetRequestFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract WitnetBytecodes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/migrations/abis/WitnetRequestFactory.json b/migrations/abis/WitnetRequestFactory.json new file mode 100644 index 000000000..c603b787f --- /dev/null +++ b/migrations/abis/WitnetRequestFactory.json @@ -0,0 +1,81 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "parameterized", + "type": "bool" + } + ], + "name": "WitnetRequestTemplateBuilt", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "sourcesIds", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "aggregatorId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "tallyId", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "resultDataMaxSize", + "type": "uint16" + } + ], + "name": "buildRequestTemplate", + "outputs": [ + { + "internalType": "address", + "name": "template", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "class", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract WitnetBytecodes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/migrations/abis/WitnetRequestTemplate.json b/migrations/abis/WitnetRequestTemplate.json new file mode 100644 index 000000000..45f545f1a --- /dev/null +++ b/migrations/abis/WitnetRequestTemplate.json @@ -0,0 +1,348 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "request", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "radHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "WitnetRequestBuilt", + "type": "event" + }, + { + "inputs": [], + "name": "class", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "contract WitnetRequestFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract WitnetBytecodes", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "aggregator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "parameterized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resultDataMaxSize", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resultDataType", + "outputs": [ + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "retrievals", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tally", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonAggregator", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getRadonRetrievalByIndex", + "outputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "argsCount", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.DataRequestMethods", + "name": "method", + "type": "uint8" + }, + { + "internalType": "enum WitnetV2.RadonDataTypes", + "name": "resultDataType", + "type": "uint8" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "body", + "type": "string" + }, + { + "internalType": "string[2][]", + "name": "headers", + "type": "string[2][]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonRetrieval", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonRetrievalsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRadonTally", + "outputs": [ + { + "components": [ + { + "internalType": "enum WitnetV2.RadonReducerOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "enum WitnetV2.RadonFilterOpcodes", + "name": "opcode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "args", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonFilter[]", + "name": "filters", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "script", + "type": "bytes" + } + ], + "internalType": "struct WitnetV2.RadonReducer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "buildRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[][]", + "name": "args", + "type": "string[][]" + } + ], + "name": "verifyRadonRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] \ No newline at end of file diff --git a/migrations/scripts/1_Create2Factory.js b/migrations/scripts/1_Create2Factory.js deleted file mode 100644 index 461307ab9..000000000 --- a/migrations/scripts/1_Create2Factory.js +++ /dev/null @@ -1,59 +0,0 @@ -const fs = require("fs") - -const addresses = require("../witnet.addresses") -const utils = require("../../scripts/utils") - -const Create2Factory = artifacts.require("Create2Factory") - -module.exports = async function (deployer, network, [, from,,,,, master]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - let factory - if (utils.isNullAddress(addresses[ecosystem][network]?.Create2Factory)) { - await deployer.deploy(Create2Factory, { from: master }) - factory = await Create2Factory.deployed() - addresses[ecosystem][network].Create2Factory = factory.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - factory = await Create2Factory.at(addresses[ecosystem][network].Create2Factory) - Create2Factory.address = factory.address - utils.traceHeader("Skipping 'Create2Factory'") - console.info(" > Contract address:", factory.address) - console.info() - } - - // Settle WitnetProxy bytecode and source code as to guarantee - // salted addresses remain as expected no matter if the solc version - // is changed in migrations/witnet.settings.js - utils.traceHeader("Defrosting 'WitnetProxy' artifact") - fs.writeFileSync( - `build/${ecosystem}/contracts/WitnetProxy.json`, - fs.readFileSync("migrations/abis/WitnetProxy.json"), - { encoding: "utf8", flag: "w" } - ) - const WitnetProxy = artifacts.require("WitnetProxy") - const metadata = JSON.parse(WitnetProxy.metadata) - console.info(" ", "> compiler: ", metadata.compiler.version) - console.info(" ", "> compilation target:", metadata.settings.compilationTarget) - console.info(" ", "> evmVersion: ", metadata.settings.evmVersion) - console.info(" ", "> optimizer: ", JSON.stringify(metadata.settings.optimizer)) - - if (addresses[ecosystem][network]?.WitnetProxy === "") { - await deployer.deploy(WitnetProxy, { from }) - addresses[ecosystem][network].WitnetProxy = WitnetProxy.address - } else { - if (addresses[ecosystem][network]?.WitnetProxy) { - WitnetProxy.address = addresses[ecosystem][network]?.WitnetProxy - } - } - if (!isDryRun) { - utils.saveAddresses(addresses) - } -} diff --git a/migrations/scripts/1_deployer.js b/migrations/scripts/1_deployer.js new file mode 100644 index 000000000..a3382c969 --- /dev/null +++ b/migrations/scripts/1_deployer.js @@ -0,0 +1,30 @@ +const addresses = require("../witnet.addresses") +const utils = require("../../scripts/utils") + +const WitnetDeployer = artifacts.require("WitnetDeployer") + +module.exports = async function (deployer, network, [, from,, master]) { + const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" + const ecosystem = utils.getRealmNetworkFromArgs()[0] + network = network.split("-")[0] + + if (!addresses[ecosystem]) addresses[ecosystem] = {} + if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} + + let factory + if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetDeployer)) { + await deployer.deploy(WitnetDeployer, { from: master }) + factory = await WitnetDeployer.deployed() + addresses[ecosystem][network].WitnetDeployer = factory.address + } else { + factory = await WitnetDeployer.at(addresses[ecosystem][network].WitnetDeployer) + WitnetDeployer.address = factory.address + utils.traceHeader("Skipped 'WitnetDeployer'") + console.info(" > Contract address:", factory.address) + console.info() + } + + if (!isDryRun) { + utils.saveAddresses(addresses) + } +} diff --git a/migrations/scripts/2_WitnetLibs.js b/migrations/scripts/2_WitnetLibs.js deleted file mode 100644 index 657a3d09d..000000000 --- a/migrations/scripts/2_WitnetLibs.js +++ /dev/null @@ -1,44 +0,0 @@ -const utils = require("../../scripts/utils") - -const WitnetErrorsLib = artifacts.require("WitnetErrorsLib") -const WitnetEncodingLib = artifacts.require("WitnetEncodingLib") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - const addresses = require("../witnet.addresses") - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - let lib - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetErrorsLib)) { - await deployer.deploy(WitnetErrorsLib, { from }) - lib = await WitnetErrorsLib.deployed() - addresses[ecosystem][network].WitnetErrorsLib = lib.address - } else { - lib = await WitnetErrorsLib.at(addresses[ecosystem][network]?.WitnetErrorsLib) - WitnetErrorsLib.address = lib.address - utils.traceHeader("Skipping 'WitnetErrorsLib'") - console.info(" ", "> library address:", lib.address) - console.info() - } - if (!isDryRun) { - utils.saveAddresses(addresses) - } - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetEncodingLib)) { - await deployer.deploy(WitnetEncodingLib, { from }) - lib = await WitnetEncodingLib.deployed() - addresses[ecosystem][network].WitnetEncodingLib = lib.address - } else { - lib = await WitnetEncodingLib.at(addresses[ecosystem][network]?.WitnetEncodingLib) - WitnetEncodingLib.address = lib.address - utils.traceHeader("Skipping 'WitnetEncodingLib'") - console.info(" ", "> library address:", lib.address) - console.info() - } - if (!isDryRun) { - utils.saveAddresses(addresses) - } -} diff --git a/migrations/scripts/2_libs.js b/migrations/scripts/2_libs.js new file mode 100644 index 000000000..451663e57 --- /dev/null +++ b/migrations/scripts/2_libs.js @@ -0,0 +1,57 @@ +const { merge } = require("lodash") + +const settings = require("../witnet.settings") +const utils = require("../../scripts/utils") + +const WitnetDeployer = artifacts.require("WitnetDeployer") + +module.exports = async function (_, network, [, from]) { + const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" + const ecosystem = utils.getRealmNetworkFromArgs()[0] + network = network.split("-")[0] + + const addresses = require("../witnet.addresses") + if (!addresses[ecosystem]) addresses[ecosystem] = {} + if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} + + const targets = merge( + settings.artifacts.default, + settings.artifacts[ecosystem], + settings.artifacts[network] + ) + const libs = [ + targets.WitnetErrorsLib, + targets.WitnetEncodingLib, + targets.WitnetPriceFeedsLib, + ] + + const deployer = await WitnetDeployer.deployed() + for (index in libs) { + const key = libs[index] + const artifact = artifacts.require(key) + if (utils.isNullAddress(addresses[ecosystem][network][key])) { + utils.traceHeader(`Deploying '${key}'...`) + const libInitCode = artifact.toJSON().bytecode + const libAddr = await deployer.determineAddr.call(libInitCode, "0x0", { from }) + console.info(" ", "> account: ", from) + console.info(" ", "> balance: ", web3.utils.fromWei(await web3.eth.getBalance(from), "ether"), "ETH") + const tx = await deployer.deploy(libInitCode, "0x0", { from }) + utils.traceTx(tx) + if ((await web3.eth.getCode(libAddr)).length > 3) { + addresses[ecosystem][network][key] = libAddr + } else { + console.info(`Error: Library was not deployed on expected address: ${libAddr}`) + process.exit(1) + } + } else { + utils.traceHeader(`Skipped '${key}'`) + } + artifact.address = addresses[ecosystem][network][key] + console.info(" ", "> library address: ", artifact.address) + console.info(" ", "> library codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(artifact.address))) + console.info() + if (!isDryRun) { + utils.saveAddresses(addresses) + } + } +} diff --git a/migrations/scripts/3_WitnetBytecodes.js b/migrations/scripts/3_WitnetBytecodes.js deleted file mode 100644 index dccaff2a2..000000000 --- a/migrations/scripts/3_WitnetBytecodes.js +++ /dev/null @@ -1,127 +0,0 @@ -const ethUtils = require("ethereumjs-util") -const { merge } = require("lodash") - -const addresses = require("../witnet.addresses") -const settings = require("../witnet.settings") -const singletons = require("../witnet.salts") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const Create2Factory = artifacts.require("Create2Factory") -const WitnetProxy = artifacts.require("WitnetProxy") -const WitnetBytecodes = artifacts.require("WitnetBytecodes") -const WitnetEncodingLib = artifacts.require("WitnetEncodingLib") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - const artifactNames = merge(settings.artifacts.default, settings.artifacts[ecosystem], settings.artifacts[network]) - const WitnetBytecodesImplementation = artifacts.require(artifactNames.WitnetBytecodes) - - let proxy - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetBytecodes)) { - const factory = await Create2Factory.deployed() - if ( - factory && !utils.isNullAddress(factory.address) && - singletons?.WitnetBytecodes - ) { - // Deploy the proxy via a singleton factory and a salt... - const bytecode = WitnetProxy.toJSON().bytecode - const salt = singletons.WitnetBytecodes?.salt - ? "0x" + ethUtils.setLengthLeft( - ethUtils.toBuffer( - singletons.WitnetBytecodes.salt - ), 32 - ).toString("hex") - : "0x0" - - const proxyAddr = await factory.determineAddr.call(bytecode, salt, { from }) - if ((await web3.eth.getCode(proxyAddr)).length <= 3) { - // deploy instance only if not found in current network: - utils.traceHeader("Singleton inception of 'WitnetBytecodes':") - const balance = await web3.eth.getBalance(from) - const gas = singletons.WitnetBytecodes.gas - const tx = await factory.deploy(bytecode, salt, { from, gas }) - utils.traceTx( - tx.receipt, - web3.utils.fromWei((balance - await web3.eth.getBalance(from)).toString()) - ) - } else { - utils.traceHeader("Singleton 'WitnetBytecodes':") - } - console.info(" ", "> proxy address: ", proxyAddr) - console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(proxyAddr))) - console.info(" ", "> proxy inception salt:", salt) - proxy = await WitnetProxy.at(proxyAddr) - } else { - // Deploy no singleton proxy ... - proxy = await WitnetProxy.new({ from }) - } - addresses[ecosystem][network].WitnetBytecodes = proxy.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - proxy = await WitnetProxy.at(addresses[ecosystem][network].WitnetBytecodes) - console.info(` Skipped: 'WitnetBytecodes' deployed at ${proxy.address}`) - } - WitnetBytecodes.address = proxy.address - - let bytecodes - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetBytecodesImplementation)) { - await deployer.link(WitnetEncodingLib, [WitnetBytecodesImplementation]) - await deployer.deploy( - WitnetBytecodesImplementation, - /* _isUpgradeable */ true, - /* _versionTag */ utils.fromAscii(version), - { from } - ) - bytecodes = await WitnetBytecodesImplementation.deployed() - addresses[ecosystem][network].WitnetBytecodesImplementation = bytecodes.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - bytecodes = await WitnetBytecodesImplementation.at(addresses[ecosystem][network].WitnetBytecodesImplementation) - console.info(` Skipped: '${WitnetBytecodesImplementation.contractName}' deployed at ${bytecodes.address}`) - console.info() - WitnetBytecodesImplementation.address = bytecodes.address - await deployer.link(WitnetEncodingLib, WitnetBytecodesImplementation) - } - - const implementation = await proxy.implementation.call({ from }) - if (implementation.toLowerCase() !== bytecodes.address.toLowerCase()) { - const header = `Upgrading 'WitnetBytecodes' at ${proxy.address}...` - console.info() - console.info(" ", header) - console.info(" ", "-".repeat(header.length)) - console.info() - console.info(" > old implementation:", implementation) - console.info(" > new implementation:", bytecodes.address, `(v${await bytecodes.version.call({ from })})`) - if ( - isDryRun || - ["y", "yes"].includes((await utils.prompt(" > Upgrade the proxy ? [y/N] ")).toLowerCase().trim()) - ) { - try { - const tx = await proxy.upgradeTo(bytecodes.address, "0x", { from }) - console.info(" => transaction hash :", tx.receipt.transactionHash) - console.info(" => transaction gas :", tx.receipt.gasUsed) - console.info(" > Done.") - } catch (ex) { - console.info(" !! Cannot upgrade the proxy:") - console.info(ex) - } - } else { - console.info(" > Not upgraded.") - } - } -} diff --git a/migrations/scripts/3_core.js b/migrations/scripts/3_core.js new file mode 100644 index 000000000..cf999f89b --- /dev/null +++ b/migrations/scripts/3_core.js @@ -0,0 +1,164 @@ +const ethUtils = require("ethereumjs-util") +const { merge } = require("lodash") + +const addresses = require("../witnet.addresses") +const settings = require("../witnet.settings") +const utils = require("../../scripts/utils") +const version = `${ + require("../../package").version +}-${ + require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) +}` + +const WitnetDeployer = artifacts.require("WitnetDeployer") + +module.exports = async function (_, network, [, from]) { + const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" + const ecosystem = utils.getRealmNetworkFromArgs()[0] + network = network.split("-")[0] + + if (!addresses[ecosystem]) addresses[ecosystem] = {} + if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} + + const specs = merge( + settings.specs.default, + settings.specs[ecosystem], + settings.specs[network], + ) + const targets = merge( + settings.artifacts.default, + settings.artifacts[ecosystem], + settings.artifacts[network] + ) + + // Deploy/upgrade WitnetBytecodes target implementation, if required + { + await deploy({ + from, + ecosystem, + network, + targets, + key: targets.WitnetBytecodes, + libs: specs.WitnetBytecodes.libs, + immutables: specs.WitnetBytecodes.immutables, + intrinsics: { + types: ["bool", "bytes32"], + values: [ + /* _upgradable */ true, + /* _versionTag */ utils.fromAscii(version), + ], + }, + }) + if (!isDryRun) { + utils.saveAddresses(addresses) + } + } + // Deploy/upgrade WitnetRequestFactory target implementation, if required + { + await deploy({ + from, + ecosystem, + network, + targets, + key: targets.WitnetRequestFactory, + libs: specs.WitnetRequestFactory.libs, + immutables: specs.WitnetRequestFactory.immutables, + intrinsics: { + types: ["address", "address", "bool", "bytes32"], + values: [ + /* _witnet */ await determineProxyAddr(from, specs.WitnetRequestBoard?.vanity || 3), + /* _registry */ await determineProxyAddr(from, specs.WitnetBytecodes?.vanity || 1), + /* _upgradable */ true, + /* _versionTag */ utils.fromAscii(version), + ], + }, + }) + if (!isDryRun) { + utils.saveAddresses(addresses) + } + } + // Deploy/upgrade WitnetRequestBoard target implementation, if required + { + await deploy({ + from, + ecosystem, + network, + targets, + key: targets.WitnetRequestBoard, + libs: specs.WitnetRequestBoard.libs, + immutables: specs.WitnetRequestBoard.immutables, + intrinsics: { + types: ["address", "address", "bool", "bytes32"], + values: [ + /* _factory */ await determineProxyAddr(from, specs.WitnetRequestFactory?.vanity || 2), + /* _registry */ await determineProxyAddr(from, specs.WitnetBytecodes?.vanity || 1), + /* _upgradable */ true, + /* _versionTag */ utils.fromAscii(version), + ], + }, + }) + if (!isDryRun) { + utils.saveAddresses(addresses) + } + } +} + +async function deploy (specs) { + const { from, ecosystem, network, key, libs, intrinsics, immutables, targets } = specs + const contract = artifacts.require(key) + if (utils.isNullAddress(addresses[ecosystem][network][key])) { + utils.traceHeader(`Deploying '${key}'...`) + console.info(" ", "> account: ", from) + console.info(" ", "> balance: ", web3.utils.fromWei(await web3.eth.getBalance(from), "ether"), "ETH") + const deployer = await WitnetDeployer.deployed() + let { types, values } = intrinsics + if (immutables?.types) types = [...types, ...immutables.types] + if (immutables?.values) values = [...values, ...immutables.values] + const constructorArgs = web3.eth.abi.encodeParameters(types, values) + if (constructorArgs.length > 2) { + console.info(" ", "> constructor types:", types) + console.info(" ", "> constructor args: ", constructorArgs.slice(2)) + } + const coreBytecode = link(contract.toJSON().bytecode, libs, targets) + if (coreBytecode.indexOf("__") > -1) { + console.info(bytecode) + console.info("Error: Cannot deploy due to some missing libs") + process.exit(1) + } + const coreInitCode = coreBytecode + constructorArgs.slice(2) + const coreAddr = await deployer.determineAddr.call(coreInitCode, "0x0", { from }) + const tx = await deployer.deploy(coreInitCode, "0x0", { from }) + utils.traceTx(tx) + if ((await web3.eth.getCode(coreAddr)).length > 3) { + addresses[ecosystem][network][key] = coreAddr + } else { + console.info(`Error: Contract was not deployed on expected address: ${coreAddr}`) + process.exit(1) + } + } else { + utils.traceHeader(`Skipped '${key}'`) + } + contract.address = addresses[ecosystem][network][key] + console.info(" ", "> contract address: ", contract.address) + console.info(" ", "> contract codehash:", web3.utils.soliditySha3(await web3.eth.getCode(contract.address))) + console.info() + return contract +} + +async function determineProxyAddr (from, nonce) { + const salt = nonce ? "0x" + ethUtils.setLengthLeft(ethUtils.toBuffer(nonce), 32).toString("hex") : "0x0" + const deployer = await WitnetDeployer.deployed() + return await deployer.determineProxyAddr.call(salt, { from }) +} + +function link (bytecode, libs, targets) { + if (libs && Array.isArray(libs) && libs.length > 0) { + for (index in libs) { + const key = targets[libs[index]] + const lib = artifacts.require(key) + bytecode = bytecode.replaceAll(`__${key}${"_".repeat(38 - key.length)}`, lib.address.slice(2)) + console.info(" ", `> linked library: ${key} => ${lib.address}`) + } + } + return bytecode +} diff --git a/migrations/scripts/4_WitnetRequestFactory.js b/migrations/scripts/4_WitnetRequestFactory.js deleted file mode 100644 index db5102a15..000000000 --- a/migrations/scripts/4_WitnetRequestFactory.js +++ /dev/null @@ -1,126 +0,0 @@ -const ethUtils = require("ethereumjs-util") -const { merge } = require("lodash") - -const addresses = require("../witnet.addresses") -const settings = require("../witnet.settings") -const singletons = require("../witnet.salts") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const Create2Factory = artifacts.require("Create2Factory") -const WitnetProxy = artifacts.require("WitnetProxy") - -const WitnetBytecodes = artifacts.require("WitnetBytecodes") -const WitnetRequestFactory = artifacts.require("WitnetRequestFactory") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - const artifactNames = merge(settings.artifacts.default, settings.artifacts[ecosystem], settings.artifacts[network]) - const WitnetRequestFactoryImplementation = artifacts.require(artifactNames.WitnetRequestFactory) - - let proxy - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRequestFactory)) { - const create2Factory = await Create2Factory.deployed() - if ( - create2Factory && !utils.isNullAddress(create2Factory.address) && - singletons?.WitnetRequestFactory - ) { - // Deploy the proxy via a singleton factory and a salt... - const bytecode = WitnetProxy.toJSON().bytecode - const salt = singletons.WitnetRequestFactory?.salt - ? "0x" + ethUtils.setLengthLeft( - ethUtils.toBuffer( - singletons.WitnetRequestFactory.salt - ), 32 - ).toString("hex") - : "0x0" - - const proxyAddr = await create2Factory.determineAddr.call(bytecode, salt, { from }) - if ((await web3.eth.getCode(proxyAddr)).length <= 3) { - // deploy instance only if not found in current network: - utils.traceHeader("Singleton inception of 'WitnetRequestFactory':") - const balance = await web3.eth.getBalance(from) - const gas = singletons.WitnetRequestFactory.gas - const tx = await create2Factory.deploy(bytecode, salt, { from, gas }) - utils.traceTx( - tx.receipt, - web3.utils.fromWei((balance - await web3.eth.getBalance(from)).toString()) - ) - } else { - utils.traceHeader("Singleton 'WitnetRequestFactory':") - } - console.info(" ", "> proxy address: ", proxyAddr) - console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(proxyAddr))) - console.info(" ", "> proxy inception salt:", salt) - proxy = await WitnetProxy.at(proxyAddr) - } else { - // Deploy no singleton proxy ... - proxy = await WitnetProxy.new({ from }) - } - addresses[ecosystem][network].WitnetRequestFactory = proxy.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - proxy = await WitnetProxy.at(addresses[ecosystem][network].WitnetRequestFactory) - console.info(` Skipped: 'WitnetRequestFactory' deployed at ${proxy.address}`) - } - WitnetRequestFactory.address = proxy.address - - let factory - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRequestFactoryImplementation)) { - await deployer.deploy( - WitnetRequestFactoryImplementation, - addresses[ecosystem][network].WitnetBytecodes || WitnetBytecodes.address, - /* _isUpgradeable */ true, - /* _versionTag */ utils.fromAscii(version), - { from } - ) - factory = await WitnetRequestFactoryImplementation.deployed() - addresses[ecosystem][network].WitnetRequestFactoryImplementation = factory.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - factory = await WitnetRequestFactoryImplementation.at(addresses[ecosystem][network].WitnetRequestFactoryImplementation) - console.info(` Skipped: '${WitnetRequestFactoryImplementation.contractName}' deployed at ${factory.address}`) - WitnetRequestFactoryImplementation.address = factory.address - } - - const implementation = await proxy.implementation.call({ from }) - if (implementation.toLowerCase() !== factory.address.toLowerCase()) { - const header = `Upgrading 'WitnetRequestFactory' at ${proxy.address}...` - console.info() - console.info(" ", header) - console.info(" ", "-".repeat(header.length)) - console.info() - console.info(" > old implementation:", implementation) - console.info(" > new implementation:", factory.address, `(v${await factory.version.call({ from })})`) - if ( - isDryRun || - ["y", "yes"].includes((await utils.prompt(" > Upgrade the proxy ? [y/N] ")).toLowerCase().trim()) - ) { - try { - const tx = await proxy.upgradeTo(factory.address, "0x", { from }) - console.info(" => transaction hash :", tx.receipt.transactionHash) - console.info(" => transaction gas :", tx.receipt.gasUsed) - console.info(" > Done.") - } catch (ex) { - console.info(" !! Cannot upgrade the proxy:") - console.info(ex) - } - } else { - console.info(" > Not upgraded.") - } - } -} diff --git a/migrations/scripts/4_proxies.js b/migrations/scripts/4_proxies.js new file mode 100644 index 000000000..08f104d1a --- /dev/null +++ b/migrations/scripts/4_proxies.js @@ -0,0 +1,149 @@ +const ethUtils = require("ethereumjs-util") +const { merge } = require("lodash") + +const addresses = require("../witnet.addresses") +const settings = require("../witnet.settings") +const utils = require("../../scripts/utils") + +const WitnetDeployer = artifacts.require("WitnetDeployer") +const WitnetProxy = artifacts.require("WitnetProxy") + +module.exports = async function (_, network, [, from, reporter]) { + const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" + const ecosystem = utils.getRealmNetworkFromArgs()[0] + network = network.split("-")[0] + + if (!addresses[ecosystem]) addresses[ecosystem] = {} + if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} + + const targets = merge( + settings.artifacts.default, + settings.artifacts[ecosystem], + settings.artifacts[network] + ) + const specs = merge( + settings.specs.default, + settings.specs[ecosystem], + settings.specs[network], + ) + const singletons = [ + "WitnetBytecodes", + "WitnetRequestFactory", + "WitnetRequestBoard", + ] + + specs.WitnetRequestBoard.mutables = merge({ + types: ["address[]"], + values: [[reporter]], + }, specs.WitnetRequestBoard.mutables + ) + + // Deploy/upgrade singleton proxies, if required + for (index in singletons) { + await deploy({ + from, + ecosystem, + network, + specs, + targets, + key: singletons[index], + }) + if (!isDryRun) { + utils.saveAddresses(addresses) + } + } +} + +async function deploy (target) { + const { from, ecosystem, network, key, specs, targets } = target + + const mutables = specs[key].mutables + const proxy = artifacts.require(key) + const proxy_salt = specs[key].vanity ? "0x" + ethUtils.setLengthLeft(ethUtils.toBuffer(specs[key].vanity), 32).toString("hex") : "0x0" + + if (utils.isNullAddress(addresses[ecosystem][network][key])) { + utils.traceHeader(`Deploying '${key}'...`) + console.info(" ", "> account: ", from) + console.info(" ", "> balance: ", web3.utils.fromWei(await web3.eth.getBalance(from), "ether"), "ETH") + const deployer = await WitnetDeployer.deployed() + const impl = await artifacts.require(targets[key]).deployed() + const proxyAddr = await deployer.determineProxyAddr.call(proxy_salt, { from }) + if ((await web3.eth.getCode(proxyAddr)).length < 3) { + const initdata = mutables ? web3.eth.abi.encodeParameters(mutables.types, mutables.values) : "0x" + if (initdata.length > 2) { + console.info(" ", "> initialize types: ", mutables.types) + console.info(" ", "> initialize params:", mutables.values) + } + const tx = await deployer.proxify(proxy_salt, impl.address, initdata, { from }) + utils.traceTx(tx) + // save/overwrite exportable abi file + utils.saveJsonAbi(key, proxy.abi) + } else { + try { + const oldImplAddr = await getProxyImplementation(from, proxyAddr) + const oldImpl = await artifacts.require(targets[key]).at(oldImplAddr) + const oldClass = await oldImpl.class.call({ from }) + const newClass = await impl.class.call({ from }) + if (oldClass !== newClass) { + console.info(`Error: proxy address already taken (\"${oldClass}\" != \"${newClass}\")`) + process.exit(1) + } else { + console.info(" ", `> recovered proxy address on class \"${oldClass}\" ;-)`) + } + } catch (ex) { + console.info("Error: cannot check proxy recoverability:", ex) + } + } + if ((await web3.eth.getCode(proxyAddr)).length > 3) { + addresses[ecosystem][network][key] = proxyAddr + } else { + console.info(`Error: Contract was not deployed on expected address: ${proxyAddr}`) + process.exit(1) + } + } else { + const oldAddr = await getProxyImplementation(from, addresses[ecosystem][network][key]) + const oldImpl = await artifacts.require(targets[key]).at(oldAddr) + const newImpl = await artifacts.require(targets[key]).deployed() + if (oldAddr !== newImpl.address) { + utils.traceHeader(`Upgrading '${key}'...`) + const oldVersion = await oldImpl.version.call({ from }) + const newVersion = await newImpl.version.call({ from }) + if ( + process.argv.length >= 3 && process.argv[2].includes("--upgrade-all") || ["y", "yes"].includes( + (await utils.prompt(` > From v${oldVersion} to v${newVersion} ? [y / N]`)).toLowerCase().trim() + ) + ) { + const initdata = mutables ? web3.eth.abi.encodeParameters(mutables.types, mutables.values) : "0x" + if (initdata.length > 2) { + console.info(" ", "> initialize types: ", mutables.types) + console.info(" ", "> initialize params:", mutables.values) + } + const tx = await upgradeProxyTo(from, proxy, newImpl.address, initdata) + utils.traceTx(tx) + // save/overwrite exportable abi file + utils.saveJsonAbi(key, proxy.abi) + } + } else { + utils.traceHeader(`Skipped '${key}'`) + } + } + proxy.address = addresses[ecosystem][network][key] + const impl = await artifacts.require(targets[key]).at(proxy.address) + console.info(" ", "> proxy address: ", impl.address) + console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(impl.address))) + console.info(" ", "> proxy operator: ", await impl.owner.call()) + console.info(" ", "> impl. address: ", await getProxyImplementation(from, proxy.address)) + console.info(" ", "> impl. version: ", await impl.version.call()) + console.info() + return proxy +} + +async function getProxyImplementation (from, proxyAddr) { + proxy = await WitnetProxy.at(proxyAddr) + return await proxy.implementation.call({ from }) +} + +async function upgradeProxyTo (from, proxy, implAddr, initData) { + proxy = await WitnetProxy.at(proxy.address) + return await proxy.upgradeTo(implAddr, initData, { from }) +} diff --git a/migrations/scripts/5_WitnetRequestBoard.js b/migrations/scripts/5_WitnetRequestBoard.js deleted file mode 100644 index 9f180baab..000000000 --- a/migrations/scripts/5_WitnetRequestBoard.js +++ /dev/null @@ -1,146 +0,0 @@ -const ethUtils = require("ethereumjs-util") -const { merge } = require("lodash") - -const addresses = require("../witnet.addresses") -const settings = require("../witnet.settings") -const singletons = require("../witnet.salts") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const Create2Factory = artifacts.require("Create2Factory") -const WitnetProxy = artifacts.require("WitnetProxy") - -const WitnetErrorsLib = artifacts.require("WitnetErrorsLib") -const WitnetRequestFactory = artifacts.require("WitnetRequestFactory") -const WitnetRequestBoard = artifacts.require("WitnetRequestBoard") - -module.exports = async function (deployer, network, [, from, reporter]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - const artifactsName = merge(settings.artifacts.default, settings.artifacts[ecosystem], settings.artifacts[network]) - const WitnetRequestBoardImplementation = artifacts.require(artifactsName.WitnetRequestBoard) - - let proxy - const factory = await Create2Factory.deployed() - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRequestBoard)) { - if ( - factory && !utils.isNullAddress(factory.address) && - singletons?.WitnetRequestBoard - ) { - // Deploy the proxy via a singleton factory and a salt... - const bytecode = WitnetProxy.toJSON().bytecode - const salt = singletons.WitnetRequestBoard?.salt - ? "0x" + ethUtils.setLengthLeft( - ethUtils.toBuffer( - singletons.WitnetRequestBoard.salt - ), 32 - ).toString("hex") - : "0x0" - - const proxyAddr = await factory.determineAddr.call(bytecode, salt, { from }) - if ((await web3.eth.getCode(proxyAddr)).length <= 3) { - // deploy instance only if not found in current network: - utils.traceHeader("Singleton inception of 'WitnetRequestBoard':") - const balance = await web3.eth.getBalance(from) - const gas = singletons.WitnetRequestBoard.gas - const tx = await factory.deploy(bytecode, salt, { from, gas }) - utils.traceTx( - tx.receipt, - web3.utils.fromWei((balance - await web3.eth.getBalance(from)).toString()) - ) - } else { - utils.traceHeader("Singleton 'WitnetRequestBoard':") - } - console.info(" ", "> proxy address: ", proxyAddr) - console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(proxyAddr))) - console.info(" ", "> proxy inception salt:", salt) - proxy = await WitnetProxy.at(proxyAddr) - } else { - // Deploy no singleton proxy ... - proxy = await WitnetProxy.new({ from }) - } - // update addresses file - addresses[ecosystem][network].WitnetRequestBoard = proxy.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - proxy = await WitnetProxy.at(addresses[ecosystem][network].WitnetRequestBoard) - console.info(` Skipped: 'WitnetRequestBoard' deployed at ${proxy.address}`) - } - WitnetRequestBoard.address = proxy.address - - let board - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRequestBoardImplementation)) { - await deployer.link(WitnetErrorsLib, WitnetRequestBoardImplementation) - await deployer.deploy( - WitnetRequestBoardImplementation, - WitnetRequestFactory.address, - /* _isUpgradeable */ true, - /* _versionTag */ utils.fromAscii(version), - ...( - // if defined, use network-specific constructor parameters: - settings.constructorParams[network]?.WitnetRequestBoard || - // otherwise, use ecosystem-specific parameters, if any: - settings.constructorParams[ecosystem]?.WitnetRequestBoard || - // or, default defined parameters for WRBs, if any: - settings.constructorParams?.default?.WitnetRequestBoard - ), - { from } - ) - board = await WitnetRequestBoardImplementation.deployed() - addresses[ecosystem][network].WitnetRequestBoardImplementation = board.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - board = await WitnetRequestBoardImplementation.at(addresses[ecosystem][network].WitnetRequestBoardImplementation) - console.info(` Skipped: '${WitnetRequestBoardImplementation.contractName}' deployed at ${board.address}`) - console.info() - WitnetRequestBoardImplementation.address = board.address - await deployer.link(WitnetErrorsLib, WitnetRequestBoardImplementation) - } - - const implementation = await proxy.implementation.call({ from }) - if (implementation.toLowerCase() !== board.address.toLowerCase()) { - const header = `Upgrading 'WitnetRequestBoard' at ${proxy.address}...` - console.info() - console.info(" ", header) - console.info(" ", "-".repeat(header.length)) - console.info() - console.info(" > old implementation:", implementation) - console.info(" > new implementation:", board.address, `(v${await board.version.call({ from })})`) - if ( - isDryRun || - ["y", "yes"].includes((await utils.prompt(" > Upgrade the proxy ? [y/N] ")).toLowerCase().trim()) - ) { - try { - const tx = await proxy.upgradeTo( - board.address, - web3.eth.abi.encodeParameter( - "address[]", - [reporter], - ), - { from } - ) - console.info(" => Transaction hash :", tx.receipt.transactionHash) - console.info(" => Transaction gas :", tx.receipt.gasUsed) - console.info(" > Done.") - } catch (ex) { - console.info(" !! Cannot upgrade the proxy:") - console.info(ex) - } - } else { - console.info(" > Not upgraded.") - } - } -} diff --git a/migrations/scripts/5_apps.js b/migrations/scripts/5_apps.js new file mode 100644 index 000000000..3080cc8ab --- /dev/null +++ b/migrations/scripts/5_apps.js @@ -0,0 +1,136 @@ +const ethUtils = require("ethereumjs-util") +const { merge } = require("lodash") + +const addresses = require("../witnet.addresses") +const settings = require("../witnet.settings") +const utils = require("../../scripts/utils") + +const WitnetDeployer = artifacts.require("WitnetDeployer") + +module.exports = async function (_, network, [,,, from]) { + const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" + const ecosystem = utils.getRealmNetworkFromArgs()[0] + network = network.split("-")[0] + + if (!addresses[ecosystem]) addresses[ecosystem] = {} + if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} + + const specs = merge( + settings.specs.default, + settings.specs[ecosystem], + settings.specs[network], + ) + const targets = merge( + settings.artifacts.default, + settings.artifacts[ecosystem], + settings.artifacts[network] + ) + + // Deploy the WitnetPriceFeeds oracle, if required + { + await deploy({ + from, + ecosystem, + network, + targets, + key: targets.WitnetPriceFeeds, + libs: specs.WitnetPriceFeeds.libs, + vanity: specs.WitnetPriceFeeds?.vanity || 0, + immutables: specs.WitnetPriceFeeds.immutables, + intrinsics: { + types: ["address", "address"], + values: [ + /* _operator */ from, + /* _wrb */ await determineProxyAddr(from, specs.WitnetRequestBoard?.vanity || 3), + ], + }, + }) + if (!isDryRun) utils.saveAddresses(addresses) + } + // Deploy the WitnetRandomness oracle, if required + { + await deploy({ + from, + ecosystem, + network, + targets, + key: targets.WitnetRandomness, + libs: specs.WitnetRandomness?.libs, + vanity: specs.WitnetRandomness?.vanity || 0, + immutables: specs.WitnetRandomness?.immutables, + intrinsics: { + types: ["address", "address"], + values: [ + /* _operator */ from, + /* _wrb */ await determineProxyAddr(from, specs.WitnetRequestBoard?.vanity || 3), + ], + }, + }) + if (!isDryRun) utils.saveAddresses(addresses) + } +} + +async function deploy (specs) { + const { from, ecosystem, network, key, libs, intrinsics, immutables, targets, vanity } = specs + const artifact = artifacts.require(key) + const salt = vanity ? "0x" + ethUtils.setLengthLeft(ethUtils.toBuffer(vanity), 32).toString("hex") : "0x0" + if (utils.isNullAddress(addresses[ecosystem][network][key])) { + utils.traceHeader(`Deploying '${key}'...`) + const deployer = await WitnetDeployer.deployed() + let { types, values } = intrinsics + if (immutables?.types) types = [...types, ...immutables.types] + if (immutables?.values) values = [...values, ...immutables.values] + const constructorArgs = web3.eth.abi.encodeParameters(types, values) + if (constructorArgs.length > 2) { + console.info(" ", "> constructor types:", types) + console.info(" ", "> constructor args: ", constructorArgs.slice(2)) + } + const coreBytecode = link(artifact.toJSON().bytecode, libs, targets) + if (coreBytecode.indexOf("__") > -1) { + console.info(bytecode) + console.info("Cannot deploy due to some missing libs") + process.exit(1) + } + const dappInitCode = coreBytecode + constructorArgs.slice(2) + const dappAddr = await deployer.determineAddr.call(dappInitCode, salt, { from }) + console.info(" ", "> account: ", from) + console.info(" ", "> balance: ", web3.utils.fromWei(await web3.eth.getBalance(from), "ether"), "ETH") + const tx = await deployer.deploy(dappInitCode, salt, { from }) + utils.traceTx(tx) + if ((await web3.eth.getCode(dappAddr)).length > 3) { + addresses[ecosystem][network][key] = dappAddr + // save/overwrite exportable abi file + utils.saveJsonAbi(key, artifact.abi) + } else { + console.info(`Contract was not deployed on expected address: ${dappAddr}`) + console.log(tx.receipt) + process.exit(1) + } + } else { + utils.traceHeader(`Skipped '${key}'`) + } + artifact.address = addresses[ecosystem][network][key] + console.info(" ", "> contract address: ", artifact.address) + console.info(" ", "> contract codehash:", web3.utils.soliditySha3(await web3.eth.getCode(artifact.address))) + console.info() + return artifact +} + +async function determineProxyAddr (from, nonce) { + const salt = nonce ? "0x" + ethUtils.setLengthLeft(ethUtils.toBuffer(nonce), 32).toString("hex") : "0x0" + const deployer = await WitnetDeployer.deployed() + const addr = await deployer.determineProxyAddr.call(salt, { from }) + return addr +} + +function link (bytecode, libs, targets) { + if (libs && Array.isArray(libs) && libs.length > 0) { + for (index in libs) { + const key = targets[libs[index]] + const lib = artifacts.require(key) + bytecode = bytecode.replaceAll(`__${key}${"_".repeat(38 - key.length)}`, lib.address.slice(2)) + console.info(" ", `> linked library: ${key} => ${lib.address}`) + } + } + return bytecode +} diff --git a/migrations/scripts/6_WitnetRandomness.js b/migrations/scripts/6_WitnetRandomness.js deleted file mode 100644 index 2df37b91b..000000000 --- a/migrations/scripts/6_WitnetRandomness.js +++ /dev/null @@ -1,154 +0,0 @@ -const ethUtils = require("ethereumjs-util") -const { merge } = require("lodash") - -const addresses = require("../witnet.addresses") -const settings = require("../witnet.settings") -const singletons = require("../witnet.salts") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const Create2Factory = artifacts.require("Create2Factory") -const WitnetProxy = artifacts.require("WitnetProxy") - -const WitnetRandomness = artifacts.require("WitnetRandomness") -const WitnetRequestBoard = artifacts.require("WitnetRequestBoard") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - console.info() - if (!isDryRun && addresses[ecosystem][network].WitnetRandomness === undefined) { - console.info(`\n WitnetRandomness: Not to be deployed into '${network}'`) - return - } - - const create2Factory = await Create2Factory.deployed() - - const artifactNames = merge(settings.artifacts.default, settings.artifacts[ecosystem], settings.artifacts[network]) - const WitnetRandomnessImplementation = artifacts.require(artifactNames.WitnetRandomness) - - if (addresses[ecosystem][network].WitnetRandomnessImplementation !== undefined) { - let proxy - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRandomness)) { - if ( - create2Factory && !utils.isNullAddress(create2Factory.address) && - singletons?.WitnetRandomness - ) { - // Deploy the proxy via a singleton factory and a salt... - const bytecode = WitnetProxy.toJSON().bytecode - const salt = singletons.WitnetRandomness?.salt - ? "0x" + ethUtils.setLengthLeft( - ethUtils.toBuffer( - singletons.WitnetRandomness.salt - ), 32 - ).toString("hex") - : "0x0" - - const proxyAddr = await create2Factory.determineAddr.call(bytecode, salt, { from }) - if ((await web3.eth.getCode(proxyAddr)).length <= 3) { - // deploy instance only if not found in current network: - utils.traceHeader("Singleton inception of 'WitnetRandomness':") - const balance = await web3.eth.getBalance(from) - const gas = singletons.WitnetRandomness.gas - const tx = await create2Factory.deploy(bytecode, salt, { from, gas }) - utils.traceTx( - tx.receipt, - web3.utils.fromWei((balance - await web3.eth.getBalance(from)).toString()) - ) - } else { - utils.traceHeader("Singleton 'WitnetRandomness':") - } - console.info(" ", "> proxy address: ", proxyAddr) - console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(proxyAddr))) - console.info(" ", "> proxy inception salt:", salt) - proxy = await WitnetProxy.at(proxyAddr) - } else { - // Deploy no singleton proxy ... - proxy = await WitnetProxy.new({ from }) - } - addresses[ecosystem][network].WitnetRandomness = proxy.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - proxy = await WitnetProxy.at(addresses[ecosystem][network].WitnetRandomness) - console.info(` Skipped: 'WitnetRandomness' deployed at ${proxy.address}`) - } - WitnetRandomness.address = proxy.address - - let randomness - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRandomnessImplementation)) { - await deployer.deploy( - WitnetRandomnessImplementation, - WitnetRequestBoard.address, - /* _versionTag */ utils.fromAscii(version), - { from } - ) - randomness = await WitnetRandomnessImplementation.deployed() - addresses[ecosystem][network].WitnetRandomnessImplementation = randomness.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - randomness = await WitnetRandomnessImplementation.at( - addresses[ecosystem][network].WitnetRandomnessImplementation - ) - console.info(` Skipped: '${WitnetRandomnessImplementation.contractName}' deployed at ${randomness.address}`) - WitnetRandomnessImplementation.address = randomness.address - } - - const implementation = await proxy.implementation.call({ from }) - if (implementation.toLowerCase() !== randomness.address.toLowerCase()) { - const header = `Upgrading 'WitnetRandomness' at ${proxy.address}...` - console.info() - console.info(" ", header) - console.info(" ", "-".repeat(header.length)) - console.info() - console.info(" > old implementation:", implementation) - console.info(" > new implementation:", randomness.address, `(v${await randomness.version.call({ from })})`) - if ( - isDryRun || - ["y", "yes"].includes((await utils.prompt(" > Upgrade the proxy ? [y/N] ")).toLowerCase().trim()) - ) { - try { - const tx = await proxy.upgradeTo(randomness.address, "0x", { from }) - console.info(" => transaction hash :", tx.receipt.transactionHash) - console.info(" => transaction gas :", tx.receipt.gasUsed) - console.info(" > Done.") - } catch (ex) { - console.info(" !! Cannot upgrade the proxy:") - console.info(ex) - } - } else { - console.info(" > Not upgraded.") - } - } - } else { - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetRandomness)) { - // deploy unproxified WitnetRandomness contract - await deployer.deploy( - WitnetRandomnessImplementation, - WitnetRequestBoard.address, - utils.fromAscii(version), - { from } - ) - addresses[ecosystem][network].WitnetRandomness = WitnetRandomnessImplementation.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - WitnetRandomnessImplementation.address = addresses[ecosystem][network]?.WitnetRandomness - console.info(` Skipped: unproxied 'WitnetRandomness' deployed at ${WitnetRandomnessImplementation.address}`) - } - WitnetRandomness.address = WitnetRandomnessImplementation.address - } -} diff --git a/migrations/scripts/7_WitnetPriceFeeds.js b/migrations/scripts/7_WitnetPriceFeeds.js deleted file mode 100644 index 3c10eacb7..000000000 --- a/migrations/scripts/7_WitnetPriceFeeds.js +++ /dev/null @@ -1,172 +0,0 @@ -const ethUtils = require("ethereumjs-util") -const { merge } = require("lodash") - -const addresses = require("../witnet.addresses") -const settings = require("../witnet.settings") -const singletons = require("../witnet.salts") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const Create2Factory = artifacts.require("Create2Factory") -const WitnetProxy = artifacts.require("WitnetProxy") - -const WitnetPriceFeeds = artifacts.require("WitnetPriceFeeds") -const WitnetPriceFeedsLib = artifacts.require("WitnetPriceFeedsLib") -const WitnetRequestBoard = artifacts.require("WitnetRequestBoard") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - console.info() - if (!isDryRun && addresses[ecosystem][network].WitnetPriceFeeds === undefined) { - console.info(`\n WitnetPriceFeeds: Not to be deployed into '${network}'`) - return - } - - const artifactNames = merge(settings.artifacts.default, settings.artifacts[ecosystem], settings.artifacts[network]) - const WitnetPriceFeedsImplementation = artifacts.require(artifactNames.WitnetPriceFeeds) - - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetPriceFeedsLib)) { - await deployer.deploy(WitnetPriceFeedsLib, { from }) - const lib = await WitnetPriceFeedsLib.deployed() - addresses[ecosystem][network].WitnetPriceFeedsLib = lib.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - const lib = await WitnetPriceFeedsLib.at(addresses[ecosystem][network]?.WitnetPriceFeedsLib) - WitnetPriceFeedsLib.address = lib.address - utils.traceHeader("Skipping 'WitnetPriceFeedsLib'") - console.info(" ", "> library address:", lib.address) - console.info() - } - await deployer.link(WitnetPriceFeedsLib, WitnetPriceFeedsImplementation) - - if (addresses[ecosystem][network]?.WitnetPriceFeedsImplementation !== undefined || isDryRun) { - let proxy - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetPriceFeeds)) { - const create2Factory = await Create2Factory.deployed() - if ( - create2Factory && !utils.isNullAddress(create2Factory.address) && - singletons?.WitnetPriceFeeds - ) { - // Deploy the proxy via a singleton factory and a salt... - const bytecode = WitnetProxy.toJSON().bytecode - const salt = singletons.WitnetPriceFeeds?.salt - ? "0x" + ethUtils.setLengthLeft( - ethUtils.toBuffer( - singletons.WitnetPriceFeeds.salt - ), 32 - ).toString("hex") - : "0x0" - - const proxyAddr = await create2Factory.determineAddr.call(bytecode, salt, { from }) - if ((await web3.eth.getCode(proxyAddr)).length <= 3) { - // deploy instance only if not found in current network: - utils.traceHeader("Singleton inception of 'WitnetPriceFeeds':") - const balance = await web3.eth.getBalance(from) - const gas = singletons.WitnetPriceFeeds.gas - const tx = await create2Factory.deploy(bytecode, salt, { from, gas }) - utils.traceTx( - tx.receipt, - web3.utils.fromWei((balance - await web3.eth.getBalance(from)).toString()) - ) - } else { - utils.traceHeader("Singleton 'WitnetPriceFeeds':") - } - console.info(" ", "> proxy address: ", proxyAddr) - console.info(" ", "> proxy codehash: ", web3.utils.soliditySha3(await web3.eth.getCode(proxyAddr))) - console.info(" ", "> proxy inception salt:", salt) - proxy = await WitnetProxy.at(proxyAddr) - } else { - // Deploy no singleton proxy ... - proxy = await WitnetProxy.new({ from }) - } - addresses[ecosystem][network].WitnetPriceFeeds = proxy.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - proxy = await WitnetProxy.at(addresses[ecosystem][network].WitnetPriceFeeds) - console.info(` Skipped: 'WitnetPriceFeeds' deployed at ${proxy.address}`) - } - - let router - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetPriceFeedsImplementation)) { - await deployer.deploy( - WitnetPriceFeedsImplementation, - WitnetRequestBoard.address, - true, - utils.fromAscii(version), - { from } - ) - router = await WitnetPriceFeedsImplementation.deployed() - addresses[ecosystem][network].WitnetPriceFeedsImplementation = router.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - router = await WitnetPriceFeedsImplementation.at( - addresses[ecosystem][network].WitnetPriceFeedsImplementation - ) - console.info(` Skipped: '${WitnetPriceFeedsImplementation.contractName}' deployed at ${router.address}`) - WitnetPriceFeedsImplementation.address = router.address - } - WitnetPriceFeeds.address = proxy.address - - const implementation = await proxy.implementation.call({ from }) - if (implementation.toLowerCase() !== router.address.toLowerCase()) { - const header = `Upgrading 'WitnetPriceFeeds' at ${proxy.address}...` - console.info() - console.info(" ", header) - console.info(" ", "-".repeat(header.length)) - console.info() - console.info(" > old implementation:", implementation) - console.info(" > new implementation:", router.address, `(v${await router.version.call({ from })})`) - if ( - isDryRun || - ["y", "yes"].includes((await utils.prompt(" > Upgrade the proxy ? [y/N] ")).toLowerCase().trim()) - ) { - try { - const tx = await proxy.upgradeTo(router.address, "0x", { from }) - console.info(" => transaction hash :", tx.receipt.transactionHash) - console.info(" => transaction gas :", tx.receipt.gasUsed) - console.info(" > Done.") - } catch (ex) { - console.info(" !! Cannot upgrade the proxy:") - console.info(ex) - } - } else { - console.info(" > Not upgraded.") - } - } - } else { - if (utils.isNullAddress(addresses[ecosystem][network]?.WitnetPriceFeeds)) { - // deploy unproxified WitnetPriceFeeds contract - await deployer.deploy( - WitnetPriceFeedsImplementation, - WitnetRequestBoard.address, - false, - utils.fromAscii(version), - { from } - ) - addresses[ecosystem][network].WitnetPriceFeeds = WitnetPriceFeedsImplementation.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - WitnetPriceFeedsImplementation.address = addresses[ecosystem][network]?.WitnetPriceFeeds - console.info(` Skipped: unproxied 'WitnetPriceFeeds' deployed at ${WitnetPriceFeedsImplementation.address}`) - } - WitnetPriceFeeds.address = WitnetPriceFeedsImplementation.address - } -} diff --git a/migrations/scripts/8_WitnetPriceRouter.js b/migrations/scripts/8_WitnetPriceRouter.js deleted file mode 100644 index 16a807697..000000000 --- a/migrations/scripts/8_WitnetPriceRouter.js +++ /dev/null @@ -1,43 +0,0 @@ -const addresses = require("../witnet.addresses") -const utils = require("../../scripts/utils") -const version = `${ - require("../../package").version -}-${ - require("child_process").execSync("git rev-parse HEAD").toString().trim().substring(0, 7) -}` - -const WitnetPriceRouter = artifacts.require("WitnetPriceRouter") - -module.exports = async function (deployer, network, [, from]) { - const isDryRun = network === "test" || network.split("-")[1] === "fork" || network.split("-")[0] === "develop" - const ecosystem = utils.getRealmNetworkFromArgs()[0] - network = network.split("-")[0] - - if (!addresses[ecosystem]) addresses[ecosystem] = {} - if (!addresses[ecosystem][network]) addresses[ecosystem][network] = {} - - console.info() - if (!isDryRun && addresses[ecosystem][network].WitnetPriceRouter === undefined) { - console.info(`\n WitnetPriceRouter: Not to be deployed into '${network}'`) - return - } - - if ( - isDryRun || - utils.isNullAddress(addresses[ecosystem][network]?.WitnetPriceRouter) - ) { - await deployer.deploy( - WitnetPriceRouter, - false, - utils.fromAscii(version), - { from } - ) - addresses[ecosystem][network].WitnetPriceRouter = WitnetPriceRouter.address - if (!isDryRun) { - utils.saveAddresses(addresses) - } - } else { - WitnetPriceRouter.address = addresses[ecosystem][network].WitnetPriceRouter - console.info(` Skipped: 'WitnetPriceRouter' deployed at ${WitnetPriceRouter.address}`) - } -} diff --git a/migrations/witnet.salts.js b/migrations/witnet.salts.js deleted file mode 100644 index 5a2cd75f5..000000000 --- a/migrations/witnet.salts.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = { - WitnetBytecodes: { - salt: 61396704, // => solc-0.8.17: 0x0000000e3a3d22d7510B36BdC88994dab11eadc8 - gas: 1000000, - }, - WitnetPriceFeeds: { - salt: 125920098, // => solc-0.8.17: 0x9999999d139bdBFbF25923ba39F63bBFc7593400 - gas: 1000000, - }, - WitnetRandomness: { - salt: 332121398, // => solc-0.8.17: 0x0123456fbBC59E181D76B6Fe8771953d1953B51a - gas: 1000000, - }, - WitnetRequestBoard: { - salt: 198789840, // => solc-0-8.17: 0x777777772C24e6CD34B464D1d71616C444254537 - gas: 1000000, - }, - WitnetRequestFactory: { - salt: 20377356, // => solc-0.8.17: 0x1111111FDE7dC956E3d7922Bc779D9E2349Afb63 - gas: 1000000, - }, -} diff --git a/migrations/witnet.settings.js b/migrations/witnet.settings.js index 8ff8e66cf..5081d57d8 100644 --- a/migrations/witnet.settings.js +++ b/migrations/witnet.settings.js @@ -2,8 +2,11 @@ module.exports = { artifacts: { default: { WitnetBytecodes: "WitnetBytecodesDefault", - WitnetPriceFeeds: "WitnetPriceFeedsUpgradable", - WitnetRandomness: "WitnetRandomnessProxiable", + WitnetEncodingLib: "WitnetEncodingLib", + WitnetErrorsLib: "WitnetErrorsLib", + WitnetPriceFeeds: "WitnetPriceFeeds", + WitnetPriceFeedsLib: "WitnetPriceFeedsLib", + WitnetRandomness: "WitnetRandomness", WitnetRequestBoard: "WitnetRequestBoardTrustableDefault", WitnetRequestFactory: "WitnetRequestFactoryDefault", }, @@ -38,113 +41,17 @@ module.exports = { compilers: { default: { solc: { - version: "0.8.17", + version: "0.8.22", settings: { optimizer: { enabled: true, runs: 200, }, + evmVersion: "paris", }, }, }, }, - constructorParams: { - default: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 133000, - ], - }, - avalanche: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 155000, - ], - }, - celo: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 114000, - ], - }, - conflux: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 78500, - ], - }, - "conflux.espace.testnet": { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 225000, - ], - }, - "conflux.espace.mainnet": { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 225000, - ], - }, - cronos: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 137500, - ], - }, - dogechain: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 85000, - ], - }, - harmony: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 530000, - ], - }, - hsc: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 85000, - ], - }, - kcc: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 92500, - ], - }, - klaytn: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 105000, - ], - }, - meter: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 85000, - ], - }, - metis: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 134800, - ], - }, - moonbeam: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 115000, - ], - }, - okxchain: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 145000, - ], - }, - optimism: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 135000, - ], - }, - reef: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ "0x3100A1CAC7EF19DC", - ], - }, - ultron: { - WitnetRequestBoard: [ - /* _reportResultGasLimit */ 83949, - ], - }, - }, networks: { default: { "ethereum.goerli": { @@ -749,4 +656,197 @@ module.exports = { }, }, }, + specs: { + default: { + WitnetBytecodes: { + libs: ["WitnetEncodingLib"], + vanity: 172582, + }, + WitnetRandomness: { + vanity: 4, + }, + WitnetRequestBoard: { + immutables: { + types: ["uint256", "uint256", "uint256", "uint256"], + values: [ + /* _reportResultGasBase */ 58282, + /* _reportResultWithCallbackGasBase */ 65273, + /* _reportResultWithCallbackRevertGasBase */ 69546, + /* _sstoreFromZeroGas */ 20000, + ], + }, + libs: ["WitnetErrorsLib"], + vanity: 899032812, // => 0x000071F0c823bD30D2Bf4CD1E829Eba5A6070000 + }, + WitnetRequestFactory: { + vanity: 178848, + }, + WitnetPriceFeeds: { + libs: ["WitnetPriceFeedsLib"], + vanity: 5, + }, + }, + avalanche: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 155000, + ], + }, + }, + }, + celo: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 114000, + ], + }, + }, + }, + conflux: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 78500, + ], + }, + }, + }, + "conflux.espace.testnet": { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 225000, + ], + }, + }, + }, + "conflux.espace.mainnet": { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 225000, + ], + }, + }, + }, + cronos: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 137500, + ], + }, + }, + }, + dogechain: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 85000, + ], + }, + }, + }, + harmony: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 530000, + ], + }, + }, + }, + hsc: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 85000, + ], + }, + }, + }, + kcc: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 92500, + ], + }, + }, + }, + klaytn: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 105000, + ], + }, + }, + }, + meter: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 85000, + ], + }, + }, + }, + metis: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 134800, + ], + }, + }, + }, + moonbeam: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 115000, + ], + }, + }, + }, + okxchain: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 145000, + ], + }, + }, + }, + optimism: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 135000, + ], + }, + }, + }, + reef: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ "0x3100A1CAC7EF19DC", + ], + }, + }, + }, + ultron: { + WitnetRequestBoard: { + immutables: { + values: [ + /* _reportResultGasBase */ 83949, + ], + }, + }, + }, + }, } diff --git a/package.json b/package.json index fb87efad1..794351cb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "witnet-solidity-bridge", - "version": "0.7.16", + "version": "2.0.1", "description": "Witnet Solidity Bridge contracts for EVM-compatible chains", "main": "", "scripts": { @@ -13,10 +13,10 @@ "coverage": "solidity-coverage", "flatten": "node ./scripts/flatten.js 2>&1", "flatten:all": "npm run clean && npm run flatten:core && npm run flatten:apps && npm run flatten:libs && npm run flatten:proxy", - "flatten:apps": "npm run flatten contracts/impls/apps/", - "flatten:core": "npm run flatten contracts/impls/core/", + "flatten:apps": "npm run flatten contracts/core/apps/", + "flatten:core": "npm run flatten contracts/core/core/", "flatten:libs": "npm run flatten contracts/libs/WitnetErrorsLib.sol && npm run flatten contracts/libs/WitnetEncodingLib.sol && npm run flatten contracts/libs/WitnetPriceFeedsLib.sol", - "flatten:proxy": "npm run flatten contracts/impls/WitnetProxy.sol", + "flatten:proxy": "npm run flatten contracts/core/WitnetProxy.sol", "fmt:js": "eslint \"**/*.js\"", "fmt:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\" && solhint \"test/**/*.sol\" && solhint \"flattened/**/*.sol\"", "fmt!:js": "eslint \"**/*.js\" --fix", @@ -55,9 +55,11 @@ "eslint-plugin-import": "~2.26.0", "eslint-plugin-n": "~15.6.0", "eslint-plugin-promise": "~6.1.1", - "eth-create2": "~1.0.1", + "eth-helpers": "^1.3.0", "eth-gas-reporter": "0.2.25", "js-sha256": "0.9.0", + "nanoassert": "^2.0.0", + "sha3-wasm": "0.0.7", "solhint": "3.3.7", "solidity-coverage": "0.7.16", "truffle": "~5.11.5", diff --git a/scripts/eth-create2.js b/scripts/eth-create2.js new file mode 100644 index 000000000..5a364f00e --- /dev/null +++ b/scripts/eth-create2.js @@ -0,0 +1,36 @@ +const assert = require("nanoassert") +const { utils } = require("eth-helpers") +const keccak = require("sha3-wasm").keccak256 + +const prefix = Buffer.from([0xff]) + +/** + * Generate Ethereum CREATE2 address + * + * @param {string|Buffer} address Ethereum address of creator contract as + * string or as a 20 byte `Buffer` + * @param {string|Buffer} salt 256 bit salt as either string or 32 byte `Buffer` + * @param {string|Buffer} initCode init_code as string or Buffer + * @returns {string} result address as hex encoded string. Not + * checksum'ed. This can be done with + * `eth-checksum` or similar modules + */ +module.exports = function create2 (address, salt, initCode) { + if (typeof address === "string") address = utils.parse.address(address) + if (typeof salt === "string") salt = utils.parse.uint256(salt) + if (typeof initCode === "string") initCode = utils.parse.bytes(initCode) + + assert(address.byteLength === 20, "address must be 20 bytes") + assert(salt.byteLength === 32, "salt must be 32 bytes") + assert(initCode.byteLength != null, "initCode must be Buffer") + + const codeHash = keccak().update(initCode).digest() + + return utils.format.address(keccak() + .update(prefix) + .update(address) + .update(salt) + .update(codeHash) + .digest() + .slice(-20)) +} diff --git a/scripts/eth-create3.js b/scripts/eth-create3.js new file mode 100644 index 000000000..613e8de59 --- /dev/null +++ b/scripts/eth-create3.js @@ -0,0 +1,42 @@ +const assert = require("nanoassert") +const { utils } = require("eth-helpers") +const keccak = require("sha3-wasm").keccak256 + +const factoryPrefix = Buffer.from([0xff]) + +/** + * Generate Ethereum CREATE3-library address + * + * @param {string|Buffer} address Ethereum address of creator contract as + * string or as a 20 byte `Buffer` + * @param {string|Buffer} salt 256 bit salt as either string or 32 byte `Buffer` + * @returns {string} result address as hex encoded string. Not + * checksum'ed. This can be done with + * `eth-checksum` or similar modules + */ +module.exports = function create3 (address, salt) { + if (typeof address === "string") address = utils.parse.address(address) + if (typeof salt === "string") salt = utils.parse.uint256(salt) + + assert(address.byteLength === 20, "address must be 20 bytes") + assert(salt.byteLength === 32, "salt must be 32 bytes") + + const factoryHash = utils.parse.uint256("0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f") + const factoryAddr = keccak() + .update(factoryPrefix) + .update(address) + .update(salt) + .update(factoryHash) + .digest() + .slice(-20) + + assert(factoryAddr.byteLength === 20, "address must be 20 bytes") + + return utils.format.address(keccak() + .update(Buffer.from([0xd6, 0x94])) + .update(factoryAddr) + .update(Buffer.from([0x01])) + .digest() + .slice(-20) + ) +} diff --git a/scripts/utils/index.js b/scripts/utils/index.js index ec39657fd..1cce66d5b 100644 --- a/scripts/utils/index.js +++ b/scripts/utils/index.js @@ -1,5 +1,6 @@ const fs = require("fs") require("dotenv").config() +const { isEqual } = require("lodash") const readline = require("readline") const web3 = require("web3") @@ -14,6 +15,7 @@ module.exports = { padLeft, prompt, saveAddresses, + saveJsonAbi, traceHeader, traceTx, } @@ -116,3 +118,23 @@ function saveAddresses (addrs) { { flag: "w+" } ) } + +function saveJsonAbi (key, abi) { + const version = require("../../package.json").version + const latest_fn = `./migrations/abis/${key}.json` + const version_fn = `./migrations/abis/${key}-${version}.json` + let latest_abi = [] + if (fs.existsSync(latest_fn)) { + try { + latest_abi = JSON.parse(fs.readFileSync(latest_fn)) + } catch {} + } + if (!isEqual(abi, latest_abi)) { + const json = JSON.stringify(abi, null, 4) + if (fs.existsSync(latest_fn)) { + // avoid creating versioned abi upon first deployment + fs.writeFileSync(version_fn, json, { flag: "w+" }) + } + fs.writeFileSync(latest_fn, json, { flag: "w+" }) + } +} diff --git a/scripts/utils/traceTx.js b/scripts/utils/traceTx.js index 06bdb31ef..28134518a 100644 --- a/scripts/utils/traceTx.js +++ b/scripts/utils/traceTx.js @@ -1,9 +1,8 @@ -module.exports = function (receipt, totalCost) { - console.log(" ", "> block number: ", receipt.blockNumber) - console.log(" ", "> transaction hash: ", receipt.transactionHash) - console.log(" ", "> transaction gas: ", receipt.gasUsed) - if (totalCost) { - console.log(" ", "> total cost: ", totalCost, "ETH") - } - console.log() +const web3 = require("web3") + +module.exports = function (tx) { + console.info(" ", "> transaction hash: ", tx.receipt.transactionHash) + console.info(" ", "> gas used: ", tx.receipt.gasUsed.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")) + console.info(" ", "> gas price: ", tx.receipt.effectiveGasPrice / 10 ** 9, "gwei") + console.info(" ", "> total cost: ", web3.utils.fromWei(BigInt(tx.receipt.gasUsed * tx.receipt.effectiveGasPrice).toString(), "ether"), "ETH") } diff --git a/scripts/vanity2gen.js b/scripts/vanity2gen.js new file mode 100644 index 000000000..0ce0ee900 --- /dev/null +++ b/scripts/vanity2gen.js @@ -0,0 +1,82 @@ +const { assert } = require("chai") +const create2 = require("./eth-create2") +const fs = require("fs") +const utils = require("./utils") + +const addresses = require("../migrations/witnet.addresses") + +module.exports = async function () { + let artifact + let count = 0 + let ecosystem = "default" + let from + let hits = 10 + let offset = 0 + let network = "default" + let prefix = "0x00" + let suffix = "00" + let hexArgs = "" + process.argv.map((argv, index, args) => { + if (argv === "--offset") { + offset = parseInt(args[index + 1]) + } else if (argv === "--artifact") { + artifact = artifacts.require(args[index + 1]) + } else if (argv === "--prefix") { + prefix = args[index + 1].toLowerCase() + assert(web3.utils.isHexStrict(prefix), "--prefix: invalid hex string") + } else if (argv === "--suffix") { + suffix = args[index + 1].toLowerCase() + assert(web3.utils.isHexStrict(suffix), "--suffix: invalid hex string") + } else if (argv === "--hits") { + hits = parseInt(args[index + 1]) + } else if (argv === "--network") { + [ecosystem, network] = utils.getRealmNetworkFromString(args[index + 1].toLowerCase()) + } else if (argv === "--hexArgs") { + hexArgs = args[index + 1].toLowerCase() + if (hexArgs.startsWith("0x")) hexArgs = hexArgs.slice(2) + assert(web3.utils.isHexStrict("0x" + hexArgs), "--hexArgs: invalid hex string") + } else if (argv === "--from") { + from = args[index + 1] + } + return argv + }) + try { + from = from || addresses[ecosystem][network].WitnetDeployer + } catch { + console.error(`WitnetDeployer must have been previously deployed on network '${network}'.\n`) + console.info("Usage:\n") + console.info(" --artifact => Truffle artifact name (mandatory)") + console.info(" --hexArgs => Hexified constructor arguments") + console.info(" --hits => Number of vanity hits to look for (default: 10)") + console.info(" --network => Network name") + console.info(" --offset => Salt starting value minus 1 (default: 0)") + console.info(" --prefix => Prefix hex string to look for (default: 0x00)") + console.info(" --suffix => suffix hex string to look for (default: 0x00)") + process.exit(1) + } + if (!artifact) { + console.error("No --artifact was set!") + process.exit(1) + } + const initCode = artifact.toJSON().bytecode + hexArgs + console.log("Init code: ", initCode) + console.log("Artifact: ", artifact?.contractName) + console.log("From: ", from) + console.log("Hits: ", hits) + console.log("Offset: ", offset) + console.log("Prefix: ", prefix) + console.log("Suffix: ", suffix) + console.log("=".repeat(55)) + suffix = suffix.slice(2) + while (count < hits) { + const salt = "0x" + utils.padLeft(offset.toString(16), "0", 32) + const addr = create2(from, salt, initCode).toLowerCase() + if (addr.startsWith(prefix) && addr.endsWith(suffix)) { + const found = `${offset} => ${web3.utils.toChecksumAddress(addr)}` + console.log(found) + fs.appendFileSync(`./migrations/salts/${artifact?.contractName}$${from.toLowerCase()}.tmp`, found + "\n") + count++ + } + offset++ + } +} diff --git a/scripts/vanity3gen.js b/scripts/vanity3gen.js new file mode 100644 index 000000000..3e1721686 --- /dev/null +++ b/scripts/vanity3gen.js @@ -0,0 +1,66 @@ +const { assert } = require("chai") +const create3 = require("./eth-create3") +const fs = require("fs") +const utils = require("./utils") + +const addresses = require("../migrations/witnet.addresses") + +module.exports = async function () { + let count = 0 + let ecosystem = "default" + let from + let hits = 10 + let offset = 0 + let network = "default" + let prefix = "0x00" + let suffix = "0x00" + const hexArgs = "" + process.argv.map((argv, index, args) => { + if (argv === "--offset") { + offset = parseInt(args[index + 1]) + } else if (argv === "--prefix") { + prefix = args[index + 1].toLowerCase() + assert(web3.utils.isHexStrict(prefix), "--prefix: invalid hex string") + } else if (argv === "--suffix") { + suffix = args[index + 1].toLowerCase() + assert(web3.utils.isHexStrict(suffix), "--suffix: invalid hex string") + } else if (argv === "--hits") { + hits = parseInt(args[index + 1]) + } else if (argv === "--network") { + [ecosystem, network] = utils.getRealmNetworkFromString(args[index + 1].toLowerCase()) + } else if (argv === "--from") { + from = args[index + 1] + } + return argv + }) + try { + from = from || addresses[ecosystem][network].WitnetDeployer + } catch { + console.error(`WitnetDeployer must have been previously deployed on network '${network}'.\n`) + console.info("Usage:\n") + console.info(" --hits => Number of vanity hits to look for (default: 10)") + console.info(" --network => Network name") + console.info(" --offset => Salt starting value minus 1 (default: 0)") + console.info(" --prefix => Prefix hex string to look for (default: 0x00)") + console.info(" --suffix => suffix hex string to look for (default: 0x00)") + process.exit(1) + } + console.log("From: ", from) + console.log("Hits: ", hits) + console.log("Offset: ", offset) + console.log("Prefix: ", prefix) + console.log("Suffix: ", suffix) + console.log("=".repeat(55)) + suffix = suffix.slice(2) + while (count < hits) { + const salt = "0x" + utils.padLeft(offset.toString(16), "0", 32) + const addr = create3(from, salt).toLowerCase() + if (addr.startsWith(prefix) && addr.endsWith(suffix)) { + const found = `${offset} => ${web3.utils.toChecksumAddress(addr)}` + console.log(found) + fs.appendFileSync(`./migrations/salts/create3$${from.toLowerCase()}.tmp`, found + "\n") + count++ + } + offset++ + } +} diff --git a/scripts/vanitygen.js b/scripts/vanitygen.js deleted file mode 100644 index b86638fce..000000000 --- a/scripts/vanitygen.js +++ /dev/null @@ -1,70 +0,0 @@ -const { assert } = require("chai") -const create2 = require("eth-create2") -const fs = require("fs") -const utils = require("./utils") - -const addresses = require("../migrations/witnet.addresses") - -module.exports = async function () { - let artifact - let count = 0 - let ecosystem = "default" - let from - let hits = 10 - let offset = 0 - let network = "default" - let target = "0xfacade" - process.argv.map((argv, index, args) => { - if (argv === "--from") { - from = args[index + 1] - } else if (argv === "--offset") { - offset = parseInt(args[index + 1]) - } else if (argv === "--artifact") { - artifact = artifacts.require(args[index + 1]) - } else if (argv === "--target") { - target = args[index + 1].toLowerCase() - } else if (argv === "--hits") { - hits = parseInt(args[index + 1]) - } else if (argv === "--network") { - [ecosystem, network] = utils.getRealmNetworkFromString(args[index + 1].toLowerCase()) - } - return argv - }) - try { - from = from || addresses[ecosystem][network].Create2Factory - } catch { - console.error(` Create2Factory must have been previously deployed on network '${network}'.\n`) - console.info("Usage:\n") - console.info(" --artifact => Truffle artifact name (default: WitnetProxy)") - console.info(" --hits => Number of vanity hits to look for (default: 10)") - console.info(" --offset => Salt starting value minus 1 (default: 0)") - console.info(" --network => Network name") - console.info(" --target => Prefix hex number to look for (default: 0xc0ffee)") - process.exit(1) - } - const bytecode = artifact - ? artifact.toJSON().bytecode - : `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${from.toLowerCase().slice(2)}5af43d82803e903d91602b57fd5bf3` - const targets = target.split(",") - for (let j = 0; j < targets.length; j++) { - assert(web3.utils.isHexStrict(targets[j]), "--target refers invalid hex string") - } - console.log("Bytecode: ", bytecode) - console.log("Artifact: ", artifact?.contractName || "ERC-1167: Minimal Proxy Contract") - console.log("From: ", from) - console.log("Hits: ", hits) - console.log("Offset: ", offset) - console.log("Target: ", target) - console.log("=".repeat(55)) - while (count < hits) { - const salt = "0x" + utils.padLeft(offset.toString(16), "0", 32) - const addr = create2(from, salt, bytecode) - if (targets.some((word) => addr.toLowerCase().startsWith(word))) { - const found = `${offset} => ${web3.utils.toChecksumAddress(addr)}` - console.log(found) - fs.appendFileSync(`./migrations/salts/${artifact?.contractName || "MinimalProxy"}$${from.toLowerCase()}.tmp`, found + "\n") - count++ - } - offset++ - } -}