25

I would like to break my code up into multiple contracts, but I'm afraid of this increasing the gas fees. Does an external function call cost more gas than an internal call to a function within the same contract? If so, is it a flat fee for each call or would the size of the arguments being passed factor into it?

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
Jonah
  • 655
  • 1
  • 7
  • 17

1 Answers1

19

A little.

Here's a very idiomatic set of contracts with a set of functions that take different paths to set and get the same value. No effort to optimize for gas. delegateCall can do it cheaper.

You can see the difference in transaction cost, which has to do with packing and unpacking requests. You can see it's (roughly) 2,000 gas extra to set the value with an invocation from the "Module" to the "StandAlone" contract that accomplishes the same thing if called directly.

Two things are worth mentioning.

The proportion of overhead to work is outsized because the contracts aren't doing any heavy lifting themselves. It's basically flat-rate overhead.

The setters are the important comparison. Although gas cost is computed for read-only operations they are essentially free, provided you don't exceed the block gasLimit (the budget).

pragma solidity 0.4.19; 

contract StandAlone {
    uint public x = 1;

    function get() public view returns(uint) {
        return x;
    }

    function set(uint _x) public returns(bool success) {
        x = _x;
        return true;
    }

    function getLongWay() public view returns(uint) {
        return get();
    }
}

contract Module {

    StandAlone s;

    function Module(address SAAddress) public {
        s = StandAlone(SAAddress);
    }

    function get() public view returns(uint) {
        return s.get();
    }

    function set(uint  _x) public returns(bool success) {
        return s.set(_x);
    }
}

Hope it helps.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • Hey Rob, does this apply to larger contracts too? What if StandAlone had some real contract code volume instead, will it keep this gas consumption ratio? – KwahuNashoba Jul 25 '18 at 14:44
  • 3
    The ratio will improve. The overhead is packing and unpacking messages. The more actual work the contracts are doing, the less significant this extra cost because it's about the size of the message. – Rob Hitchens Jul 25 '18 at 21:41
  • Aham, I see. So loading the called contract into memory in order to call its function does not affect cost proportionally to its size? Can you provide me reference to read more about that packing and unpacking messages? – KwahuNashoba Jul 25 '18 at 22:49
  • That wasn't how I interpreted the question. He's asking about the extra cost of splitting a monolithic contract into several smaller ones. No one is saying you get to run anything for free ... in fact, we're talking about the extra overhead of passing messages between contracts instead of containing all the code in one bug gulp. – Rob Hitchens Jul 25 '18 at 23:13
  • 2
    Sorry for not being clear, that's actually what I'm trying to understand, is it worth the extra cost of calling another contract to separate some logic and state in another contract. – KwahuNashoba Jul 25 '18 at 23:20
  • 2
    Ah, okay. Messages are cheap. For perspective, every SSTORE costs 10x as much. So, it costs 20,000 gas to write 32 bytes to the contract state. – Rob Hitchens Jul 26 '18 at 09:40
  • I had the same question. I think that in the long run, gas prices will drop (thanks to ETH 2.0) but discounting current price which is higher due to DeFi, gas price in April 2020 was 10Gwei.

    2000 gas at 10 Gwei per gas unit comes to 20000 gwei which means 0.0070$. so 0.7 cents PER CALL is not that expensive but overall it isn't cheap as well, esp. if you are calculating overheads long term.

    Sucks to have to optimize gas costs for now. This will change as gas prices become much cheaper with ETH 2.0. Maybe we can try using Matic POS side chain?

    – Bharat Mallapur Sep 24 '20 at 22:49