本文详细介绍了以太坊中的staticcall操作,解释了其与常规call的区别,及其在防止状态变更中的应用。同时,文章也讨论了staticcall的安全性问题,如拒绝服务攻击和重入攻击,并提供了代码示例来说明其使用方法。
Staticcall 类似于常规的以太坊调用,不同的是,如果发生状态更改,它将回滚。它不能用于转账以太币。无论是 EVM 操作码、Yul 汇编函数还是 Solidity 内置函数,都称为 staticcall。
Staticcall 是在 EIP 214 中引入的,该提案于 2017 年作为 Byzantium 硬分叉的一部分被添加到以太坊中。对于那些只需要返回值而不希望有状态更改的函数,它增加了一层安全性。如果被调用的合约导致状态更改,Staticcall 将回滚,这些状态更改包括:记录事件、发送以太币、创建合约、销毁合约或设置存储变量。读取存储变量是可以的。只要不导致状态更改,不转账以太币的调用也是允许的。
Solidity 将调用外部合约的 view 函数编译为在底层使用 staticcall。
以下是一个简单的示例:
contract ERC20User {
IERC20 public token;
// 其余代码
function myBalance() public view returns (uint256 balance) {
balance = token.balanceOf(address(this));
}
function myBalanceLowLevelEquivalent() public view returns (uint256 balance) {
(bool ok, bytes memory result) = token.staticcall(abi.encodeWithSignature("balanceOf(address)", address(this)));
require(ok);
balance = abi.decode(result, (uint256));
}
}
如果 balanceOf
更改了状态,代码将回滚。
可以以下方式指定转发的 gas 数量。转发的 gas 数量受 EIP 150 中描述的 63/64 规则限制。
staticcall{gas: gasAmount}(abiEncodedArguments);
尽管 staticcall 在某种程度上比常规调用“更安全”,但这并不意味着在使用时可以忽视安全性。
Staticcall 仍然会受到 gas 消耗型拒绝服务攻击的影响。考虑上述 ERC20 代币在 balanceOf 函数中放入一个无限循环的情况。根据 EIP 150,调用合约仍然会有剩余的 gas,但只有原始数量的 1/64。
Staticcall 的另一个攻击向量是获得了错误的值。在 只读重入攻击 中,代币值通过闪电贷被临时操纵,因此任何查看值(通过 staticcall)的智能合约都可能因预言机操纵而被攻击。
在 Yul 汇编中,staticcall 的参数如下:
let ok := staticcall(gas, addressToCall, in, insize, out, outsize)
参数 out 和 outsize 是内存中返回值将被复制到的区域。然而,这两个值通常设置为零,并使用“returndatacopy”和“returndatasize”来灵活处理可变长度的返回值。
这些操作码在 EIP 211 中引入,消除了预测其他智能合约返回值长度的需求。
参见以下示例:
returndatacopy(0, 0, returndatasize())
变量 in 和 insize 指向内存中调用外部合约的(通常是 abi 编码的)数据部分。
如果 staticcall 成功,变量 ok 返回 true;如果回滚,则返回 false。回滚不会向上传递。
Staticcall 是与 以太坊预编译合约(地址 0x01 到 0x09)交互的适当方式,因为它们都不会更改状态。
以下示例将计算一个 uint 的 SHA256。请注意,此预编译直接哈希数据,而不应进行 abi 编码。
function getSha256(uint256 x) public view returns (bytes32 hashOut) {
(bool ok, bytes memory result) = address(0x02).staticcall(abi.encode(x));
require(ok);
hashOut = abi.decode(result, (bytes32));
}
参见我们的专家 Solidity 开发者训练营 以了解更多高级以太坊开发概念。我们还提供 免费的 Solidity 课程。
最初发布于 2023 年 4 月 10 日
- 原文链接: rareskills.io/post/solid...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!