1

This answer explains well how to measure the gas used in a block of code.

I had actually been using this method before I found that answer:

pragma solidity 0.4.26;

import './IERC20Token.sol';

contract Tester {
    uint256 public gasUsed;

    function transfer(IERC20Token _token, address _to, uint256 _value) public {
        uint256 bgn = gasleft();
        require(_token.transfer(_to, _value));
        uint256 end = gasleft();
        gasUsed = bgn - end;
    }
}

Then, simply from a Truffle 4.1.16 test:

const token = await ERC20Token.new('name', 'symbol', 18, SUPPLY);
const tester = await Tester.new();
await token.transfer(tester.address, AMOUNT);
await tester.transfer(token.address, accounts[0], AMOUNT);
const gasUsed = await tester.gasUsed();
console.log(gasUsed.toFixed());

However, it seems that it doesn't take into account gas-refund for changing storage variables from nonzero to zero.

Reading a little bit about this refund, I believe that it is sent back to the sender (msg.sender) or even all the way back to the original sender (tx.origin).

So I'm looking for a more accurate method.

I don't mind if the solution involves the off-chain, for example (using web3.js):

const balanceBefore = await web3.eth.getBalance(myAccount);
const response = await myContract.methods.myFunc().send({from: myAccount, gasPrice: myGasPrice});
const balanceAfter = await web3.eth.getBalance(myAccount);
const gasUsed = response.receipt.gasUsed;
// now do something with balanceBefore, balanceAfter, myGasPrice and gasUsed

But the result should reflect only the gas-cost of the actual block of code in the contract.

For example, it should avoid taking the cost of the transaction itself into account.

Does anybody have a leading clue on this?

Thank you!

goodvibration
  • 26,003
  • 5
  • 46
  • 86

1 Answers1

2

OK, I've realized that I can simply use this, without having to rely on gasleft():

pragma solidity 0.4.26;

import './IERC20Token.sol';

contract Tester1 {
    address public to;
    uint256 public value;

    function transfer(IERC20Token _token, address _to, uint256 _value) public returns (bool) {
        to = _to;
        value = _value;
        return _token.transfer(_to, _value);
    }
}

contract Tester2 {
    address public to;
    uint256 public value;

    function transfer(IERC20Token _token, address _to, uint256 _value) public returns (bool) {
        to = _to;
        value = _value;
        return true; // _token.transfer(_to, _value);
    }
}

Then, from the Truffle 4.1.16 test:

const token = await ERC20Token.new('name', 'symbol', 18, SUPPLY);
const tester1 = await Tester1.new();
const tester2 = await Tester2.new();
await token.transfer(tester1.address, AMOUNT);
await token.transfer(tester2.address, AMOUNT);
const response1 = await tester1.transfer(token.address, accounts[1], AMOUNT);
const response2 = await tester2.transfer(token.address, accounts[2], AMOUNT);
console.log(response1.receipt.gasUsed - response2.receipt.gasUsed);
goodvibration
  • 26,003
  • 5
  • 46
  • 86