WTF Solidity极简入门第十九讲: 接收ETH receive和fallback

  • 本文介绍了Solidity中的两种特殊回调函数:receive()fallback(),主要用于处理接收ETH和代理合约中的不存在函数调用。

  • receive()函数专门用于接收ETH,声明方式为receive() external payable,不能有参数和返回值。当合约接收ETH且msg.data为空时触发。需注意避免复杂逻辑,因为使用sendtransfer发送ETH时gas限制为2300,可能导致Out of Gas错误。恶意合约可能利用此函数进行攻击,如Akutar NFT项目因此被锁定大量ETH。

  • fallback()函数在调用合约中不存在的函数时触发,也可用于接收ETH。声明方式为fallback() external payable。当msg.data不为空或不存在receive()时触发。

  • 两者的触发规则如下:

    • 如果msg.data为空且存在receive(),则触发receive()
    • 如果msg.data不为空或不存在receive(),则触发fallback()(需为payable)。
    • 如果两者均不存在,向合约发送ETH会报错。
  • 文章还提到可以通过事件记录触发情况,并强调了在退款逻辑中需警惕恶意合约的gas消耗攻击。

总结

原文:《Solidity 极简入门: 19. 接收 ETH receive 和 fallback》

我最近在重新学 solidity,巩固一下细节,也写一个「Solidity 极简入门」,供小白们使用(编程大佬可以另找教程),每周更新 1-3 讲。

所有代码和教程开源在 github: github.com/AmazingAng/WTFSolidity

回调函数

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

- 接收 ETH

- 处理合约中不存在的函数调用(代理合约 proxy contract)

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

接收 ETH 函数 receive

receive() 只用于处理接收 ETH。一个合约最多有一个 receive() 函数,声明方式与一般函数不一样,不需要 function 关键字:receive() external payable { ... }

receive() 函数不能有任何的参数,不能返回任何值,必须包含 external 和 payable。

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

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

WTF Solidity极简入门第十九讲: 接收ETH receive和fallback

有些恶意合约,会在 receive() 函数嵌入恶意消耗 gas 的内容,使得一些退款合约不能正常工作:Akutar NFT项目因此被永久锁定了 11539 ETH,接近 2 亿元!因此写包含退款等逻辑的合约时候,一定要注意这种情况。

回退函数 fallback

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

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

WTF Solidity极简入门第十九讲: 接收ETH receive和fallback

receive 和 fallback 的区别

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

WTF Solidity极简入门第十九讲: 接收ETH receive和fallback

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

receive() 和 payable fallback() 均不存在的时候,向合约发送 ETH 将会报错。

总结

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

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/AmazingAng/WTFSolidity

分享至:

作者:0xAA

本文为PANews入驻专栏作者的观点,不代表PANews立场,不承担法律责任。

文章及观点也不构成投资意见

图片来源:0xAA如有侵权,请联系作者删除。

关注PANews官方账号,一起穿越牛熊
推荐阅读
8分钟前
1小时前
4小时前
6小时前
9小时前
15小时前

热门文章

行业要闻
市场热点
精选读物

精选专题

App内阅读