1

Consider this simple function,

function setXFromAddress(address _addr, uint _x) public {
        Callee callee = Callee(_addr);
        callee.setX(_x);
    }

The above code creates a contract instance from address and calls it's method. Solidity-by-example says it's the recommended way compared to low level call.

My question is, how much gas is forwarded to the callee contract? I know that with call I can specify how much is sent like this,

function testCallFoo(address payable _addr) public payable {
        // You can send ether and specify a custom gas amount
        (bool success, bytes memory data) = _addr.call{value: msg.value, gas: 5000}(
            abi.encodeWithSignature("foo(string,uint256)", "call foo", 123)
        );

    }

So what determines how much is sent in the first case? Assume callee functions are state changing functions. And also, does any of the approaches create a new transaction?

1 Answer 1

3

Starting with Solidity 0.5.0 all available gas will be forwarded by default with an external call (see changelog).

But it is important to note what "all available gas" means. EIP-150 defines the "all but one 64th" rule, which states that always at least 1/64 of the gas still not used for this transaction cannot be sent along.

How do wallets determine how much gas is needed for a transaction?

Most wallets use eth_estimateGas to estimate the total gas usage of a transaction. Geth implements this by doing a binary search with a gas limit set until they find a value where the transaction does not fail (e.g. starting with the block gas limit, then trying half, etc).

If you require your internal call to be successful (e.g. require(success, "Internal call failed")), then this process will estimate the correct gas amount to also make your internal call succeed (if possible).

If you don't enforce this then it might happen that the gas estimated is lower than what is needed, since the outer transaction will success even if the inner one fails. In this case it might make sense to use other was to enforce that enough gas is available (e.g. require(gasleft() > 1000000, "I need a lot of gas"), but hardcoding this is discouraged, as gas costs change over time.

Last note: Just because you specific the gas that should be sent along with a call, doesn't mean that really that much gas will be sent along. Looking again at EIP-150 it is defined there that if more gas is requested to be sent, than what is available, then all but 1/64th are sent along.

3
  • Related question: ethereum.stackexchange.com/questions/83329/…
    – Richard
    Jan 6, 2022 at 21:02
  • Thanks for the answer. I took a look at the EIP-150 too. But can't understand why only 63/64 gas is forwarded. How does it help mitigating DoS? And why the specific ratio. Thanks Richard!
    – Pranay
    Jan 7, 2022 at 3:16
  • Not sure why this specific ration. Most of the times tests/simulations are being made and then the number was chosen (there is a google doc linked in the eip with some numbers). In general it prevents DoS as it limits how many nested transactions you can do. But besides that there is also a usability aspect for contract developers. Both of these are outlined in the EIPs linked in EIP-150 (see EIP-114 and EIP-90)
    – Richard
    Jan 7, 2022 at 8:34

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.