Preisumrechnung unter Verwendung des Kettenglied-ETHUSD-Preises

Ich speichere den USD-Wert eines Produkts im Vertrag.mapping (string => uint256) productUSD;

Wenn es zum Beispiel 52 $ kostet, würde ich es speichern alsproductUSD[_product] = 52;

Wenn Leute jetzt in ETH bezahlen, möchte ich sicherstellen, dass sie einen korrekten umgerechneten Betrag eingeschickt haben.

dh0.013 ETH

Chainlink getThePrice()gibt den neuesten ETH/USDPreis zurück und stellte fest, dass er so zurückkehrte.price = 348365740274

    function getThePrice() public view returns (int) {
        (
            uint80 roundID, 
            int price,
            uint startedAt,
            uint timeStamp,
            uint80 answeredInRound
        ) = priceFeed.latestRoundData();
        return price;
    }

Einfache Mathematik, ich kann 8 Dezimalstellen weglassen 348365740274und verwenden 3483, um einen umgerechneten ETH-Betrag zu erhalten

dh52 / 3483 = 0.0149296583405111 ETH

  1. Wie berechne ich das in Solidität? nicht sicher, wie man Dezimalstellen löscht348365740274
  2. Wie kann ich überprüfen, ob der Benutzer den korrekten Eth-Betrag gesendet hat? dhrequire(msg.value >= ...)
Möglicherweise benötigen Sie eine Festkomma-Mathematikbibliothek. Siehe meinen Thread Welche mathematischen Bibliotheken mit festen oder Gleitkommazahlen sind in solidity verfügbar? .

Antworten (2)

In Bezug auf Chainlink-Preisfeeds haben ETH-Paare (USD/ETH, AAVE/ETH, UNI/ETH usw.) 18 Dezimalstellen, während Nicht-ETH-Paare (ETH/USD usw.) 8 Dezimalstellen haben. Quelle

Solidity Integer Division rundet automatisch in Richtung 0 abprice/10**8 .

Um zu überprüfen, ob der mit der Transaktion gesendete Wert größer als ein bestimmter Schwellenwert ist, wenn ETH mit USD verglichen wird, würden Sie den erforderlichen Mindestwert in USD durch USD pro ETH teilen, zum Beispiel:

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

Sie können die Verwendung von Variablen weglassen, um Gas zu sparen, und Werte direkt verwenden, dies dient nur einer klareren Erklärung.

Wenn Sie eine Solidity-Compiler-Version unter 0.8.x verwenden, verwenden Sie SafeMath, um sich um Ganzzahlüberlauf und -unterlauf zu kümmern

Nein, ich glaube nicht, dass die Lösung von hack3r_Om funktioniert. Betrachten Sie mein Beispiel:

  • Der Etherpreis in USD beträgt 2000 Dollar. Der Pricefeed gibt Ihnen also 2000 * 10 ** 8.
  • Wenn Sie nun den zurückgegebenen Wert durch 10**8 teilen, erhalten Sie 2000.
  • Ihr min_required beträgt 50 Dollar, wenn Sie diese 50 Dollar bis 50/2000 in Ether umwandeln, gibt Ihnen die Solidität null, weil sie keine Dezimalzahlen mag. Was bedeutet die

require(msg.value >= min_required / _price, "NOT ENOUGH ETHER");

wird niemals scheitern, denn 50/2000 = 0 in Solidität.

Meine Lösung ist laut PatrickAlphas Tutorial , dass Sie Ihren min_required und den von pricefeed zurückgegebenen Wert vor dem Teilen mit einer Zahl multiplizieren müssen, damit er nicht gerundet wird. Das ist mein Mustervertrag:

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

}