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

Call

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

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

call 的使用规则

call 的使用规则如下:

f35c88d933900013b3fbadfd0307257c.jpeg

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

427dd10916b135ee1a6b89452ef1b24d.jpeg

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

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

001038dcb24b9e14c740cb3a0696f5c5.jpeg

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

目标合约

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

92687111e8896e16e4c25b67b9070208.jpeg

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

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

利用 call 调用目标合约

1. Response 事件

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

6662b8c81ce0805b079f85f8d872cb13.jpeg

2. 调用 setX 函数

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

9cf38112f4b3f14d75220212207c0cd5.jpeg

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

3. 调用 getX 函数

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

1a7db1eefbccae42aff9ceaa8c15c30f.jpeg

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

4. 调用不存在的函数

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

47561aac9116b042c40eac7d1e83d2ac.jpeg

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

总结

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

f8e57ab7c9b9b9b272d2c87d7f10289a.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值