Sending Ether in Solidity

Overview

When sending ether to someone from our contract, the address of our contract is the sender address.

We can specify the receiver to be any payable address.

address payable to = 0x…;

When sending, we can define how much ether we want to send.

uint amount = 1 ether;

To send the ether we can choose between 3 functions available on the receiver address variable:

Send

to.send(amount);

Transfer

to.transfer(amount);

Call

to.call{value: amount}();

How to differentiate

All 3 functions: send, transfer and call can be used to send a given amount of eher to a given address.

However, the functions work differently in the following aspects:

  • How much gas is send along with the ether
  • How errors are handled

Gas

When we execute smart contracts, we need to pay for the execution.

We pay with gas.

When we send ether, we also want to forward gas.

This way the receiver can use the gas to process the incoming ether.

When looking at the different functions to send ether, there are some differences about:

  • If we can define the amount of gas we want to forward
  • And how much gas is forwarded

Error handling

When we try to send ether with our contracts, sending for some reason may fail.

And in solidity there are different ways to handle errors.

Comparing the different functions to send ether:

A function may already handle a possible failure and revert the call.

Or the function does not handle failure internally. Instead it returns a bool indicating success or failure. In this case we have to implement error handling by ourselves.


Transfer

address payable to;
to.transfer(amount);

Gas

Sending with transfer will forward a fixed amount of 2300 gas.

We have no control on this, there is no way to forward a custom amount of gas to the receiver.

Error handling

Possible failure is automatically covered by transfer, so we don’t have to implement it by ourselves.

When transfer fails, it automatically reverts and all changes on the current state are rolled back.


Send

address payable to;
bool success = to.send(amount);

Gas

send’s behaviour in terms of gas is exactly the same as with transfer:

It will forward a fixed amount of 2300 gas. We can not change this.

Error handling

Possible failure is not automatically covered by send, we have to implement it by ourselves.

The status is returned as a bool.

To handle failure we can make use of one of the multiple ways to handle errors in solidity.

require(success, "not send");
if (!success) {
	revert("not send");
}
error FailedTransfer();

...

if (!success) {
	revert FailedTransfer;
}

Call

(bool success,) = to.call{value: amount}("");

Gas

When we use call to send ether, we can set a custom amount of gas we would like to forward:

(bool success,) = to.call{value: amount, gas: 10000 wei}("");

Error handling

As with send, call will not handle a failed transaction automatically for us.

The first return value we get back is a bool that indicated success or failure.

Based on this we have to implement corresponding error handling.


What should we use?

The fixed amount of 2300 gas we get with transfer and send may not be enough for the recipient to process.

This especially is true, since gas prices can and may change.

Because of this it makes to use call, where we can define a custom amount of gas that gets forwarded.


background scene
Join the garden
Finally enjoy quality-first content.
'cause low-quality sucks

legal privacy