79

I noticed that address's offer two member functions that perform the transfer of ether to the specified address. send returns false upon failure and transfer raises an exception. In the Solidity documentation they offer an example that utilizes both calls Simple Open Auction.

When should I use send and when should I use transfer?

2

4 Answers 4

61

EDIT May 2021: call{value: amount}("") should now be used for transferring ether (Do not use send or transfer.)

Here's an example:

(bool success, ) = recipient.call{value:amt}("");
require(success, "Transfer failed.");

Please see:

TLDR; transfer and send should be avoided because they forward a fixed amount of gas and gas costs can and will change.

Original Answer

Both send and transfer are considered to be a safe way to move funds as they have a gas stipend of 2300.

If you are curious about the reasons for adding a transfer you may follow an original discussion about the feature.

7
  • 1
    If send fails, it returns false, correct? What does transfer do if it fails? Does it return false? Does it revert all changes?
    – Curt
    Aug 3, 2017 at 14:52
  • 2
    Transfer throw an exception and all of the changes in a transaction are reverted. Aug 3, 2017 at 20:18
  • 4
    Dec 2019: call.value()() should now be used for transferring ether. (send and transfer should be avoided.) See: ethereum.stackexchange.com/questions/78124/… I will clean up this comment if this answer is updated.
    – eth
    Dec 8, 2019 at 10:49
  • Well, if you're going to now advise people to not use send or transfer, something should be said about reentrancy, as that was the point of the 2300 gas stipend for the other approaches (misguided as they turned out to be). Jan 15, 2020 at 19:41
  • 2
    Why in 2021 you cannot use send and transfer ? Manuals says it's safe. And the gas set to 2300
    – RusAlex
    Jul 24, 2021 at 11:37
101

address.transfer()

  • throws on failure
  • forwards 2,300 gas stipend (not adjustable), safe against reentrancy
  • should be used in most cases as it's the safest way to send ether

address.send()

  • returns false on failure
  • forwards 2,300 gas stipend (not adjustable), safe against reentrancy
  • should be used in rare cases when you want to handle failure in the contract

address.call.value().gas()()

  • returns false on failure
  • forwards all available gas (adjustable), not safe against reentrancy
  • should be used when you need to control how much gas to forward when sending ether or to call a function of another contract

Detailed version below:

The relative tradeoffs between the use of someAddress.send(), someAddress.transfer(), and someAddress.call.value()():

  • someAddress.send()and someAddress.transfer() are considered safe against reentrancy. While these methods still trigger code execution, the called contract is only given a stipend of 2,300 gas which is currently only enough to log an event.
  • x.transfer(y) is equivalent to require(x.send(y)), it will automatically revert if the send fails.
  • someAddress.call.value(y)() will send the provided ether and trigger code execution. The executed code is given all available gas for execution making this type of value transfer unsafe against reentrancy.

Using send() or transfer() will prevent reentrancy but it does so at the cost of being incompatible with any contract whose fallback function requires more than 2,300 gas. It is also possible to use someAddress.call.value(ethAmount).gas(gasAmount)() to forward a custom amount of gas.

One pattern that attempts to balance this trade-off is to implement both a push and pull mechanism, using send() or transfer() for the push component and call.value()() for the pull component.

It is worth pointing out that exclusive use of send() or transfer() for value transfers does not itself make a contract safe against reentrancy but only makes those specific value transfers safe against reentrancy.

More details are here https://consensys.github.io/smart-contract-best-practices/recommendations/#be-aware-of-the-tradeoffs-between-send-transfer-and-callvalue

Reasons for adding transfer(): https://github.com/ethereum/solidity/issues/610


call() can also be used to issue a low-level CALL opcode to make a message call to another contract:

if (!contractAddress.call(bytes4(keccak256("someFunc(bool, uint256)")), true, 3)) {
    revert;
}

The forwarded value and gas can be customized:

contractAddress.call.gas(5000)
    .value(1000)(bytes4(keccak256("someFunc(bool, uint256)")), true, 3);

This is equivalent to using a function call on a contract:

SomeContract(contractAddress).someFunc.gas(5000)
    .value(1000)(true, 3);

Beware of the right padding of the input data in call() https://github.com/ethereum/solidity/issues/2884


transfer(), send() and call() functions are translated by the Solidity compiler into the CALL opcode.

As explained on the Subtleties page in the Ethereum's wiki:

CALL has a multi-part gas cost:

  • 700 base
  • 9000 additional if the value is nonzero
  • 25000 additional if the destination account does not yet exist (note: there is a difference between zero-balance and nonexistent!)

The child message of a nonzero-value CALL operation (NOT the top-level message arising from a transaction!) gains an additional 2300 gas on top of the gas supplied by the calling account; this stipend can be considered to be paid out of the 9000 mandatory additional fee for nonzero-value calls. This ensures that a call recipient will always have enough gas to log that it received funds.


Sending and Receiving ether explained in Solidity docs:

5
  • 1
    Very nice post :D Can I ask a question: so if I use transfer/send, I will always lost 2300 gas right ? There is no refund policy.
    – hqt
    May 1, 2018 at 5:43
  • Thank you. You will always lose at least 9700 gas when you make a send/transfer. 2300 is the stipend that the internal transaction will be able to spend. This is how it's explained in the Subtleties page: The child message of a nonzero-value CALL operation (NOT the top-level message arising from a transaction!) gains an additional 2300 gas on top of the gas supplied by the calling account; this stipend can be considered to be paid out of the 9000 mandatory additional fee for nonzero-value calls. This ensures that a call recipient will always have enough gas to log that it received funds. May 1, 2018 at 6:43
  • 1
    This answer should be the validated answer as it provide the most comprehensive explanation on which to use in the different scenarios. The current answer is also a very good answer as well, but it describes more the historical context of the feature.
    – Cyril
    Jan 19, 2019 at 8:21
  • @medvedev1088 which of those methods in your posts returns false if the contract returns null? Feb 17, 2021 at 23:08
  • What value is returned by transfer on success?
    – zak100
    Mar 24, 2021 at 15:20
5

Very good answers above but please note the change in syntax in the latest version of Solidity.

From Solidity Docs:

address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));
4

EDIT Dec 2019: call.value()() should now be used for transferring ether. (Do not use send or transfer.)

See: Is transfer() still safe after the Istanbul update?

5
  • sender.transfer{gas:10000}(2 ether) is it also ok to set the gas limit with transfer. On one of two different sources, I read it will be possible in the future. On the other, I read it can be set like the sample I provided. Jan 25, 2022 at 18:05
  • @Ferda-Ozdemir-Sonmez You should use sender.call{value: 2 ether}(""). You should avoid transfer and specifying gas. Additional info: ethereum.stackexchange.com/questions/78124/…
    – eth
    Jan 26, 2022 at 8:51
  • Thanks for the response. Yes, I know that. I am asking if sender.transfer{gas:10000}(2 ether) works ? Jan 27, 2022 at 19:42
  • That's not reliable. Sometimes it might work, sometimes not. And it would be permanently broken if 10,000 gas is never enough. You can't assume 10,000 gas will always be enough. The answers have explained how people assumed 2,300 gas was enough before, well it wasn't. The lesson is to not assume that 10,000 gas will also be enough.
    – eth
    Jan 30, 2022 at 4:46
  • 1
    I will not use it, I am preparing an educational material.. Don't worry.. Jan 30, 2022 at 9:48

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.