Should we never use the transfer function?

For some time now, the following has been recommended with the use of the transfer function:

After December 2019, the call method became the recommended approach for sending Ether. It grants more control over gas usage and facilitates complex interactions between contracts


As I have always understood it, the transfer function is usable for sending the native token to user accounts, and the calls for sending to smart contracts.

But the recommendation says to always use calls functions, not?

I come to this forum to confirm what is the best practice in this regard.
Should we always use call calls and forget about the transfer function?

Should we update all transfers in all our new deploy contracts?

1 Like

This is because in order to determine if the target account is an EOA (externally-owned account) or an SCA (smart-contract account), you need to take an extra step, which costs extra gas AND increases your own contract's byte-code size:

function isContract(address account) private returns (bool) {
    uint32 size;
    assembly {
        size := extcodesize(account)
    return size > 0;

So instead, you are encouraged to just use call conclusively.

Its use is definitely recommended in all cases, isn't it?

With transfer, the associated stipend (2300 gas) protects your system from reentrancy attacks in a native manner, i.e., without any additional code that you need to explicitly implement in your contracts.

With call, you need to explicitly add reentrancy-protection in your contracts, for example, by inheriting and using OpenZeppelin's ReentrancyGuard contract.

Since reentrancy-protection mechanisms such as the one linked above have been well established and thoroughly verified by now, you may as well use call, but you should nevertheless make sure that your system is indeed fully protected from reentrancy attacks (for example, by having your code audited by an external party).

If you don't trust yourself to properly add reentrancy-protection everywhere needed in your code, then you should use transfer, but note that you'd essentially be replacing the potential reentrancy vulnerability in your system with a potential frequent reverting of transactions in your system (either in the present, or in the future - when the gas cost of various opcodes is increased following an EVM upgrade).

Thank you for your extensive explanation,

In my case I only have to change the habit of using the transfer function in transactions between clients, not contract accounts, since I apply the reentry measures with the well known countermeasures.

We will then have to forget about the transfer function because of the possible future or present gas cost.

Problem that I have already experienced in some contract.

We will change our programming routines and adapt to this suggestion as good practice.

In general, send dropped, and now the transfer function as well.

We will only use call .

Thank you very much.

1 Like