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!

1 Answer 1

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);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.