header-langage
简体中文
繁體中文
English
Tiếng Việt
한국어
日本語
ภาษาไทย
Türkçe
扫码下载APP

Solidity极简入门|第二十二讲:Call

2022-08-24 10:00
阅读本文需 8 分钟
本文介绍了如何用call这一低级函数来调用其他合约。
原文标题:《 Solidity 极简入门: 22. Call 》
原文作者:0xAA     


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


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


我们曾在第 17 讲:发送 ETH那一讲介绍过利用 call 来发送 ETH,这一讲我们将介绍如何利用它调用合约。


Call


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


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


call 的使用规则


call 的使用规则如下:



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



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


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



看起来有点复杂,下面我们举个 call 应用的例子。


目标合约


我们先写一个简单的目标合约 OtherContract 并部署,代码与第 19 讲中基本相同,只是多了 fallback 函数。



这个合约包含一个状态变量 x,一个事件 Log 在收到 ETH 时触发,三个函数:


getBalance(): 返回合约 ETH 余额。setX(): external payable 函数,可以设置 x 的值,并向合约发送 ETH。getX(): 读取 x 的值。


利用 call 调用目标合约


1. Response 事件


我们写一个 Call 合约来调用目标合约函数。首先先写一个定义 Response 事件,输出 call 返回的 success 和 data,方便我们观察返回值。



2. 调用 setX 函数


我们定义 callSetX 函数来调用目标合约的 setX(),转入 msg.value 数额的 ETH,并释放 Response 事件输出 success 和 data:



接下来我们调用 callSetX 把状态变量_x 改为 5,参数为 OtherContract 地址和 5,由于目标函数 setX() 没有返回值,因此 Response 事件输出的 data 为 0x,也就是空。


3. 调用 getX 函数


下面我们调用 getX() 函数,它将返回目标合约_x 的值,类型为 uint256。我们可以利用 abi.decode 来解码 call 的返回值 data,并读出数值。



从 Response 事件的输出,我们可以看到 data 为 0x0000000000000000000000000000000000000000000000000000000000000005。而经过 abi.decode,最终返回值为 5。


4. 调用不存在的函数


如果我们给 call 输入的函数不存在于目标合约,那么目标合约的 fallback 函数会被触发。



上面例子中,我们 call 了不存在的 foo 函数。call 仍能执行成功,并返回 success,但其实调用的目标合约 fallback 函数。


总结


这一讲,我们介绍了如何用 call 这一低级函数来调用其他合约。call 不是调用合约的推荐方法,因为不安全。但他能让我们在不知道源代码和 ABI 的情况下调用目标合约,很有用。


原文链接


点击了解律动BlockBeats 在招岗位


欢迎加入律动 BlockBeats 官方社群:

Telegram 订阅群:https://t.me/theblockbeats

Telegram 交流群:https://t.me/BlockBeats_App

Twitter 官方账号:https://twitter.com/BlockBeatsAsia

举报 纠错/举报
本平台现已全面集成Farcaster协议, 如果您已有Farcaster账户, 可以登录 后发表评论
选择文库
新增文库
取消
完成
新增文库
仅自己可见
公开
保存
纠错/举报
提交