Currently, when I call
oraclize_getPrice("random", 400000);
I get back
8000000000000000
on rinkeby. That'd be over 2$ USD if on the mainnet and also looks oddly round. Why is this so high?
Your oraclize_getPrice("random", 400000)
returns 8000000000000000 because it calculates gasLimit * gasPrice
with the given gasLimit of 400000 and the default gasPrice of 20 Gwei.
The total cost is calculated by: $0.05 +( call of your __callback() + execution gas of the __callback()) * gasPrice
However, in practice it's calculated by $0.05 + CUSTOM_GAS_LIMIT * CUSTOM_GAS_PRICE
whereby CUSTOM_GAS_LIMIT should be enough to execute your __callback()
and CUSTOM_GAS_PRICE high enough to have the transaction be mined in time.
See below how to influence these values:
There are three factors affecting the "real" price of using oraclize:
__callback()
function. This function is called by Oraclize and must be paid by your contract.__callback()
. These 200k are paid by your contract. However, unused gas will be returned to Oraclize - not to your contract! Try and error to find a close value and use it in oraclize_newRandomDSQuery(delay, N, CUSTOM_GASLIMIT)
and oraclize_getPrice("random", CUSTOM_GASLIMIT)
.
This value MUST BE >= than the value determined in (1).oraclize_setCustomGasPrice(customGasPrice)
. I suggest not to hardcode that value because the requirements may vary in times of high network load. If your gasPrice is too low, the oraclize callback to your contract may take very long or may even never be mined.Here's an example how I handle these values:
pragma solidity ^0.4.24;
import "oraclize-api/contracts/usingOraclize.sol";
contract MyContract is usingOraclize {
// USD Cent value of 1 ether. Init with non-zero value.
uint256 public ethusd = 1;
// Sold out / sale active?
bool public soldOut = false;
// Oracle active?
bool public oracleActive = false;
// Delay between autonomous oraclize requests
uint256 public oracleInterval;
// Gas price for oraclize callback transaction. 5 Gwei
uint256 public oracleGasPrice = 5000000000;
// Gas limit for oraclize callback transaction
// Unused gas is returned to oraclize.
uint256 public oracleGasLimit = 100000;
constructor(uint _oracleInterval, uint _oracleGasPrice) public {
require(_oracleInterval > 0);
require(_oracleGasPrice > 0);
oracleInterval = _oracleInterval;
oracleGasPrice = _oracleGasPrice;
oraclize_setCustomGasPrice(_oracleGasPrice);
}
// Activate ethusd oracle and load contract with ETH
function activateOracle() external payable {
oracleActive = true;
requestEthUsd(0);
}
/**
* @dev Request ETHUSD rate from oraclize
* @param _delay in seconds when the request should be scheduled from now on
*/
function requestEthUsd(uint _delay) internal {
if (oracleActive && !soldOut) {
if (oraclize_getPrice("URL") > address(this).balance) {
oracleActive = false;
} else {
if (_delay == 0) {
oraclize_query("URL", "json(https://api.gdax.com/products/ETH-USD/ticker).price", oracleGasLimit);
} else {
oraclize_query(_delay, "URL", "json(https://api.gdax.com/products/ETH-USD/ticker).price", oracleGasLimit);
}
}
}
}
/**
* @dev Called by oraclize.
*/
function __callback(bytes32 myid, string result) public {
if (msg.sender != oraclize_cbAddress()) revert();
ethusd = parseInt(result, 2);
requestEthUsd(oracleInterval);
}
/**
* @dev Public function to set the oracle gas price.
*/
function setOracleGasPrice(uint256 _gasPrice) external {
require(_gasPrice > 0, "Gas price must be a positive number.");
oraclize_setCustomGasPrice(_gasPrice);
oracleGasPrice = _gasPrice;
}
/**
* @dev Public function to set the oracle gas limit.
*/
function setOracleGasLimit(uint256 _gasLimit) external {
require(_gasLimit > 0, "Gas limit must be a positive number.");
oracleGasLimit = _gasLimit;
}
/**
* @dev Public function to set the oracle query interval.
*/
function setOracleInterval(uint256 _interval) external {
require(_interval > 0, "Interval must be > 0");
oracleInterval = _interval;
}
}
This way you're able to apply new values even after contract deployment. The cost of my "URL" query has been lowered from $1.20 to $0.13.
NB: you should make your contract ownable and limit access to some of the above functions to the contract owner.
$0.254 +( call of your __callback() + execution gas of the __callback()) * gasPrice
. But since oraclize does not know how much gas is needed in total, you have to deliver a close value by your own.