最新消息:本站技术交流 QQ 群:28124927

回退函数与三种方法发送ETH

区块链/比特币 exchen 1648浏览 0评论

回退函数与三种方法发送ETH

之前测试过重入漏洞,了解到发送主币 ETH 给一个合约,这个合约需要有一个回退函数,如果发送币使用 call 容易造成重入的问题,这次我们来详细了解回退函数,还有三种方法发送 ETH,分别看它们之间有什么不同点。

回退函数

回退函数有两个功能,一个是用于接收主币 ETH,还有一个作用是当调用的函数在合约里不存在,会调用回退函数。回退函数有两种,一种是 receive,一种是 fallback,这两种都可以用于接受主币,那它们有什么区别呢?

当以太坊的主币发送到合约,会先判断 msg.data 是否为空,如果不为空会调用 fallback,如果为空会先判断判断 receive 是否存在,如果存在则调用 receive,不存在则调用 fallback。下面我们编写一个 Test 合约来测试,代码里有 fallback 和 recive 两个回退函数,都添加了一个 Log 日志,日志会返回 4 个参数,第一个是函数名,第二个是发送者地址,第三个是发送的数量,第四个是 bytes 数据,可以用于合约之间的交互,代码如下:

布署 Tes 合约后,测试发送 1 个 ETH,在 CALLDATA 数据里随便输入一段数据,比如 0x112233,点击 Transact 即可发送,如下图所示:

从日志里可以看到,会有 4 个参数,其中 functionName 是 fallback,value 是 数据,data 是 CALLDATA 里输入的数据,如下图所示,说明 msg.data 有数据的话,就会调用 fallback,主要为了合约之间的交互 。

再将 CALLDATA 置空,充值一个 ETH,这时发现 functionName 是 receive,说明在 msg.data 为空的情况下,会调用 receive,如下图所示。当然如果合约里没有 receive,还是会调用 fallback。

三种方法发送ETH

solidity 有三种发送 ETH 的方法,分别是 transfer、send、call。

(1) transfer 只会带有 2300 个 gas,没有返回值,如果失败会提示 reverts 错误。

(2) send 也是只带有 2300 个 gas,但是会有返回值,返回 true 代表成功,返回 false 代表失败。

(3) call 会发送所有剩余的 gas,会有两个返回值,第一个是否成功的 bool 值,第二个是一个 bytes 数据,如果发送的目标是一个合约,这个合约有返回值,就会返回在这个 bytes 数据里,主要用于合约之间的数据交互。

下面编写测试代码看看效果,编写一个名为 SendETH 的合约, 在构造函数里添加 payable 属性,方便在创建时得到 ETH,然后添加三个函数 Transfer、Send,Call,分别用来测试三种方式发送 ETH,代码如下:

再编写一个 Test 合约,用来接受 ETH,添加 receive 回退函数,再添加一个 Log 日志,日志里有两个参数,第一个是打印函数名称,第二个是调用 gasleft 获取剩余的 gas,代码如下:

接下来布署两个合约,在 SendETH 合约布署时,添加一个 ETH,如下图所示:

先使用 transfer 方法发送,查看打印的日志,可以发现剩余的 gas 是 2240,如下图所示,使用 send 方法发送,gas 也是一样。

再测试使用 call 方法发送,从日志打印可以发现剩余的 gas 是 7216,这样如果在回退函数还可以再执行其他操作,容易造成重入,如下图所示。

转载请注明:exchen's blog » 回退函数与三种方法发送ETH

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址