【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评论