Solidity:发送ETH (transfer,send,call)

  • Post author:
  • Post category:solidity


注:学习笔记,仅供参考,如有错误,烦请指正



如何发送ETH币?

您可以通过以下方式将以太币发送到其它合约

  • transfer(2300 gas,抛出错误)
  • send(2300 gas,返回布尔bool值)
  • call(转发所有gas或设置gas,返回布尔值)



您应该使用哪种方法?

call 2019年12月后推荐与重入防护相结合使用的方法。

通过以下方式防止重新进入

  • 在调用其它合约之前进行所有状态更改
  • 使用重入保护修饰符

call 是 address 类型的低级成员函数,它用来与其他合约交互。它的返回值为 (bool, data),分别对应 call 是否成功以及目标函数的返回值。

call 是 solidity 官方推荐的通过触发 fallback 或 receive 函数发送 ETH 的方法。不推荐用 call 来调用另一个合约,因为当你调用不安全合约的函数时,你就把主动权交给了它。推荐的方法仍是声明合约变量后调用函数,当我们不知道对方合约的源代码或 ABI,就没法生成合约变量;这时,我们仍可以通过 call 调用对方合约的函数。



call的使用规则

call的使用规则如下:

目标合约地址.call(二进制编码)

其中二进制编码利用结构化编码函数 abi.encodeWithSignature获得:

 abi.encodeWithSignature("函数签名",逗号分隔的具体参数)

函数签名为”函数名(逗号分隔的参数类型)”。例如 abi.encodeWithSignature(“f(uint256,address)”, _x, _addr)。

另外 call 在调用合约时可以指定交易发送的 ETH 数额和 gas:

目标合约地址.call{value:发送ETH数额,gas:gas数额}(二进制编码);



发送ETH (transfer,send,call)代码演示

contract SendEther {
    function sendViaTransfer(address payable _to) public payable {
        // This function is no longer recommended for sending Ether.
        _to.transfer(msg.value);
    }

    function sendViaSend(address payable _to) public payable {
        // Send returns a boolean value indicating success or failure.
        // This function is not recommended for sending Ether.
        bool sent = _to.send(msg.value);
        require(sent, "Failed to send Ether");
    }

    function sendViaCall(address payable _to) public payable {
        // Call returns a boolean value indicating success or failure.
        // This is the current recommended method to use.
        (bool sent, bytes memory data) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }

参考资料:

[1] Solidity极简入门|第二十二讲:Call,律动,https://www.theblockbeats.info/news/31680

[2] 发送eth (transfer, send, call),登链社区,https://learnblockchain.cn/article/3738



版权声明:本文为runrundream原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。