Как посчитать актуальную цену токена в USD?

Владельцы ICO устанавливают стоимость токена в USD. При этом внутри смарт-контракта мы работаем с ETH. Для того чтобы правильно начислять токены по актуальному курсу можно использовать сервис Oraclize.it

Чтобы отправить запрос к внешнему сайту и получить ответ об актуальном курсе эфира, будем использовать решение от компании Oraclize.it. Это удобное решение позволяет отправлять запросы к внешним ресурсам в формате URL, WolframAlpha, IPFS и другим.
Решение является платным и списывает деньги с баланса вашего контракта при запросе. На 30.09.2017 стоимость запроса к URL составляет 0.1$. Важное преимущество решения — встроенные библиотеки для преобразования полученных данных.

Для этого импортируем в код контракта решение oraclizeAPI.

import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";

создаем необходимые переменные:

string public USDETH;
event updatedPrice(string price);
event newOraclizeQuery(string description);

Далее с payable функции нашего контракта вызываем updatePrice();

function ExampleContract() payable {
updatePrice();
}

В updatePrice() происходит сравнение баланса вашего контракта и стоимости вашего запроса. Если на балансе достаточно средств, то отправляется запрос и получаем обработанный результат запроса.

function updatePrice() payable {
if (oraclize_getPrice("URL") > this.balance) {
newOraclizeQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee");
} else {
newOraclizeQuery("Oraclize query was sent, standing by for the answer..");
oraclize_query("URL", "json(http://api.fixer.io/latest?symbols=USD,ETH).rates.ETH");
}
}

Ниже пример контракта с поддержкой запроса и обновлением стоимости.
Обратите внимание, пример не будет работать, если ваша тестовая среда разработки не поддерживает подключение файлов github. В этом случае для тестирования добавьте необходимое решение в свой код самостоятельно.


pragma solidity ^0.4.11;
import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";

contract ExampleContract is usingOraclize {

string public USDETH;
event updatedPrice(string price);
event newOraclizeQuery(string description);

function ExampleContract() payable {
updatePrice();
}

function __callback(bytes32 myid, string result) {
if (msg.sender != oraclize_cbAddress()) throw;
USDETH = result;
updatedPrice(result);
}

function updatePrice() payable {
if (oraclize_getPrice("URL") > this.balance) {
newOraclizeQuery("Oraclize query was NOT sent, please add some ETH to cover for the query fee");
} else {
newOraclizeQuery("Oraclize query was sent, standing by for the answer..");
oraclize_query("URL", "json(http://api.fixer.io/latest?symbols=USD,ETH).rates.ETH");
}
}
}