Я сохраняю стоимость продукта в долларах США в контракте.mapping (string => uint256) productUSD;
Например, если это 52 доллара, я бы сохранил его какproductUSD[_product] = 52;
Теперь, когда люди платят в ETH, я хочу убедиться, что они отправили правильную конвертированную сумму.
то есть0.013 ETH
Chainlink getThePrice()
возвращает последнюю ETH/USD
цену и обнаружил, что она возвращается вот так.price = 348365740274
function getThePrice() public view returns (int) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = priceFeed.latestRoundData();
return price;
}
Простая математика, я могу отбросить 8 знаков после запятой 348365740274
и использовать их 3483
, чтобы получить преобразованную сумму ETH.
то есть52 / 3483 = 0.0149296583405111 ETH
348365740274
require(msg.value >= ...)
Что касается ценовых каналов цепочки, пары ETH (USD/ETH, AAVE/ETH, UNI/ETH и т. д.) имеют 18 знаков после запятой, а пары без ETH (ETH/USD и т. д.) — 8 знаков после запятой. Источник
Целочисленное деление солидности автоматически округляется до 0. ( Справочник по документации ), поэтому вы можете сделать price/10**8
округленное целое число для делимого, представляющего 8 знаков после запятой.
Чтобы убедиться, что значение, отправленное с транзакцией, больше некоторого порогового значения при сравнении ETH с долларами США, вы должны разделить минимальное требуемое значение в долларах США на доллары США за ETH, например:
int min_required = 50; // minimum required in USD
int _price = getThePrice() / 10 ** 8; // price of 1 ether in USD
require(msg.value >= min_required / _price, "NOT ENOUGH ETHER");
вы можете не использовать переменные для экономии газа и использовать значения напрямую, это просто для более ясного объяснения.
Если вы используете версию компилятора Solidity ниже 0.8.x, используйте SafeMath, чтобы позаботиться о целочисленном переполнении и потере значимости.
Нет, я не думаю, что решение hack3r_Om работает. Рассмотрим мой пример:
require(msg.value >= min_required / _price, "NOT ENOUGH ETHER");
никогда не подведет, потому что 50/2000 = 0 в солидности.
Мое решение, согласно учебнику PatrickAlpha , вы должны умножить min_required и значение, возвращаемое ценой, на некоторое число перед делением, чтобы оно не округлялось. Это мой пример контракта:
contract Test{
uint256 minRequiredUSD;
uint256 etherPriceUSD;
uint256 public minRequiredEther;
constructor() {
minRequiredUSD = 50*10**18; // multiply your minRequired to 10**18
etherPriceUSD = 2000*10**18; // multiply your etherPrice to 10**18
// this means (50*10*18)/2000, it converts your minReqiredEther to wei first
// before divide. The result is 25*10**15 wei.
minRequiredEther = (minRequiredUSD*10**18)/etherPriceUSD;
}
event ReceivedEther(uint256 _amount);
function donate() public payable {
require(msg.value > minRequireEther);
emit ReceivedEther(msg.value);
}
}
Пол Разван Берг