From 3e14fcd45323bcbdf5a841a85ed1c7da82d5cc71 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 09:57:57 +0100 Subject: [PATCH 01/17] adds swap files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 10501583560..95fdb84e3e6 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ build/ _yardoc doc/ .idea/ +*.sw* From bbced2f0c54c95b2b4a216a9a2c12801fefeaaff Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 10:00:07 +0100 Subject: [PATCH 02/17] adds query rebroadcasts section to ETH docs --- source/includes/_ethereum.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index 8f8e616288d..ce2fbf0a2d1 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -258,6 +258,42 @@ When calling `oraclize_setCustomGasPrice` the parameter type is uint and represe +### Query Rebroadcasts + +When making Provable queries, users are able to specify custom gas limits and gas prices for them as outlined __[in this section here.](http://docs.oraclize.it/#ethereum-quick-start-custom-gas-limit-and-gas-price)__ However, due to the asynchronous nature of Provable queries and the volatility of gas-prices on the Ethereum Mainnet, a user may occasionally find themselves in a situation where the gas price they have requested for their callback transaction is no longer high enough to ensure the transaction gets mined quickly. This is especially true when using delayed queries, where the likelihood of the congestion level of the Ethereum network when the query was made being the same as when the delayed callback is due diminishes. + +In such cases, users have the ability to request a _rebroadcast_ of their transaction, via which the user may specify new, higher parameters for both the gas limit and the gas price: + +```javascript +uint256 newGasLimit = ; +uint256 newGasPrice = ; + +oraclize_requestCallbackRebroadcast( + , + newGasLimit, + newGasPrice + oraclize_getRebroadcastCost(newGasLimit, newGasPrice) +); +``` + +This way, the effects of the changing network conditions can be mitigated, ensuring callbacks are always received in a timely manner. + +Another useful feature of rebroadcasting is in giving a user a finer-control over the gas limit of their callback. Should a query be sent with an amount of gas too low for the `__callback()` to fully execute, the query would normally `revert()` and be wasted. Now a user has the ability to request a rebroadcast on that query and thus the opportunity to make changes to the gas limit in order to remedy the situation. + +In order to enable rebroadcasts, a contract writer must explicitly define the following in the storage of their contract: `bool public constant allowQueryRebroadcasts = true;`. Any attempts to rebroadcast a query destined for a contract which does not have the preceding line present will be unfulfilled. + +Just like a normal query, any over-payment is refunded, but always to the _final calling contract_. Which latter gives rise to two important caveats: + +- The first is that the refund will _always_ go to the final calling contract, and so if the call for a rebroadcast is proxied via another contract, the refund will always be made to the that implements the API, and not necessarily to the contract which initiated and paid for the call. + +- The second caveat is that the final calling contract will also require a payable `fallback()` function in order to receive refunds in such cases. Absent this function, the refund attempt will cause the query to `revert();`. + +Due to the preceding caveats, it is strongly recommended that queries be paid for using their exact cost, which can be calculated via: `oraclize_getRebroadcastCost(, );` + + + ### Authenticity Proofs ```javascript From e7651fb0ccffc8f3d7302ca6c1b0e5366489818a Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 11:00:32 +0100 Subject: [PATCH 03/17] adds `getPrice` helper overloads info to docs --- source/includes/_ethereum.md | 43 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index ce2fbf0a2d1..00388369284 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -370,7 +370,7 @@ Supported proofs can be verified. The following tools can be used: this.balance) { newOraclizeQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee"); } else { @@ -409,8 +415,25 @@ contract KrakenPriceTicker is usingOraclize { ``` -You have to consider that your account will be debited for most of your Oraclize calls. If your contract is not covered with enough ETH, the query will fail. Depending on your contract logic you may want to check the price for your next query before it gets send. You can do this by calling `oraclize_getPrice` and check if it is higher than your current contract balance. If that's the case the `oraclize_query` will fail and you may want to handle it gracefully. You can also add a gaslimit parameter to the `oraclize_getPrice` function: `oraclize_getPrice(string datasource, uint gaslimit)`. Make sure that the custom gaslimit for `oraclize_getPrice` matches with the one you will use for `oraclize_query`. +Payment for Provable queries are debited directly from the contract that calls the `oraclize_query(...)'` function at the moment that function call is made. So - depending on your contract's logic - you may want to know ahead of time the price of your next query before making it. Provable provides a helper method to do just that: `oraclize_getPrice(string _datasource);`. + +Using this helper function, it is possible gracefully handle the scenario where your contract's balance has dropped below the cost of the query price. Otherwise, if a contract's ETH balance is insufficient to cover the query at the time the query is attempted, it will fail via: `revert('Error settling query payment');`. The `update();` function in the sample contract on the right demonstrates how to implement the `oraclize_getPrice()` helper function in order to check if a contracts balance is sufficient to cover the query cost. +The `oraclize_getPrice` function is overloaded and so can also accept a gas limit parameter: `oraclize_getPrice(string _datasource, uint256 _gasLimit);`. This allowing you to get accurate prices for queries that use a gas limit different from the `200,000` default. + + + +`oraclize_getPrice` can also accept an `address` parameter, allowing you to discover prices for queries for _any_ contract, rather than just only the contract that is actually calling: `oraclize_getPrice(string _datasource, address _contractAddress);`. + +Finally, `oraclize_getPrice` can accept all three of the aforementioned parameters in order to discover very specific query prices for any datasource, using any custom gas limit and for any desired contract: `oraclize_getPrice(string _datasource, uint256 _gasLimit, address _contractAddress);` + +All overloaded versions of the `oraclize_getPrice` helper function have the `view` visibility specifier and so are free for your contract to call. + + ### Mapping Query Ids From c99ea040dcb31dc1b8d4f2aa029a3498ac38fa9c Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 11:03:30 +0100 Subject: [PATCH 04/17] fix trailing whitespace/line endings --- source/includes/_ethereum.md | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index 00388369284..a4b99189492 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -8,7 +8,7 @@ The interaction between Oraclize and an Ethereum smart contract is asynchronous. * Firstly, in the most common case, a transaction executing a function of a smart contract is broadcasted by a user. The function contains a special instruction which manifest to Oraclize, who is constantly monitoring the Ethereum blockchain for such instruction, a request for data. * Secondly, according to the parameters of such request, Oraclize will fetch or compute a result, build, sign and broadcast the transaction carrying the result. In the default configuration, such transaction will execute the `__callback` function which should be placed in the smart contract by its developer: for this reason, this transaction is referred in the documentation as the Oraclize callback transaction. -As said in previous sections, one of the fundamental characteristics of Oraclize is the capability of returning data to a smart contract together with one or more proofs of authenticity of the data. The generation of an authenticity proof is optional and it is a contract-wide setting which must be configured by the smart contract developer before the request for data is initiated. Oraclize always recommends the use of authenticity proofs for production deployments. +As said in previous sections, one of the fundamental characteristics of Oraclize is the capability of returning data to a smart contract together with one or more proofs of authenticity of the data. The generation of an authenticity proof is optional and it is a contract-wide setting which must be configured by the smart contract developer before the request for data is initiated. Oraclize always recommends the use of authenticity proofs for production deployments. ## Quick Start @@ -41,7 +41,7 @@ contract ExampleContract is usingOraclize { oraclize_query("URL", "json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price"); } } -} +} ``` The most simple way to introduce the Ethereum - Oraclize integration, it is by showing a working example, such as the smart contract on the right. @@ -87,7 +87,7 @@ A request for data is called **query**. The `oraclize_query` is a function, inhe * or a `WolframAlpha` formula * or an `IPFS` multihash -The number and type of supported arguments depends from the data-source in use. Beside, few more code example will be shown and commented. The datasource, as well as the authenticity proof chosen, determine the fee which the contract has to pay to Oraclize. +The number and type of supported arguments depends from the data-source in use. Beside, few more code example will be shown and commented. The datasource, as well as the authenticity proof chosen, determine the fee which the contract has to pay to Oraclize. ### Schedule a Query in the Future @@ -344,7 +344,7 @@ When a smart contract requests for an authenticity proof, it **must** define a d The `oraclize_setProof` function expects the following format: `oraclize_setProof(proofType_ | proofStorage_ )` -Both proofType and proofStorage are byte constants defined in usingOraclize: +Both proofType and proofStorage are byte constants defined in usingOraclize: Available parameters for proofTypes are: @@ -481,12 +481,12 @@ It might occur that a callback function of a sent query gets called more than on ### Encrypted Queries Certain contexts, such as smart contracts on public blockchains, might require a level of privacy to protect data from public scrutiny. Developers can make encrypted Oraclize queries by encrypting a part (or all) of a query with the Oraclize public key. -The encrypted queries feature may be of interested to developers who want to deploy their blockchain applications of public networks. For example, if an application leverages data from an authenticated API, it would be dangerous to disclose the API key to anyway who is monitoring the public chain. +The encrypted queries feature may be of interested to developers who want to deploy their blockchain applications of public networks. For example, if an application leverages data from an authenticated API, it would be dangerous to disclose the API key to anyway who is monitoring the public chain. Oraclize therefore offers the possibility of encrypting the parameters contained in a query to Oraclize's public key: `044992e9473b7d90ca54d2886c7addd14a61109af202f1c95e218b0c99eb060c7134c4ae46345d0383ac996185762f04997d6fd6c393c86e4325c469741e64eca9` Only Oraclize will then be able to decrypt the request using its paired private key. -To encrypt the query, Oraclize provides a CLI tool, which can be found here. Alternatively, +To encrypt the query, Oraclize provides a CLI tool, which can be found here. Alternatively, The CLI command to encrypt an arbitrary string of text is then: `python encrypted_queries_tools.py -e -p 044992e9473b7d90ca54d2886c7addd14a61109af202f1c95e218b0c99eb060c7134c4ae46345d0383ac996185762f04997d6fd6c393c86e4325c469741e64eca9 "YOUR QUERY"` @@ -584,29 +584,29 @@ contract Calculation is usingOraclize { event calculationResult(uint _result); // General Calculation: ((NUMBER_1 + NUMBER_2) * MULTIPLIER) / DIVISOR - + function Calculation() { - oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); + oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); } function __callback(bytes32 myid, string result, bytes proof) { require (msg.sender == oraclize_cbAddress()); calculationResult(parseInt(result)); } - + function testCalculation() payable { sendCalculationQuery(NUMBER_1, NUMBER_2, MULTIPLIER, DIVISOR); // = 105 } - + function sendCalculationQuery(string _NUMBER1, string _NUMBER2, string _MULTIPLIER, string _DIVISOR) payable { if (oraclize.getPrice("computation") > this.balance) { LogNewOraclizeQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee"); } else { LogNewOraclizeQuery("Oraclize query was sent, standing by for the answer.."); - oraclize_query("computation",["QmZRjkL4U72XFXTY8MVcchpZciHAwnTem51AApSj6Z2byR", - _NUMBER1, - _NUMBER2, - _MULTIPLIER, + oraclize_query("computation",["QmZRjkL4U72XFXTY8MVcchpZciHAwnTem51AApSj6Z2byR", + _NUMBER1, + _NUMBER2, + _MULTIPLIER, _DIVISOR]); } } @@ -614,7 +614,7 @@ contract Calculation is usingOraclize { ``` Arguments can be passed to the package by adding parameters to the query array. They will be accessible from within the Docker instances as environmental parameters. -Currenty the API supports up to 5 inline arguments, including the IPFS Hash: +Currenty the API supports up to 5 inline arguments, including the IPFS Hash: `oraclize_query("computation",["QmZRjkL4U72XFXTY8MVcchpZciHAwnTem51AApSj6Z2byR", _firstOperand, _secondOperand, _thirdOperand, _fourthOperand]);` ```shell @@ -647,10 +647,10 @@ pragma solidity ^0.4.18; import "github.com/oraclize/ethereum-api/oraclizeAPI.sol"; contract Calculation is usingOraclize { - + event calculationResult(uint _result); event LogNewOraclizeQuery(string description); - + function Calculation() payable { oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); @@ -664,7 +664,7 @@ contract Calculation is usingOraclize { require (msg.sender == oraclize_cbAddress()); calculationResult(parseInt(result)); } - + function testCalculation( string _hash, string _number1, @@ -673,7 +673,7 @@ contract Calculation is usingOraclize { string _divisor, string _number3, string _number4) public payable { - + string[] memory numbers = new string[](7); numbers[0] = _hash; numbers[1] = _number1; @@ -682,10 +682,10 @@ contract Calculation is usingOraclize { numbers[4] = _divisor; numbers[5] = _number3; numbers[6] = _number4; - + sendCalculationQuery(numbers); } - + function sendCalculationQuery(string[] array) internal { if (oraclize.getPrice("computation") > this.balance) { LogNewOraclizeQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee"); From d0bdf1fa7ecf43adbb8ea42a9c80a58c0e916bd0 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 11:19:14 +0100 Subject: [PATCH 05/17] add datasources-as-bytes1 info --- source/includes/_ethereum.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index a4b99189492..dcf3d6951b3 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -851,5 +851,33 @@ contract proofShieldExample is usingOraclize { } ``` +### Byte Datasources + +As a more advanced feature, Provable are providing all datasource `strings` as type `bytes1` as well as `strings`. The strings remain more readable (`URL`, `Random` and so on…) in Provable queries, but as with any string-related manipulation in Solidity, using them costs more gas-wise. As such, by offering the same set of datasources as a `bytes1` equivalent, advanced users may choose to declare their datasource in this manner instead and thus benefit from cheaper query gas-costs. + + + +``` javascript + +// Datasource strings and their `bytes1` equivalents: + +|---------------------------| +| `string` | `bytes1` | +|---------------------------| +| 'URL' | 0xFF | +| 'IPFS' | 0xFB | +| 'swarm' | 0xF8 | +| 'nested' | 0xFA | +| 'Random' | 0xFE | +| 'Blockchain' | 0xF9 | +| 'computation' | 0xFD | +| 'WolframAlpha' | 0xFC | +|---------------------------| + + +``` + ### More Examples More complete, complex examples are available on the dedicated Github repository: https://github.com/oraclize/ethereum-examples From 385e5de5750851285840b1a28e83c49d2d3e62a4 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 12:36:18 +0100 Subject: [PATCH 06/17] fix proofshield section formatting err --- source/includes/_ethereum.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index dcf3d6951b3..506e1eed1ae 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -798,16 +798,7 @@ The ProofShield is still EXPERIMENTAL, please DO NOT use it in production (yet). The ProofShield enables smart contracts to verify on-chain the authenticity proofs provided by Oraclize, this ensures that the authenticity of the data received is verified before going ahead and using the data. - -To enable the ProofShield it is enough to set it via the `oraclize_setProof` function like you see in the following code: - - -```javascript - - oraclize_setProof(proofType_Android_v2 | proofShield_Ledger); - -```` - +To enable the ProofShield it is enough to set it via the `oraclize_setProof` function like you see in the following code: `oraclize_setProof(proofType_Android_v2 | proofShield_Ledger);` Once the ProofShield is enabled, the received proof will not be the raw Authenticity Proof, but the ProofShield proof instead: some functions are provided so that the ProofShield proof can be verified on-chain. In order to verify it, you need to call from within the `__callback` method the function `oraclize_proofShield_proofVerify__returnCode(queryId, result, proof)` and ensure that it returns 0. From 613888d7d182668092e766b4e0e9e8a810c8839f Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Mon, 29 Apr 2019 12:36:33 +0100 Subject: [PATCH 07/17] adds section on cached queries --- source/includes/_ethereum.md | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index 506e1eed1ae..9c284803b3d 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -566,6 +566,93 @@ To protect the plaintext queries, an Elliptic Curve Integrated Encryption Scheme * An Elliptic Curve Diffie-Hellman Key Exchange (ECDH), which uses secp256k1 as curve and ANSI X9.63 with SHA256 as Key Derivation Function. This algorithm is used to derive a shared secret from the Oraclize public key and ad-hoc, randomly generated developer private key. * The shared secret is used by an AES-256 in Galois Counter Mode (GCM), an authenticated symmetric cipher, to encrypt the query string. The authentication tag is 16-bytes of length and the IV is chosen to be '000000000000' (96 bits of length). The IV can be set to the zero byte-array because each shared secret is thrown-away and use only once. Every time the encryption function is called a new developer private key is re-generated. The final ciphertext is the concatenation of the encoded point (i.e the public key of the developer), the authentication tag and the encrypted text. +### Cached Queries + +It is common for oracle-leveraging smart-contracts to be relatively simple in their external datasource needs. Frequently, a contract will have a static query that always calls the same endpoint with the same parameters. In such cases, Provable have implemented a method whereby queries can be _cached_ in order to make large gas savings when making the query. The gas-savings can be upwards of 50% of the original gas price of the query. + +To enable query caching, a contract must first make a standard Provable query using whichever datasource & parameters are required, and then save the `bytes32` query ID that Provable returns: `bytes32 cachedQueryID = oraclize_query(, );`. Next, a contract should enable caching of that specific query, using its ID, by calling: `oraclize_requestQueryCaching(cachedQueryId);`. + +Thereafter, a contract may make a _new_ query using the cached query’s parameters via: `oraclize_queryCached();`. This will return a _new_ queryID in order for the query to be tracked within your contract’s context. The new query made will have exactly the parameters of the query which was originally cached by the contract. + +See the example to the right for a contract that sets up and then uses cached queries in a recursive manner in order to benefit from the large gas savings when using a single, static query. + + + +```javascript + +pragma solidity >= 0.5.0 < 0.6.0; + +contract RecursiveCachedQueryExample is usingOraclize { + + bytes32 cachedQueryID; + string public priceETHXBT; + + event LogNewKrakenPriceTicker(string price); + event LogNewOraclizeQuery(string description); + + constructor() + payable + public + { + updateAndRequestQueryCaching(); // Note: Set the recursive queries going on contract creation... + } + /** + * + * @dev Notice here that we make a normal Provable query and save the + * returned query ID, which is then used to request caching of the + * specific query using that ID just saved. + * + */ + function updateAndRequestQueryCaching() + public + payable + { + emit LogNewOraclizeQuery("Oraclize query was sent, standing by for the answer..."); + cachedQueryID = oraclize_query( + "URL", + "json(https://api.kraken.com/0/public/Ticker?pair=ETHXBT).result.XETHXXBT.c.0" + ); + oraclize_requestQueryCaching(cachedQueryID); + } + /** + * + * @dev Now here we are making the *same* Provable query as above but by + * simply calling `oraclize_queryCached(...)`. Notice too how we + * provide to it the cost of the query which is a required parameter. + * + */ + function updateCached() + public + payable + { + emit LogNewOraclizeQuery("Oraclize query was sent, standing by for the answer..."); + oraclize_queryCached(oraclize_getPrice("URL")); + } + /** + * + * @dev When the Provable service returns our result and calls this + * callback, we call our *cached* version of the update function, + * thus continuing the asynchronous recursion. + * + */ + function __callback( + bytes32 myid, + string memory result, + bytes memory proof + ) + public + { + require(msg.sender == oraclize_cbAddress()); + updateCached(); + priceETHXBT = result; + emit LogNewKrakenPriceTicker(priceETHXBT); + } +} + +``` + ### Computation Data Source #### Passing Arguments to the Package From 57a6c46afdf5fdb4f34c615943dde337be2e3ca7 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Tue, 30 Apr 2019 16:45:37 +0100 Subject: [PATCH 08/17] adds section on ERC20 token payments --- source/includes/_ethereum.md | 162 ++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index 9c284803b3d..ed1aa0676b4 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -58,8 +58,8 @@ To ease development, Oraclize doesn't charge a contract for its first request of Only the first query is free. Ensure that the contract has a sufficient ETH balance to pay the following queries. The contract gets automatically charged on the `oraclize_query` call but fails if the balance is insufficient. - ### Simple Query + ```javascript // This code example will ask Oraclize to send as soon as possible // a transaction with the primary result (as a string) of the given @@ -427,7 +427,7 @@ When using a custom gas limit, to correctly calculate your contract's _next_ que `oraclize_getPrice` can also accept an `address` parameter, allowing you to discover prices for queries for _any_ contract, rather than just only the contract that is actually calling: `oraclize_getPrice(string _datasource, address _contractAddress);`. -Finally, `oraclize_getPrice` can accept all three of the aforementioned parameters in order to discover very specific query prices for any datasource, using any custom gas limit and for any desired contract: `oraclize_getPrice(string _datasource, uint256 _gasLimit, address _contractAddress);` +Finally, `oraclize_getPrice` can accept a combination of parameters allowing the discovery of very specific query prices for any datasource combined with any proof-type, using any custom gas limit, any custom gas price and for any desired contract: `oraclize_getPrice(string _datasource, uint256 _gasLimit, uint256 _gasPrice, bytes1 _proofType);` All overloaded versions of the `oraclize_getPrice` helper function have the `view` visibility specifier and so are free for your contract to call. @@ -435,6 +435,37 @@ All overloaded versions of the `oraclize_getPrice` helper function have the `vie Note that the first query to the Provable service is _free_, and so the first call to `oraclize_getPrice` from a contract with a gas limit and/or gas price that is _less than or equal_ to the default values will result in the function _correctly_ returning `0`. +```javascript + +/** + * + * @notice All oraclize_getPrice(...) function overloads: + * + */ + +// For datasource prices... +oraclize_getPrice(string datasource); +oraclize_getPrice(bytes1 datasource); + +// For prices involing custom gas limits... +oraclize_getPrice(string datasource, uint256 _gasLimit); +oraclize_getPrice(bytes1 datasource, uint256 _gasLimit); + +// For query prices for addresses other than the calling contract... +oraclize_getPrice(string datasource, address _address); +oraclize_getPrice(bytes1 datasource, address _address); + +// For prices involving custom gas limits and custom gas prices... +oraclize_getPrice(string datasource, uint256 _gasLimit, uint256 _gasPrice); +oraclize_getPrice(bytes1 datasource, uint256 _gasLimit, uint256 _gasPrice); + +// For prices involving different datasource & prooftype combinations... +oraclize_getPrice(string datasource, uint256 _gasLimit, uint256 _gasPrice, bytes1 _proofType); +oraclize_getPrice(bytes1 datasource, uint256 _gasLimit, uint256 _gasPrice, bytes1 _proofType); + + +``` + ### Mapping Query Ids ```javascript @@ -871,9 +902,136 @@ The random datasource is currently available on the Ethereum mainnet and on all The `oraclize_newRandomDSQuery` can be used for different kind of interactions, but the security can be incresed further by additing additional commitment data to the request. For example, for two party interactions, the `oraclize_newRandomDSQuery` can be modified as showon the side to include the sender address and the value send along as commitment data. This more strongly commitment the request for random bytes to current party, which are assumed to have a stake in the contract, making it impossible for miners to replay transactions on potential forks or reorg of the current chain. #### Multi-Party Interactions + In the case of multi-party interactions, such as voting schemes or lotteries, the commitment data can should include all participants addresses, to ensure that the transaction cannot be replayed by a miner on a fork or a reorged chain where a participant didn't put a stake. +### ERC20 Token Payments + +```javascript + +/** + * + * @dev Provable helper functions for managing ERC20 Payments + * + */ + +// Set payment method to token existing at +oraclize_setCustomTokenPayment(address ); + +// Approve an allowance of the token for the Provable service: +oraclize_approveTokenAllowance( + address , + uint256 +); + +// Or combine the above into a single call to this function: +oraclize_setAndApproveTokenAllowance( + address, + uint256 +); + +// Get the price of a query in tokens: +oraclize_getPriceERC20(uint256 ); + +// Revert back to paying with ETH and revoke the approved token amount: +oraclize_unsetAndRevokeCustomPayment(); +``` + +Provable supports ERC20 token payments. In order to make queries using a token as payment rather than ETH, you must somewhere in your contract call: `oraclize_setCustomTokenPayment(address );`, where `` is any of those existing on the whitelist of supported tokens. + +Once called, subsequent queries made by a contract will be paid for in the specified tokens. Query prices are exactly the same as when paying in ETH, but will be converted to their token equivalent automatically. + + + +The same as when paying for queries with ETH, when paying with a token you will need to ensure your contract has a sufficient balance of that token to cover the query cost, and that a balance has been `approved` to be used by the Provable connector contract which it is calling. (See the ERC20 token __[specification here](https://theethereum.wiki/w/index.php/ERC20_Token_Standard#Approve_And_TransferFrom_Token_Balance)__ for more information on token approval.) + +To make this simpler, the Provable API provides various helper functions which you can see on the right hand side. + + + +Just as when __[paying for queries using ETH](http://docs.oraclize.it/#ethereum-best-practices-pre-calculating-the-query-price)__, when paying using a token it is also possible to pre-calculate a query-price via: `oraclize_getPriceERC20();`. This returns the next query price expressed in units of the token that the your contract has set as its `customTokenPayment`. + +Additional parameters may be passed to get prices for more specific query types. See the information to the right for a full list of `oraclize_getPriceERC20` function overloads. All overloaded versions of the `oraclize_getPrice` helper function have the `view` visibility specifier and so are free for your contract to call. + + + +In the case of a contract specifying a token payment, but sending enough ETH to cover the cost of the query, ETH will be used as payment rather than the token. + +Should a contract wish to switch back to using ETH to pay for queries, rather than a token, it can do so by calling: `oraclize_unsetAndRevokeCustomPayment();`. This will unset the custom token payment option, and reset the allowance to the Provable contract to zero. + +```javascript + +/** + * + * @dev The complete set of oraclize_getPriceERC20() overloads follow, + * allowing for price discovery of any query type. + * + */ + +// For datasource prices... +oraclize_getPriceERC20(string _datasource); +oraclize_getPriceERC20(bytes1 _datasource); + +// For prices involving custom gas limits... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit); +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit); + +// For query prices for addresses other than the calling contract... +oraclize_getPriceERC20(string _datasource, address _contractAddress); +oraclize_getPriceERC20(bytes1 _datasource, address _contractAddress); + +// For query prices involving different contracts w/ custom gas limits... +oraclize_getPriceERC20(string _datasource, address _contractAddress, uint256 _gasLimit); +oraclize_getPriceERC20(bytes1 _datasource, address _contractAddress, uint256 _gasLimit); + +// For prices involving custom gas limits and custom gas prices... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit, uint256 _gasPrice); +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit, uint256 _gasPrice); + +// For prices involving different _datasource & prooftype combinations... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit, uint256 _gasPrice, bytes1 _proofType); +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit, uint256 _gasPrice, bytes1 _proofType); + +/** + * + * @dev Or have the same set of oraclize_getPriceERC20 overloads but which + * can be used for getting prices in *any* token, rather than only that + * which your contract has elected to use. + * + */ + +// For datasource prices in given token's units... +oraclize_getPriceERC20(address _tokenAddress, string _datasource) +oraclize_getPriceERC20(address _tokenAddress, bytes1 _datasource) + +// For prices in the given token's units & involving custom gas limits... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit, address _tokenAddress) +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit, address _tokenAddress) + +// For query prices in the given token's units & for addresses other than the calling contract... +oraclize_getPriceERC20(string _datasource, address _contractAddress, address _tokenAddress) +oraclize_getPriceERC20(bytes1 _datasource, address _contractAddress, address _tokenAddress) + +// For prices in the given token's units & involving different contracts w/ custom gas limits... +oraclize_getPriceERC20(string _datasource, address _contractAddress, uint256 _gasLimit, address _tokenAddress) +oraclize_getPriceERC20(bytes1 _datasource, address _contractAddress, uint256 _gasLimit, address _tokenAddress) + +// For prices in a given token's units & involving different datasource & prooftype combinations... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit, uint256 _gasPrice, address _tokenAddress) +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit, uint256 _gasPrice, address _tokenAddress) + +// For prices in a given token's units & involving different datasource & prooftype combinations... +oraclize_getPriceERC20(string _datasource, uint256 _gasLimit, uint256 _gasPrice, byte _proofType, address _tokenAddress) +oraclize_getPriceERC20(bytes1 _datasource, uint256 _gasLimit, uint256 _gasPrice, byte _proofType, address _tokenAddress) + +``` ### ProofShield From 8e423cb8afc40140b72e3efc08253869c81a2f74 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Thu, 30 May 2019 15:14:53 +0100 Subject: [PATCH 09/17] integrate @d-nice suggested change Co-Authored-By: D-Nice --- source/includes/_ethereum.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index ed1aa0676b4..af775b481f9 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -286,7 +286,7 @@ Just like a normal query, any over-payment is refunded, but always to the _final - The first is that the refund will _always_ go to the final calling contract, and so if the call for a rebroadcast is proxied via another contract, the refund will always be made to the that implements the API, and not necessarily to the contract which initiated and paid for the call. -- The second caveat is that the final calling contract will also require a payable `fallback()` function in order to receive refunds in such cases. Absent this function, the refund attempt will cause the query to `revert();`. +- The second caveat is that the final calling contract will also require a payable `fallback()` function in order to receive refunds in such cases. If the payable fallback is omitted, any refund attempt will cause the query to `revert();`. Due to the preceding caveats, it is strongly recommended that queries be paid for using their exact cost, which can be calculated via: `oraclize_getRebroadcastCost(, );` From a7b05aadc2526a20adf29813f9fed5580d93e984 Mon Sep 17 00:00:00 2001 From: Greg Kapka Date: Thu, 30 May 2019 15:25:20 +0100 Subject: [PATCH 10/17] point out that either contract or caller can pay for query --- source/includes/_ethereum.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/includes/_ethereum.md b/source/includes/_ethereum.md index af775b481f9..0b38fa8da4f 100644 --- a/source/includes/_ethereum.md +++ b/source/includes/_ethereum.md @@ -415,11 +415,11 @@ contract KrakenPriceTicker is usingOraclize { ``` -Payment for Provable queries are debited directly from the contract that calls the `oraclize_query(...)'` function at the moment that function call is made. So - depending on your contract's logic - you may want to know ahead of time the price of your next query before making it. Provable provides a helper method to do just that: `oraclize_getPrice(string _datasource);`. +Payment for Provable queries are debited directly from the contract that calls the `oraclize_query(...)'` function at the moment that function call is made. In order for that to succeed, either the contract itself needs to hold a balance of ETH, or the contract needs to implement logic to burden the contract-caller to supply the ETH. Either way, you may want to know ahead of time the price of the next query before making it. Provable provides a helper method to do just that: `oraclize_getPrice(string _datasource);`. -Using this helper function, it is possible gracefully handle the scenario where your contract's balance has dropped below the cost of the query price. Otherwise, if a contract's ETH balance is insufficient to cover the query at the time the query is attempted, it will fail via: `revert('Error settling query payment');`. The `update();` function in the sample contract on the right demonstrates how to implement the `oraclize_getPrice()` helper function in order to check if a contracts balance is sufficient to cover the query cost. +If your contract is paying for queries from its own balance, it is possible gracefully handle the scenario where that balance has dropped below the cost of the query price using this helper function. Otherwise, if the balance is insufficient to cover the query at the time the query is attempted, it will fail via: `revert('Error settling query payment');`. The `update();` function in the sample contract on the right demonstrates how to implement the `oraclize_getPrice()` helper in order to perform this balance check before making a Provable query. -The `oraclize_getPrice` function is overloaded and so can also accept a gas limit parameter: `oraclize_getPrice(string _datasource, uint256 _gasLimit);`. This allowing you to get accurate prices for queries that use a gas limit different from the `200,000` default. +The `oraclize_getPrice` helper function is overloaded and so can also accept a gas limit parameter: `oraclize_getPrice(string _datasource, uint256 _gasLimit);`. This allowing you to get accurate prices for queries that use a gas limit different from the `200,000` default.