Why does this internal transfer transaction is running out of gas?

Hi there!

I'm having some trouble to understand why two very similar and simple smart contracts are behaving differently. Both of them are using .call.gas(10000000).value(msg.value)(""), but one of them run out of gas when the target contract triggers a transfer function.

You can check the context, link for transactions on Rinkeby and images on this blog post:

But basically, I'm using the following contracts:

// SPDX-License-Identifier: None
pragma solidity 0.6.0;

contract SenderWithRequire {
    function send(address payable receiver) public payable {
        (bool success,) = receiver.call.gas(10000000).value(msg.value)("");
        require(success, "Failed to send value!");
    }
}

contract SenderWithEmit {
    event Debug(bool success);
    function send(address payable receiver) public payable {
        (bool success,) = receiver.call.gas(10000000).value(msg.value)("");
        emit Debug(success);
    }
}

contract Sender {
    function send(address payable receiver) public payable {
        receiver.call.gas(10000000).value(msg.value)("");
    }
}

contract Receiver {
    bool public hasReceived;
    receive() external payable {
        hasReceived = true;
        payable(address(0)).transfer(msg.value);
    }
}

Both SenderWithEmit and SenderWithRequire work fine, but Sender fails.

I'm mostly using Remix with default gas limit 3000000.
Thanks in advance!

Hello again!
Thanks to Ernesto from OpenZeppelin, I was able to understand what was happening.
The details are in the blog post mentioned before, but here's a small explanation:

The Gas Limit used on Remix was not being passed to the Metamask extension, which ended up estimating a gas limit.

This gas limit estimate was not enough, because it only takes into account the main transaction and not its underlying transactions (in this case, the transfer transaction).

Increasing the gas limit manually made the transaction to succeed.

For both SenderWithEmit and SenderWithRequire contracts, the gas limit estimate was barely enough to make them pass, thanks to their extra code.

It was very interesting to find out about gas limits and how they are resolved.
I hope this post helps someone in the future!

1 Like