conversión de precios usando el precio ETHUSD de chainlink

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/USDprecio 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 348365740274y usarlos 3483para obtener una cantidad ETH convertida

es decir52 / 3483 = 0.0149296583405111 ETH

  1. ¿Cómo calculo esto en solidez? no estoy seguro de cómo quitar decimales de348365740274
  2. ¿Cómo verifico que el usuario haya enviado la cantidad correcta de eth? es decirrequire(msg.value >= ...)
Es posible que necesite una biblioteca matemática de punto fijo. Ver mi hilo ¿ Qué bibliotecas matemáticas de punto fijo o flotante están disponibles en Solidity? .

Respuestas (2)

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**8para 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:

  • El precio del éter en USD es de 2000 dólares. Así que el precio de alimentación te dará 2000*10**8.
  • Ahora, si divide el valor devuelto por 10**8, obtendrá 2000.
  • Su min_required es de 50 dólares, si convierte esos 50 dólares a ether por 50/2000, la solidez le dará cero porque no le gustan los decimales. lo que significa que

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);
}

}