2
votes

I'm using the Truffle testing framework (v4.0.1) for Ethereum. I can't figure out why the transaction fees aren't adding up to gasPrice*gasUsed for the following simple contract:

contract MinTest {
    function run() public returns(bool) {
        return true;
    }
}

The mocha test I'm using is:

contract('Minimum Test', function (accounts) {

  it("min test", function () {
    var initial = web3.eth.getBalance(accounts[1]);
    var final;

    return MinTest.deployed().then(function(instance) {
        return instance.run({from: accounts[1]});
    }).then(function(result) {
        final =  web3.eth.getBalance(accounts[1]);

        var gasPrice = new BigNumber(web3.eth.gasPrice);
        var gasUsed = new BigNumber(result.receipt.gasUsed);
        var gasCost = gasPrice.times(gasUsed);

        console.log("gasPrice       : " + gasPrice);
        console.log("gasUsed        : " + gasUsed);
        console.log("gasCost        : " + gasCost);
        console.log("initial        : " + initial);
        console.log("initial-gasCost: " + initial.minus(gasCost));
        console.log("final          : " + final);
        console.log("unaccounted    : " + initial.minus(gasCost).minus(final));
    });
  });

});

The test above produces the following output:

gasPrice       :            20000000000
gasUsed        :                  21478
gasCost        :        429560000000000
initial        :  100000000000000000000
initial-gasCost:   99999570440000000000
final          :   99997852200000000000
unaccounted    :       1718240000000000

I expected that the call to the MinTest.run function of the contract to cause accounts[1] to be debited an amount exactly equal to gasPrice*gasUsed, but that isn't the case in this example. There is a an additional 1718240000000000 wei debited that I can't account for. Why is an additional 1718240000000000 wei debited here?

1

1 Answers

2
votes

web3.eth.gasPrice is not the price specified in your transaction call. From the docs:

This property is read only and returns the current gas price. The gas price is determined by the x latest blocks median gas price.

It is used to tell you what others are paying so you can dynamically determine the "going rate". You would use this if you want to change the gas price for your transactions over time. I'm guessing testrpc just has this set at 20000000000.

On the other hand, when you don't specify a gasPrice in your transaction call, it defaults to 10000000000. Below is an updated test case with the gasPrice passed in and the output (I used 15 Gwei for my test).

contract('Minimum Test', function (accounts) {

  it("min test", function () {
    var initial = web3.eth.getBalance(accounts[1]);
    var final;
    var gasPrice = new BigNumber(15000000000);

    return MinTest.deployed().then(function(instance) {
      return instance.run({from: accounts[1], gasPrice: gasPrice});
    }).then(function(result) {
      final =  web3.eth.getBalance(accounts[1]);

      var gasUsed = new BigNumber(result.receipt.gasUsed);
      var gasCost = gasPrice.times(gasUsed);

      console.log("gasPrice       : " + gasPrice);
      console.log("gasUsed        : " + gasUsed);
      console.log("gasCost        : " + gasCost);
      console.log("initial        : " + initial);
      console.log("initial-gasCost: " + initial.minus(gasCost));
      console.log("final          : " + final);
      console.log("unaccounted    : " + initial.minus(gasCost).minus(final));
    });
  });

});
  Contract: Minimum Test
gasPrice       : 15000000000
gasUsed        : 21431
gasCost        : 321465000000000
initial        : 100000000000000000000
initial-gasCost: 99999678535000000000
final          : 99999678535000000000
unaccounted    : 0
    √ min test (773ms)


  1 passing (922ms)

EDIT - The web3js docs DO indeed say the default value for gasPrice is supposed to be the same:

gasPrice: Number|String|BigNumber - (optional, default: To-Be-Determined) The price of gas for this transaction in wei, defaults to the mean network gas price.

It may be a bug in Truffle then. In any case, if you pass in your own gas price, the numbers work out.