如需获取本内容的最新版本,请参见 Cyfrin.io 上的"发送以太币(传输、发送、调用)(代码示例)"
如何发送以太币?
您可以通过以下方式向其他合约发送以太币:
transfer(2300 gas,抛出错误)send(2300 gas,返回布尔值)call(转发所有 gas 或设置 gas,返回布尔值)
如何接收以太币?
一个接收以太币的合约必须至少包含以下函数之一:
receive() external payablefallback() external payable
如果 msg.data为空,则会调用 receive(),否则会调用 fallback()。
你应该使用哪种方法?
2019年12月之后,推荐使用结合了重入防护的call方法。
防范重入攻击的方法包括:
- 在调用其他合约之前完成所有状态变更
- 使用重入防护修饰器
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract ReceiveEther {
/*
调用的函数是fallback()还是receive()?
send Ether
|
msg.data is empty?
/ \
yes no
/ \
receive() exists? fallback()
/ \
yes no
/ \
receive() fallback()
*/
// receive函数。msg.data必须为空。
receive() external payable {}
// 当msg.data不为空时,将调用fallback函数
fallback() external payable {}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
}
contract SendEther {
function sendViaTransfer(address payable _to) public payable {
// 此函数不再推荐用于发送以太币。
_to.transfer(msg.value);
}
function sendViaSend(address payable _to) public payable {
// Send返回一个布尔值,表示成功或失败。.
// 不建议使用此函数发送以太币。
bool sent = _to.send(msg.value);
require(sent, "发送以太币失败");
}
function sendViaCall(address payable _to) public payable {
// Call 返回一个布尔值,表示成功或失败。
// 这是目前推荐使用的方法。
(bool sent, bytes memory data) = _to.call{value: msg.value}("");
require(sent, "发送以太币失败");
}
}
Remix Lite 尝试一下
END
