Wie schätzt man die Gaskosten?

Ich habe eine Funktion, die ein Array durchläuft, was viel Benzin kosten könnte. Aber ich möchte trotzdem die geschätzten Benzinkosten testen und dann entscheiden, ob ich das Design beibehalten soll oder nicht.

function giveAwayDividend(uint amount) onlyOwner payable {
for(uint i=0;i<size();i++){
    customerAddress[i].call.value((balances[customerAddress[i]] * amount * 100) / totalSupply)();
}}

Wenn ich auf Testnet teste, muss ich manuell über 1.000 Benutzerkonten erstellen und jedem von ihnen ein Token schicken, was dumm erscheint. Gibt es eine bessere Möglichkeit, die Gaskosten zu berechnen? Wenn die Kosten beispielsweise linear sind, könnte ich die Kosten für einen Kunden berechnen und dann mit der Anzahl der Kunden multiplizieren. Die Frage ist, ich glaube nicht, dass es linear ist. Kann jemand etwas Licht ins Dunkel bringen?

Antworten (2)

Mit Truffle und testrpc . Es ist eigentlich ziemlich einfach, eine Entwicklungsumgebung zu erstellen und verschiedene Anwendungsfälle zu testen.

Für die Gasschätzung basiert es hauptsächlich auf nativen Web3-Funktionen:

  1. Sie können den Gaspreis (in wei) mit abrufenweb3.eth.getGasPrice

  2. Die Funktion estimateGasgibt die Gasschätzung für eine Funktion (mit den übergebenen Parametern)

  3. Multiplizieren Sie die Anzahl der Gase mit dem Gaspreis , um die Schätzung der Gaskosten zu erhalten .

Zum Beispiel

var TestContract = artifacts.require("./Test.sol");

// Run unit tests to populate my contract
// ...
// ...

// getGasPrice returns the gas price on the current network
TestContract.web3.eth.getGasPrice(function(error, result){ 
    var gasPrice = Number(result);
    console.log("Gas Price is " + gasPrice + " wei"); // "10000000000000"

    // Get Contract instance
    TestContract.deployed().then(function(instance) {

        // Use the keyword 'estimateGas' after the function name to get the gas estimation for this particular function 
        return instance.giveAwayDividend.estimateGas(1);

    }).then(function(result) {
        var gas = Number(result);

        console.log("gas estimation = " + gas + " units");
        console.log("gas cost estimation = " + (gas * gasPrice) + " wei");
        console.log("gas cost estimation = " + TestContract.web3.fromWei((gas * gasPrice), 'ether') + " ether");
    });
});

Ergebnis in meinem Fall (privates Netzwerk):

> truffle test
Using network 'test'.

Compiling .\contracts\Migrations.sol...
Compiling .\contracts\Test.sol...

Gas Price is 20000000000 wei
gas estimation = 26794 units
gas cost estimation = 535880000000000 wei
gas cost estimation = 0.00053588 ether
Oder web3.eth.gasPricestattweb3.eth.getGasPrice
Wie führen wir eine tatsächliche Transaktion mit dem Gas durch?

Die Antwort von Greg Jeanmart erklärte perfekt, wie man die Gaskosten für eine Funktion schätzt. An dieser Stelle möchte ich darauf hinweisen, dass das Design Ihrer Funktion giveAwayDividend()möglicherweise anfällig für Angriffe ist.

Da jede for-Schleife Ether an einen Benutzer zahlt und die nächste Schleife erst ausführt, nachdem diese Zahlung erfolgreich gesendet wurde, könnte es der Fall sein, dass der Benutzer customerAddress[0]die Zahlung verweigert (sie können dies tun, indem sie einen Vertrag haben, dessen Fallback Funktion absichtlich fehlschlägt), dann giveAwayDividend()würde Ihre Funktion dann auch jedes Mal fehlschlagen und somit unaufrufbar werden.

Ein besserer Ansatz könnte darin bestehen, dass Benutzer eine Funktion „draw()“ aufrufen, sodass das Guthaben nur dann an ihre Adresse geht, wenn die Benutzer dies anfordern. Auf diese Weise können Angreifer die Funktion nur für ihr Konto ungültig machen und andere nicht beeinträchtigen.

Ich habe auch über Ihre Lösung nachgedacht, es ist eine technisch ideale Lösung, aber die Situation ist: Ich möchte Dividenden automatisch verschenken, damit meine Benutzer nicht selbst draw() aufrufen müssen, da die meisten von ihnen Investoren sind, die dies nicht tun sogar etwas über Smart Contract wissen.