Estoy almacenando el valor en USD de un producto en el contrato.mapping (string => uint256) productUSD;
Por ejemplo, si son $52, los guardaría comoproductUSD[_product] = 52;
Ahora, cuando las personas pagan en ETH, quiero asegurarme de que envíen una cantidad convertida correcta.
es decir0.013 ETH
Chainlink's getThePrice()
devuelve el último ETH/USD
precio y descubrió que volvía así.price = 348365740274
function getThePrice() public view returns (int) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = priceFeed.latestRoundData();
return price;
}
Matemáticas simples, puedo eliminar 8 decimales 348365740274
y usarlos 3483
para obtener una cantidad ETH convertida
es decir52 / 3483 = 0.0149296583405111 ETH
348365740274
require(msg.value >= ...)
En lo que respecta a los precios de los enlaces de cadena, los pares ETH (USD/ETH, AAVE/ETH, UNI/ETH, etc.) tienen 18 decimales, mientras que los pares que no son ETH (ETH/USD, etc.) tienen 8 decimales. Fuente
La división de enteros de solidez se redondea automáticamente hacia 0. ( Referencia de documentos ), por lo que puede hacer price/10**8
para redondear el entero para el dividendo que representa 8 decimales.
Para verificar que el valor enviado con la transacción es mayor que algún umbral cuando ETH se compara con USD, dividiría el valor mínimo requerido en USD con USD por ETH, por ejemplo:
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");
puede omitir el uso de variables para ahorrar gasolina y usar valores directamente, esto es solo para una explicación más clara.
Si está utilizando una versión del compilador de solidity inferior a 0.8.x, utilice SafeMath para encargarse del desbordamiento y subdesbordamiento de enteros.
No, no creo que la solución de hack3r_Om funcione. Considera mi ejemplo:
require(msg.value >= min_required / _price, "NOT ENOUGH ETHER");
nunca fallará, porque 50/2000 = 0 en solidez.
Mi solución es, de acuerdo con el tutorial de PatrickAlpha , debe multiplicar su min_required y el valor devuelto de pricefeed a algún número antes de dividir, para que no se redondee. Este es mi contrato de ejemplo:
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);
}
}
Pablo Razvan Berg