Wie erhalte ich die Transaktionskosten in einem Truffle Unit Test?

Wie kann ich den tatsächlichen Gasverbrauch sendTransactioneines Trüffeltests ermitteln?

Im folgenden Test buyersendet eine amountvon 50 ETH an einen Vertrag:

const EmptyContract = artifacts.require("EmptyContract");
const BigNumber = web3.BigNumber;

contract('Test', function(accounts) {   
    it("should work", async () => {
        let contract = await EmptyContract.new({ from: accounts[1] });
        let amount = web3.toWei(50, 'ether');
        let buyer = accounts[2];

        // BALANCE BEFORE TX
        let balanceBefore = web3.eth.getBalance(buyer);

        // SEND TX
        let hash = await contract.buy.sendTransaction({from: buyer, value: amount});

        // BALANCE AFTER TX
        const balanceAfter = web3.eth.getBalance(buyer);

        let tx = await web3.eth.getTransaction(hash);
        const gasUsed = tx.gas;
        const gasCost = tx.gasPrice.mul(gasUsed);
        console.log("BEFORE", balanceBefore.toNumber());
        console.log("amount sent", amount);
        console.log("gas price", tx.gasPrice.toNumber());
        console.log("gas used", gasUsed);
        console.log("gas cost", gasCost.toNumber());
        console.log("AFTER", balanceAfter.toNumber());
        console.log("CHECKSUM", balanceAfter.add(gasCost).add(amount).toNumber());

        assert.equal(balanceBefore.toNumber(), balanceAfter.add(gasCost).add(amount).toNumber());
    });
});

Dann buyerwird das Guthaben von überprüft. Es sollte sein

[Saldo vor tx] = [Saldo nach tx] + [gesendeter Betrag] + [Benzinkosten]

Aber es schlägt fehl, Drucken:

BEFORE 100000000000000000000
amount sent 50000000000000000000
gas price 100000000000
gas used 6721975
gas cost 672197500000000000
AFTER 49997862200000000000
CHECKSUM 100670059700000000000       
   :    
AssertionError: expected 100000000000000000000 to equal 100670059700000000000

Der Vertrag ist sehr einfach:

pragma solidity ^0.4.18;

contract EmptyContract {
    function buy() public payable  { }
}

Es scheint, dass die Transaktion 0,6700597 ETH weniger gekostet hat als der von zurückgegebene Wert tx.

Ich habe die Transaktionsgaskosten im Trüffel-Testfall verfolgt, aber es hat nicht geholfen.

Irgendeine Idee?

Antworten (2)

Dafür musst du gasUsedmultiplizieren gasPrice. Die gasUsedist in der Transaktionsquittung enthalten. Während das gasPricein der Transaktion selbst ist. Tatsächlich versuchen Sie in Ihrem Fall, die gasPricefür die zu multiplizieren gas, die vom Absender bereitgestellt wird (die höher sein kann als die gasUsed). ref: getTransaction , getTransactionReceipt

So sollte Ihr Code also aussehen, um korrekt zu sein

const hash = await contract.buy.sendTransaction({von: Käufer, Wert: Betrag});

// BILANZ NACH TX
const balanceAfter = web3.eth.getBalance(buyer);
const tx = warte auf web3.eth.getTransaction(hash);
Konstante Quittung = warten auf web3.eth.getTransactionReceipt (Hash);
const gasCost = tx.gasPrice.mul(receipt.gasUsed);

oder Sie können den Aufruf auch tatsächlich speichern getTransactionReceipt, falls Sie Ihre Methode direkt aufrufen (in diesem Fall sollten Sie ein Ergebnis erhalten, das auch die Transaktionsquittung ref enthält ) .

const txInfo = await contract.buy({von: Käufer, Wert: Betrag});

// BILANZ NACH TX
const balanceAfter = web3.eth.getBalance(buyer);
const tx = warte auf web3.eth.getTransaction(txInfo.tx);
const gasCost = tx.gasPrice.mul(txInfo.receipt.gasUsed);
Vielen Dank! Ich verstehe nicht warum web3.eth.getTransaction(hash).gasund bin web3.eth.getTransactionReceipt(hash).gasUsedanders. Was bedeutet ersteres?
Wie ich im Beitrag erklärt habe, web3.eth.getTransaction(hash).gasist der vom Benutzer bereitgestellte Wert. While web3.eth.getTransactionReceipt(hash).gasUsedist das Gas, das von der Transaktion verwendet wird. Muss also gas>= gasUsedsein, um die Transaktion auszuführen. Natürlich konnten Sie vorher nicht wissen, wie viel Gas Ihre Transaktion verbrauchen wird, deshalb muss der Benutzer das Gas erhöhen, um sicher zu sein, dass die Transaktion ausgeführt wird. gasUsedist oft <= gasund die Differenz (nicht verbrauchtes Gas) wird sofort erstattet.

Alternative: Sie können truffle-cost verwenden . Es ermöglicht Ihnen, Transaktionskosten anstelle der Testdauer mit einer Syntax wie dieser zu protokollieren:

result = await truffleCost.log(
  yourContract.yourFunction()
);

Siehe Link zur Installation (oder soll ich das hier erklären?).

Haftungsausschluss: Ich bin der Entwickler von truffle-cost.