【Solidity】fallback和receive的用法
这两个是回调function,Solidity支持两种特殊的回调函数,receive()和fallback(),他们主要在两种情况下被使用:
- 接收
ETH - 处理合约中不存在的函数调用(代理合约
proxy contract)
receive和fallback的区别
receive和fallback都能够用于接收ETH,他们触发的规则如下:

简单来说,合约接收ETH时,msg.data为空且存在receive()时,会触发receive();msg.data不为空或不存在receive()时,会触发fallback(),此时fallback()必须为payable。
receive()和payable fallback()均不存在的时候,向合约发送ETH将会报错。
代码范例
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Receiver{
event Received(address caller,uint amount,string message);
event Foo(string message);
fallback() external payable{
emit Received(msg.sender, msg.value,"fallback was called");
}
receive() external payable{
emit Received(msg.sender, msg.value,"receive was called");
}
function foo(string calldata message) public returns(string memory){
emit Foo(message);
return message;
}
function getBalance() public view returns(uint){
return address(this).balance;
}
}
contract Caller{
event Response(bool success, bytes data);
//付款将会回调receive
function triggerReceive(address contractAddress)public payable{
(bool success, bytes memory data) = contractAddress.call{value:msg.value, gas:5000}("");
emit Response(success,data);
}
//foo function是纯在的,所以不会回调fallback
function triggerFoo(address contractAddress,string calldata message)public payable{
(bool success, bytes memory data) = contractAddress.call(
abi.encodeWithSignature("foo(string)",message)
);
emit Response(success,data);
}
//由于function不存在所以去回调fallback
function testCallDoesNotExist(address _addr) public {
(bool success, bytes memory data) = _addr.call(
abi.encodeWithSignature("doesNotExist()")
);
emit Response(success, data);
}
}
结果1:触发triggerReceive,往receiver发送eth,由于call msg是空值,所以response log内data是0x,也就是空值

结果2:触发testCallDoesNotExist,由于receiver合约内不存在doesNotExist function,所以就会回调fallback

结果3:触发triggerFoo,由于receiver当中这function存在,所有并不会回调fallback

![]()
Facebook评论