WTF Solidity: 20. Sending ETH
Twitter: @0xAA_Science | @WTFAcademy_
Community: Discord|Wechat|Website wtf.academy
Codes and tutorials are open source on GitHub: github.com/AmazingAng/WTFSolidity
There are three ways of sending ETH
in Solidity
: transfer()
, send()
and call()
, in which call()
is recommended.
Contract of Receiving ETH
Let's deploy a contract ReceiveETH
to receive ETH
. ReceiveETH
has an event Log
, which logs the received ETH
amount and the remaining gas
. Along with two other functions, one is the receive()
function, which is executed when receiving ETH
, and emit the Log
event; the other is the getBalance()
function that is used to get the balance of the contract.
contract ReceiveETH {
// Receiving ETH event, log the amount and gas
event Log(uint amount, uint gas);
// receive() is executed when receiving ETH
receive() external payable{
emit Log(msg.value, gasleft());
}
// return the balance of the contract
function getBalance() view public returns(uint) {
return address(this).balance;
}
}
After deploying ReceiveETH
, call getBalance()
function, we can see the balance is 0 Ether
.
Contract of Sending ETH
We will implement three ways to send ETH
to the ReceiveETH
contract. First thing first, let's make the constructor
of the SendETH
contract payable
, and add the receive()
function, so we can transfer ETH
to our contract at deployment and after.
contract SendETH {
// constructor, make it payable so we can transfer ETH at deployment
constructor() payable{}
// receive() function, called when receiving ETH
receive() external payable{}
}
transfer
- Usage:
receiverAddress.transfer(value in Wei)
. - The
gas
limit oftransfer()
is2300
, which is enough to make transfer, but not if the receiving contract has a gas consumingfallback()
orreceive()
. - If
transfer()
fails, the transaction willrevert
.
Sample code: note that _to
is the address of ReceiveETH
contract, and amount
is the value you want to send.
// sending ETH with transfer()
function transferETH(address payable _to, uint256 amount) external payable{
_to.transfer(amount);
}
After deploying SendETH
contract, we can send ETH
to ReceiveETH
contract, if amount
is 10, and value
is 0, amount
>value
, transaction failed and get reverted
.
If amount
is 10, and value
is 10, amount
<=value
, then the transaction will go through.
In ReceiveETH
contract, when we call getBalance()
, we can see the balance of the contract is 10
Wei.
send
- Usage:
receiverAddress.send(value in Wei)
. - The
gas
limit ofsend()
is2300
, which is enough to make transfer, but not if the receiving contract has a gas consumingfallback()
orreceive()
. - If
send()
fails, the transaction will bereverted
. - The return value of
send()
isbool
, which is the status of the transaction, you can choose to act on that.
Sample Code:
// sending ETH with send()
function sendETH(address payable _to, uint256 amount) external payable{
// check result of send(),revert with error when failed
bool success = _to.send(amount);
if(!success){
revert SendFailed();
}
}
Now we send ETH
to ReceiveETH
contract, if amount
is 10, and value
is 0, amount
>value
, so the transaction failed, since we handled the return value, transaction will be reverted
.
If amount
is 10, and value
is 11, amount
<=value
, so the transaction succeeded.
call
- Usage:
receiverAddress.call{value: value in Wei}("")
. - There is no
gas
limit forcall()
, so it supports more operations infallback()
orreceive()
of the receiving contract. - If
call()
fails, the transaction will not bereverted
. - The return value of
call()
is(bool, data)
, in whichbool
is the status of transaction, you can choose to act on that.
Sample Code:
// sending ETH with call()
function callETH(address payable _to, uint256 amount) external payable{
// check result of call(),revert with error when failed
(bool success, ) = _to.call{value: amount}("");
if(!success){
revert CallFailed();
}
}
Now we send ETH
to ReceiveETH
contract, if amount
is 10, and value
is 0, amount
>value
, so the transaction failed, since we handled the return value, transaction will be reverted
.
If amount
is 10, and value
is 11, amount
<=value
, so the transaction succeeded.
With any of these three methods, we send ETH
to ReceiveETH
contract successfully.
Summary
In this tutorial, we talked about three ways of sending ETH
in solidity
:
transfer
, send
and call
.
- There is no
gas
limit forcall
, which is the most flexible and recommended way; - The
gas
limit oftransfer
is2300 gas
, transaction will bereverted
if it fails, which makes it the second choice; - The
gas
limit ofsend
is2300
, transaction will not bereverted
if it fails, which makes it the worst choice.