Solidity有三种方法向其他合约发送ETH,他们是:transfer(),send()和call(),其中call()是被鼓励的用法。
先部署一个接收ETH合约receiveETH;合约里有一个事件Log,记录收到的ETH数量和gas剩余。还有两个函数,一个是receive()函数,收到ETH被触发,并发送Log事件;另一个是查询合约ETH余额的getBalance()函数。
contract ReceiveETH {
// 收到eth事件,记录amount和gas
event Log(uint amount, uint gas);
// receive方法,接收eth时被触发
receive() external payable{
emit Log(msg.value, gasleft());
}
// 返回合约ETH余额
function getBalance() view public returns(uint) {
return address(this).balance;
}
}
我们将实现三种方法向ReceiveETH合约发送ETH。首先,先在发送ETH合约SendETH中实现payable的构造函数和receive(),让我们能够在部署时和部署后向合约转账。
contract SendETH {
// 构造函数,payable使得部署的时候可以转eth进去
constructor() payable{}
// receive方法,接收eth时被触发
receive() external payable{}
}
- 用法是接收方地址.transfer(发送ETH数额)。
- transfer()的gas限制是2300,足够用于转账,但对方合约的fallback()或receive()函数不能实现太复杂的逻辑。
- transfer()如果转账失败,会自动revert(回滚交易)。
示例如下:
function transferETH(address payable _to, uint256 amount) external payable{
_to.transfer(amount);
}
其中,_to是接收地址,amount是数量
- 用法是接收方地址.send(发送ETH数额)。
- send()的gas限制是2300
- send()如果转账失败,不会revert
- send()的返回值是bool,代表着转账成功或失败,需要额外代码处理一下。
示例如下:
error SendFailed(); // 用send发送ETH失败error
function sendETH(address payable _to, uint256 amount) external payable{
// 如果失败,revert交易并发送error
bool success = _to.send(amount);
if(!success){
revert SendFailed();
}
}
- 用法是接收方地址.call{value: 发送ETH数额}("")。
- call()没有gas限制,可以支持对方合约fallback()或receive()函数实现复杂逻辑。
- call()如果转账失败,不会revert。
- 返回值是(bool, bytes),其中bool代表着转账成功或失败,需要额外代码处理
示例代码如下:
error CallFailed(); // 用call发送ETH失败error
function callETH(address payable _to, uint256 amount) external payable{
// 处理call的返回值,如果失败,revert交易并发送error
(bool success,) = _to.call{value: amount}("");
if(!success){
revert CallFailed();
}
}