0

I have written following contracts to test the gas used by a simple function depends on what parameters. As described here the four use cases, each gives different transaction cost even though content of function is exactly same. I tried to know the impact of const function to reduce gas.

The content of 2 functions is just a = constantFnA(); and a = a=5, but it results in different transaction cost. As you can see Case 1 and 2 are exacly same, just the function name and Case 1 and 3 are same just case 3 has some addition functions added. But transaction cost is still different.

Why transaction cost for same function performing same computational steps is different?

Case 1:

pragma solidity ^0.4.16;
contract TestConst{
    uint public a = 10;

    function constantFnA() constant returns (uint) {
        return  a+5;
    }

    // Transaction cost: 26658 gas. 
    // Execution cost: 5386 gas.
    function const_NonConst_A(){
        a = constantFnA();
    }

    // Transaction cost: 26644 gas. 
    // Execution cost: 5372 gas.
    function nonConst_A(){
        a = a+5;
    }
}

case 2:

pragma solidity ^0.4.16;
contract TestConst{
    uint public a = 10;

    function constantFnA() constant returns (uint) {
        return  a+5;
    }

    // Transaction cost: 26636 gas. 
    // Execution cost: 5364 gas.
    function NonCosntUsesConst(){
        a = constantFnA();
    }

    // Transaction cost: 26644 gas. 
    // Execution cost: 5372 gas.
    function nonConstantFn(){
        a = a+5;
    }    
}

Case 3:

pragma solidity ^0.4.16;
contract TestConst{
    uint public a = 10;

    function constantFnA() constant returns (uint) {
        return  a+5;
    }

    // Transaction cost: 26676 gas. 
    // Execution cost: 5404 gas.
    function const_NonConst_A(){ 
        a = constantFnA();
    }

    // Transaction cost: 26684 gas. 
    // Execution cost: 5412 gas.

    function nonConst_A(){
        a = a+5;
    }

    uint8 public b = 10;

    // Transaction cost: 27097 gas. 
    // Execution cost: 5825 gas.
    function constantFnB() constant returns (uint8) {
        return  b+5;
    }

    // Transaction cost: 26995 gas. 
    // Execution cost: 5723 gas.
    function const_NonConst_B(){
        b = b+5;
    }

    function nonConst_B(){
        b = constantFnB();
    }  
}

Case 4:

pragma solidity ^0.4.16;
contract TestConst{
    uint public a = 10;

    function constantFnA() constant returns (uint) {
        return  a+5;
    }

    // Transaction cost: 26654 gas. 
    // Execution cost: 5382 gas.
    function NonCosntUsesConst(){
        a = constantFnA();
    }

    // Transaction cost: 26662 gas. 
    // Execution cost: 5390 gas.

    function nonConstantFn(){
        a = a+5;
    }


    uint8 public b = 10;
    function constantFnB() constant returns (uint8) {
        return  b+5;
    }

    // Transaction cost: 26973 gas. 
    // Execution cost: 5701 gas.
    function nonConstUisngB(){
        b = b+5;
    }

    // Transaction cost: 27053 gas. 
    // Execution cost: 5781 gas.
    function NonConstUsingConstB(){
        b = constantFnB();
    }
}

So pints that needs to addressed are:

Does transaction cost depends on:

  • function name?
  • number of other functions in contract?
  • using uint or unit8 as function parameter?

Does using constant function to perform calculation decreases/increases gas consumption (as used 2 functions in every case results different gas)?

If the transaction cost depends on them, then WHY and HOW?

3

Does transaction cost depends on:

  • function name?
  • number of other functions in contract?
  • using uint or unit8 as function parameter?

Yes, all of these.

For function calls, when the Solidity generated bytecode is identifying which function to execute it sequentially compares the function signatures in numerical order of the hash values. As you rename functions, the hash values change and it takes slightly more or less work to find any particular function. The ones with lower function signature get found more quickly and thus use a little less gas.

In case 1 functions are identified in the following order.

0dbe671f a()  // Automatic getter for a
3162ac67 const_NonConst_A()
5ff17adc nonConst_A()
9b78e905 constantFnA()

In case 2 functions are identified in the following order.

0210c557 NonCosntUsesConst()
0dbe671f a()
301c433a nonConstantFn()
9b78e905 constantFnA()

If you add more functions to the contract then this list gets longer and the functions towards the end will take more gas for the EVM to find when you call them.

As for uint vs. uint8, in the latter case, the EVM has to do some more work to mask out the unused bits in the word. (It performs an and operation with 0xff - actually it does this twice if you don't use the optimiser, which is pointless and wasteful.) It doesn't need to do this when dealing directly with uints.

  • Thanks! This sound convincing. But can you please post the source of info so that I can dig deep into it. Also how solidity hashes these functions? and on what basis these hashes are ordered? I just wish to know how can I choose functions names wisely to reduce gas? Is there any documentation on that? – Prashant Prabhakar Singh Sep 16 '17 at 14:59
  • My info is from inspecting the EVM bytecode generated by the compiler. I wrote my own decompiler, but you can use the Remix debugger, or look at the assembly code there. The compiler source code is here if you are really keen to know what's going on. These amounts of gas are trivial - I wouldn't worry about it; the Solidity compiler wastes way more gas than this elsewhere. If you are truly serious about optimising for gas, then check out LLL. – benjaminion Sep 16 '17 at 15:51
  • 1
    For the function selector, you can find out more in the ABI specification; I've got a bit more info here. – benjaminion Sep 16 '17 at 15:56
  • Thanks @benjaminion for your insights. These links were really helpful. – Prashant Prabhakar Singh Sep 16 '17 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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