How can I get the actual gas consumed by a sendTransaction
inside a truffle test?
In the following test, buyer
sends an amount
of 50 ETH to a contract:
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());
});
});
Then buyer
's balance is checked. It should be
[balance before tx] = [balance after tx] + [amount sent] + [gas cost]
But it fails, printing:
BEFORE 100000000000000000000
amount sent 50000000000000000000
gas price 100000000000
gas used 6721975
gas cost 672197500000000000
AFTER 49997862200000000000
CHECKSUM 100670059700000000000
:
AssertionError: expected 100000000000000000000 to equal 100670059700000000000
The contract is very basic:
pragma solidity ^0.4.18;
contract EmptyContract {
function buy() public payable { }
}
It seems that the transaction cost 0.6700597 ETH less than the value returned by tx
.
I followed Transaction gas cost in truffle test case but it didn't help.
Any idea?
Best Answer
You have to multiply the
gasUsed
for thegasPrice
. ThegasUsed
is contained into the transaction receipt. While thegasPrice
is into the transaction itself. Indeed, in your case, you're trying to multiply thegasPrice
for thegas
, which is the one provided by the sender (which can be higher that thegasUsed
). ref: getTransaction, getTransactionReceiptSo, this is how your code should look like to be correct
or you can also actually save the
getTransactionReceipt
call in case you call your method directly (in this case should give you a result that contains also the transaction receipt ref)