1

I'm learning solidity I got two methods for transferring ether

  1. <address payable>.send(1 ether)
  2. <address payable>.transfer(1 ether)

Both are used to transferring ether to the recipient address but what is the difference between them, and where should we use transfer or send.

0

1 Answer 1

4

Short answer

  • .send() returns a boolean result for success/failure.
  • .transfer() reverts on failure.

.send() is the original method. If the receiver is a contract, flow control will be transfered to the receiver's fallback function until it returns.

Long answer

They can fail if the receiver is a contract that doesn't want the money, and there are many good reasons why that might be the case. It is almost always best to revert if the send was unsuccessful.

Therefore, in old syntax, a good pattern was:

bool success = <address>.send(amount);
if(!success) throw; // revert() in newer compilers, possibly require instead of if()

Developers would not always remember (or know) to do that, so the contract might carry on assuming money has been sent when it wasn't ... bugs.

There are few occasions when it would be appropriate to transfer assets, update accounting or generally carry on if the transfer actually failed, but .send() provides a way to do that:

bool success = <address>.send(amount);
if(!success) {
  // deal with the failure case
} else {
  // deal with the success case
}

Reentrance

Reentrance was discovered with the DAO incident. "Checks, effects, interactions" is a defensive pattern, meaning:

  1. Validation
  2. Optimistic accounting
  3. send, transfer or call

So, you get something like:

balances[msg.sender] -= amount; // optimistic accounting
bool success = <address>.send(amount);
if(!success) {
  // failure case
  balances[msg.sender] += amount; // put it back
...

In most cases, one doesn't want to continue and one does want to revert the optimistic accounting, so:

balances[msg.sender] -= amount;
<address>.transfer(amount); // will revert on failure
// success, carry on

Hope it helps.

5
  • Thanks, Rob for this descriptive answer.
    – Rathore
    Feb 18, 2020 at 3:32
  • 1
    When you say "//will revert on failure" in your last code snippet do you mean that "balances[msg.sender] -=amount" will automatically be reversed? i.e. no need to code that explicitly like in the .send example? Thanks.
    – john blair
    Aug 19, 2021 at 9:39
  • That is correct. Aug 19, 2021 at 14:18
  • Why would you want to .transfer(amount) and at the same time deduct amount from the balance?
    – sunwarr10r
    Dec 25, 2021 at 15:38
  • In many cases, contracts have internal accounting concerns as well as the actual receipt and sending of funds. Consider a simple ATM. If Alice and Bob both deposit funds then the contract has a balance that is the sum of both deposits. The contract can transfer funds to Alice or Bob and its funds on hand will indeed adjust. However, it cannot know its liabilities to either user user - how much is owed to Alice? - unless it attends to accounting. This is what the balances mapping is doing in the example. Dec 26, 2021 at 8:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.