【Solidity】fallback和receive的用法

这两个是回调function,Solidity支持两种特殊的回调函数,receive()fallback(),他们主要在两种情况下被使用:

  1. 接收ETH
  2. 处理合约中不存在的函数调用(代理合约proxy contract

receive和fallback的区别

receivefallback都能够用于接收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

Loading

Facebook评论