【从0学习Solidity】 19. 接收ETH receive和fallback

【从0学习Solidity】 19. 接收ETH receive和fallback

  • 博主简介:不写代码没饭吃,一名全栈领域的创作者,专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构,分享一些项目实战经验以及前沿技术的见解。
  • 关注我们的主页,探索全栈开发,期待与您一起在移动开发的世界中,不断进步和创造!
  • 本文收录于 不写代码没饭吃 的学习汇报系列,大家有兴趣的可以看一看。
  • 欢迎访问我们的微信公众号:不写代码没饭吃,获取更多精彩内容、实用技巧、行业资讯等。您关注的是我们前进的动力!

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

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

注意⚠️:在solidity 0.6.x版本之前,语法上只有 fallback() 函数,用来接收用户发送的ETH时调用以及在被调用函数签名没有匹配到时,来调用。
0.6版本之后,solidity才将 fallback() 函数拆分成 receive()fallback() 两个函数。

我们这一讲主要讲接收ETH的情况。

接收ETH函数 receive

receive()函数是在合约收到ETH转账时被调用的函数。一个合约最多有一个receive()函数,声明方式与一般函数不一样,不需要function关键字:receive() external payable { ... }receive()函数不能有任何的参数,不能返回任何值,必须包含externalpayable

当合约接收ETH的时候,receive()会被触发。receive()最好不要执行太多的逻辑因为如果别人用sendtransfer方法发送ETH的话,gas会限制在2300receive()太复杂可能会触发Out of Gas报错;如果用call就可以自定义gas执行更复杂的逻辑(这三种发送ETH的方法我们之后会讲到)。

我们可以在receive()里发送一个event,例如:

    // 定义事件
    event Received(address Sender, uint Value);
    // 接收ETH时释放Received事件
    receive() external payable {
        emit Received(msg.sender, msg.value);
    }

有些恶意合约,会在receive() 函数(老版本的话,就是 fallback() 函数)嵌入恶意消耗gas的内容或者使得执行故意失败的代码,导致一些包含退款和转账逻辑的合约不能正常工作,因此写包含退款等逻辑的合约时候,一定要注意这种情况。

回退函数 fallback

fallback()函数会在调用合约不存在的函数时被触发。可用于接收ETH,也可以用于代理合约proxy contractfallback()声明时不需要function关键字,必须由external修饰,一般也会用payable修饰,用于接收ETH:fallback() external payable { ... }

我们定义一个fallback()函数,被触发时候会释放fallbackCalled事件,并输出msg.sendermsg.valuemsg.data:

    event fallbackCalled(address Sender, uint Value, bytes Data);

    // fallback
    fallback() external payable{
        emit fallbackCalled(msg.sender, msg.value, msg.data);
    }

receive和fallback的区别

receivefallback都能够用于接收ETH,他们触发的规则如下:

触发fallback() 还是 receive()?
           接收ETH
              |
         msg.data是空?
            /  \
          是    否
          /      \
receive()存在?   fallback()
        / \
       是  否
      /     \
receive()   fallback()

简单来说,合约接收ETH时,msg.data为空且存在receive()时,会触发receive()msg.data不为空或不存在receive()时,会触发fallback(),此时fallback()必须为payable

receive()payable fallback()均不存在的时候,向合约直接发送ETH将会报错(你仍可以通过带有payable的函数向合约发送ETH)。

Remix 演示

  1. 首先在 Remix 上部署合约 “Fallback.sol”。

  2. “VALUE” 栏中填入要发送给合约的金额(单位是 Wei),然后点击 “Transact”。
    【从0学习Solidity】 19. 接收ETH receive和fallback_第1张图片

  3. 可以看到交易成功,并且触发了 “receivedCalled” 事件。
    【从0学习Solidity】 19. 接收ETH receive和fallback_第2张图片

  4. “VALUE” 栏中填入要发送给合约的金额(单位是 Wei),“CALLDATA” 栏中填入随意编写的msg.data,然后点击 “Transact”。
    【从0学习Solidity】 19. 接收ETH receive和fallback_第3张图片

  5. 可以看到交易成功,并且触发了 “fallbackCalled” 事件。
    【从0学习Solidity】 19. 接收ETH receive和fallback_第4张图片

总结

这一讲,我介绍了Solidity中的两种特殊函数,receive()fallback(),他们主要在两种情况下被使用,他们主要用于处理接收ETH和代理合约proxy contract

如果这份博客对大家有帮助,希望各位给作者一个免费的点赞作为鼓励,并评论收藏一下⭐,谢谢大家!!!
制作不易,如果大家有什么疑问或给作者的意见,欢迎评论区留言。

你可能感兴趣的:(Web3,web3,solidity,区块链)