Skip to content

Commit 66a31c2

Browse files
committed
feat: WRBv2 approach witnet#2
1 parent 30a72c2 commit 66a31c2

30 files changed

+1656
-158
lines changed

.env_example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1+
ARBISCAN_API_KEY=
2+
ELASTOS_API_KEY=
3+
ETHERSCAN_API_KEY=
4+
MOONSCAN_API_KEY=
5+
POLYGONSCAN_API_KEY=
16
WITNET_EVM_REALM=default

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ yarn-error.log
1313
package-lock.json
1414

1515
*.tmp
16+
.old

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,9 @@ Please, have a look at the [`witnet/truffle-box`](https://github.com/witnet/truf
267267
·······································|···························|·············|·············|·············|··············|··············
268268
| WitnetProxy · upgradeTo · - · - · 129653 · 1 · - │
269269
·······································|···························|·············|·············|·············|··············|··············
270-
| WitnetRandomness · clone · - · - · 247765 · 7 · - │
270+
| WitnetRandomnessProxiable · clone · - · - · 247765 · 7 · - │
271271
·······································|···························|·············|·············|·············|··············|··············
272-
| WitnetRandomness · upgradeRandomizeFee · - · - · 28446 · 1 · - │
272+
| WitnetRandomnessProxiable · upgradeRandomizeFee · - · - · 28446 · 1 · - │
273273
·······································|···························|·············|·············|·············|··············|··············
274274
| WitnetRequestBoardTrustableBoba · deleteQuery · - · - · 59706 · 3 · - │
275275
·······································|···························|·············|·············|·············|··············|··············

contracts/UsingWitnetV2.sol

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.7.0 <0.9.0;
4+
pragma experimental ABIEncoderV2;
5+
6+
import "./WitnetRequestBoardV2.sol";
7+
8+
/// @title The UsingWitnetV2 contract
9+
/// @dev Witnet-aware contracts can inherit from this contract in order to interact with Witnet.
10+
/// @author The Witnet Foundation.
11+
abstract contract UsingWitnetV2 {
12+
13+
/// @dev Immutable address to the WitnetRequestBoardV2 contract.
14+
WitnetRequestBoardV2 public immutable witnet;
15+
16+
/// @dev Include an address to specify the WitnetRequestBoard entry point address.
17+
/// @param _wrb The WitnetRequestBoard entry point address.
18+
constructor(WitnetRequestBoardV2 _wrb)
19+
{
20+
require(
21+
_wrb.class() == type(WitnetRequestBoardV2).interfaceId,
22+
"UsingWitnetV2: uncompliant request board"
23+
);
24+
witnet = _wrb;
25+
}
26+
27+
/// @dev Provides a convenient way for client contracts extending this to block the execution of the main logic of the
28+
/// @dev contract until a particular data query has been successfully solved and reported by Witnet,
29+
/// @dev either with an error or successfully.
30+
modifier witnetQueryInStatus(bytes32 _queryHash, WitnetV2.QueryStatus _queryStatus) {
31+
require(
32+
witnet.checkQueryStatus(_queryHash) == _queryStatus,
33+
"UsingWitnetV2: unexpected query status");
34+
_;
35+
}
36+
37+
/// @notice Returns EVM gas price within the context of current transaction.
38+
function _getTxGasPrice() virtual internal view returns (uint256) {
39+
return tx.gasprice;
40+
}
41+
42+
/// @notice Estimate the minimum reward in EVM/wei required for posting the described Witnet data request.
43+
/// @param _radHash The hash of the query's data request part (previously registered in `witnet.registry()`).
44+
/// @param _slaParams The query's SLA parameters.
45+
/// @param _witEvmPrice The price of 1 nanoWit in EVM/wei to be used when estimating query rewards.
46+
/// @param _maxEvmGasPrice The maximum EVM gas price willing to pay upon result reporting.
47+
function _witnetEstimateQueryReward(
48+
bytes32 _radHash,
49+
WitnetV2.RadonSLAv2 memory _slaParams,
50+
uint256 _witEvmPrice,
51+
uint256 _maxEvmGasPrice
52+
)
53+
internal view
54+
returns (uint256)
55+
{
56+
return witnet.estimateQueryReward(_radHash, _slaParams, _witEvmPrice, _maxEvmGasPrice, 0);
57+
}
58+
59+
/// @notice Post some data request to be eventually solved by the Witnet decentralized oracle network.
60+
/// @dev Enough EVM coins need to be provided as to cover for the implicit cost and bridge rewarding.
61+
/// @param _radHash The hash of the query's data request part (previously registered in `witnet.registry()`).
62+
/// @param _slaParams The query's SLA parameters.
63+
/// @param _witEvmPrice The price of 1 nanoWit in EVM/wei to be used when estimating query rewards.
64+
/// @param _maxEvmGasPrice The maximum EVM gas price willing to pay upon result reporting.
65+
/// @return _queryHash The unique identifier of the new data query.
66+
/// @return _queryReward The actual amount escrowed into the WRB as query reward.
67+
function _witnetPostQuery(
68+
bytes32 _radHash,
69+
WitnetV2.RadonSLAv2 memory _slaParams,
70+
uint256 _witEvmPrice,
71+
uint256 _maxEvmGasPrice
72+
)
73+
virtual internal
74+
returns (bytes32 _queryHash, uint256 _queryReward)
75+
{
76+
_queryReward = _witnetEstimateQueryReward(_radHash, _slaParams, _witEvmPrice, _maxEvmGasPrice);
77+
require(_queryReward <= msg.value, "UsingWitnetV2: EVM reward too low");
78+
_queryHash = witnet.postQuery{value: _queryReward}(_radHash, _slaParams);
79+
}
80+
81+
/// @notice Post some data request to be eventually solved by the Witnet decentralized oracle network.
82+
/// @dev Enough EVM coins need to be provided as to cover for the implicit cost and bridge rewarding.
83+
/// @dev Implicitly sets `tx.gasprice` as the maximum EVM gas price expected to be paid upon result reporting.
84+
/// @param _radHash The hash of the query's data request part (previously registered in `witnet.registry()`).
85+
/// @param _slaParams The query's SLA parameters.
86+
/// @param _witEvmPrice The price of 1 nanoWit in EVM/wei to be used when estimating query rewards.
87+
/// @return _queryHash The unique identifier of the new data query.
88+
/// @return _queryReward The actual amount escrowed into the WRB as query reward.
89+
function _witnetPostQuery(bytes32 _radHash, WitnetV2.RadonSLAv2 memory _slaParams, uint256 _witEvmPrice)
90+
virtual internal
91+
returns (bytes32 _queryHash, uint256 _queryReward)
92+
{
93+
return _witnetPostQuery(_radHash, _slaParams, _witEvmPrice, _getTxGasPrice());
94+
}
95+
}

contracts/WitnetBlocks.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.7.0 <0.9.0;
4+
pragma experimental ABIEncoderV2;
5+
6+
import "./interfaces/V2/IWitnetBlocks.sol";
7+
8+
abstract contract WitnetBlocks
9+
is
10+
IWitnetBlocks
11+
{}

contracts/WitnetRequestBoardV2.sol

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.7.0 <0.9.0;
4+
pragma experimental ABIEncoderV2;
5+
6+
import "./WitnetBlocks.sol";
7+
import "./WitnetBytecodes.sol";
8+
import "./WitnetRequestFactory.sol";
9+
10+
/// @title Witnet Request Board V2 functionality base contract.
11+
/// @author The Witnet Foundation.
12+
abstract contract WitnetRequestBoardV2
13+
is
14+
IWitnetRequestBoardV2
15+
{
16+
WitnetBlocks immutable public blocks;
17+
WitnetRequestFactory immutable public factory;
18+
WitnetBytecodes immutable public registry;
19+
constructor (
20+
WitnetBlocks _blocks,
21+
WitnetRequestFactory _factory
22+
)
23+
{
24+
require(
25+
_blocks.class() == type(WitnetBlocks).interfaceId,
26+
"WitnetRequestBoardV2: uncompliant blocks"
27+
);
28+
require(
29+
_factory.class() == type(WitnetRequestFactory).interfaceId,
30+
"WitnetRequestBoardV2: uncompliant factory"
31+
);
32+
blocks = _blocks;
33+
factory = _factory;
34+
registry = _factory.registry();
35+
}
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.8.0 <0.9.0;
4+
5+
import "../libs/WitnetV2.sol";
6+
7+
/// @title WitnetBlocks data model.
8+
/// @author The Witnet Foundation.
9+
abstract contract WitnetBlocksData {
10+
11+
bytes32 private constant _WITNET_BLOCKS_DATA_SLOTHASH =
12+
/* keccak256("io.witnet.blocks.data") */
13+
0x28b1d7e478138a94698f82768889fd6edf6b777bb6815c200552870d3e78ffb5;
14+
15+
struct Storage {
16+
WitnetV2.Beacon lastBeacon;
17+
}
18+
19+
// ================================================================================================
20+
// --- Internal functions -------------------------------------------------------------------------
21+
22+
/// @notice Returns storage pointer to where Storage data is located.
23+
function __blocks()
24+
internal pure
25+
returns (Storage storage _ptr)
26+
{
27+
assembly {
28+
_ptr.slot := _WITNET_BLOCKS_DATA_SLOTHASH
29+
}
30+
}
31+
32+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity >=0.7.0 <0.9.0;
4+
5+
import "../libs/WitnetV2.sol";
6+
import "../interfaces/V2/IWitnetBlocks.sol";
7+
8+
/// @title Witnet Request Board base data model.
9+
/// @author The Witnet Foundation.
10+
abstract contract WitnetRequestBoardV2Data {
11+
12+
bytes32 internal constant _WITNET_BOARD_DATA_SLOTHASH =
13+
/* keccak256("io.witnet.boards.data.v2") */
14+
0xfeed002ff8a708dcba69bac2a8e829fd61fee551b9e9fc0317707d989cb0fe53;
15+
16+
struct Storage {
17+
uint256 nonce;
18+
mapping (address => Escrow) escrows;
19+
mapping (bytes32 => WitnetV2.Query) queries;
20+
}
21+
22+
struct Escrow {
23+
uint256 atStake;
24+
uint256 balance;
25+
}
26+
27+
/// Asserts the given query was previously posted but not yet deleted.
28+
modifier queryExists(bytes32 queryHash) {
29+
require(__query_(queryHash).from != address(0), "WitnetRequestBoardV2Data: empty query");
30+
_;
31+
}
32+
33+
34+
// ================================================================================================================
35+
// --- Internal functions -----------------------------------------------------------------------------------------
36+
37+
/// Gets query storage by query id.
38+
function __query_(bytes32 queryHash) internal view returns (WitnetV2.Query storage) {
39+
return __storage().queries[queryHash];
40+
}
41+
42+
/// Gets the Witnet.Request part of a given query.
43+
function __request_(bytes32 queryHash) internal view returns (WitnetV2.QueryRequest storage) {
44+
return __query_(queryHash).request;
45+
}
46+
47+
/// Gets the Witnet.Result part of a given query.
48+
function __report_(bytes32 queryHash) internal view returns (WitnetV2.QueryReport storage) {
49+
return __query_(queryHash).report;
50+
}
51+
52+
/// Returns storage pointer to contents of 'WitnetBoardState' struct.
53+
function __storage() internal pure returns (Storage storage _ptr) {
54+
assembly {
55+
_ptr.slot := _WITNET_BOARD_DATA_SLOTHASH
56+
}
57+
}
58+
59+
/// Gets current status of given query.
60+
function _statusOf(bytes32 queryHash, IWitnetBlocks blocks)
61+
internal view
62+
returns (WitnetV2.QueryStatus)
63+
{
64+
WitnetV2.Query storage __query = __query_(queryHash);
65+
if (__query.reporter != address(0) || __query.disputes.length > 0) {
66+
if (blocks.getLastBeaconIndex() >= __query.epoch) {
67+
return WitnetV2.QueryStatus.Finalized;
68+
} else {
69+
if (__query.disputes.length > 0) {
70+
return WitnetV2.QueryStatus.Disputed;
71+
} else {
72+
return WitnetV2.QueryStatus.Reported;
73+
}
74+
}
75+
} else if (__query.from != address(0)) {
76+
return WitnetV2.checkQueryPostStatus(
77+
__query.epoch,
78+
blocks.getCurrentBeaconIndex()
79+
);
80+
} else {
81+
return WitnetV2.QueryStatus.Void;
82+
}
83+
}
84+
85+
function _statusOfRevertMessage(WitnetV2.QueryStatus queryStatus)
86+
internal pure
87+
returns (string memory)
88+
{
89+
string memory _reason;
90+
if (queryStatus == WitnetV2.QueryStatus.Posted) {
91+
_reason = "Posted";
92+
} else if (queryStatus == WitnetV2.QueryStatus.Reported) {
93+
_reason = "Reported";
94+
} else if (queryStatus == WitnetV2.QueryStatus.Disputed) {
95+
_reason = "Disputed";
96+
} else if (queryStatus == WitnetV2.QueryStatus.Expired) {
97+
_reason = "Expired";
98+
} else if (queryStatus == WitnetV2.QueryStatus.Finalized) {
99+
_reason = "Finalized";
100+
} else {
101+
_reason = "expected";
102+
}
103+
return string(abi.encodePacked(
104+
"WitnetRequestBoardV2Data: not in ",
105+
_reason,
106+
" status"
107+
));
108+
}
109+
}

contracts/impls/WitnetUpgradableBase.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ abstract contract WitnetUpgradableBase
4343
revert("WitnetUpgradableBase: not implemented");
4444
}
4545

46+
function class() virtual external view returns (bytes4);
47+
4648

4749
// ================================================================================================================
4850
// --- Overrides IERC165 interface --------------------------------------------------------------------------------

contracts/impls/apps/WitnetPriceFeedsUpgradable.sol

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ contract WitnetPriceFeedsUpgradable
6060
}
6161
}
6262

63+
function class() virtual override external pure returns (bytes4) {
64+
return type(WitnetPriceFeeds).interfaceId;
65+
}
66+
6367

6468
// ================================================================================================================
6569
// --- Overrides 'Upgradeable' -------------------------------------------------------------------------------------
@@ -93,7 +97,8 @@ contract WitnetPriceFeedsUpgradable
9397
witnessCollateral: 15 * 10 ** 9,
9498
witnessReward: 15 * 10 ** 7,
9599
minerCommitRevealFee: 10 ** 7,
96-
minConsensusPercentage: 51
100+
minConsensusPercentage: 51,
101+
minMinerFee: 0
97102
}));
98103
}
99104
__proxiable().implementation = base();

0 commit comments

Comments
 (0)