staticCall
staticcall{gas: gasAmount}(abiEncodedArguments);
staticcall
外部合约函数只读数据- 函数必须被
view|pure
修饰,表明只读
- 函数必须被
- 天然适用于 预编译合约
staticcall
无法更新状态变量:- 更新合约内部的状态变量
emit event
触发链上事件- 创建其他合约
self destruct
销毁合约(合约余额强制转移到传参地址)- 转账,更新账户余额
- 调用其他未标记
pure/view
的函数 - 使用内联编码更改状态数据库
Solidity Examples
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
interface IERC20 {
function balanceOf(address) external view returns (uint256);
}
contract Token is IERC20 {
mapping(address => uint256) balance;
function mint(address addr, uint256 qty) external {
balance[addr] += qty;
}
function balanceOf(address addr) external view returns (uint256) {
return balance[addr];
}
}
contract ERC20User {
// 5837 gas cost
function myBalance(IERC20 token, address addr)
public
view
returns (uint256 balance)
{
balance = token.balanceOf(addr);
}
// 6294 gas cost
function myBalanceLowLevelEquivalent(IERC20 token, address addr)
public
view
returns (uint256 balance)
{
(bool ok, bytes memory result) = address(token).staticcall(
abi.encodeWithSignature("balanceOf(address)", addr)
);
require(ok);
balance = abi.decode(result, (uint256));
}
}
Security Issues
Denial of Service
staticCall
支持指定 gas
63/64 执行只读的调用,但是对方函数逻辑不明,存在恶意消耗 gas
的安全隐患
Read only Re-entrancy
只读函数会受到其他函数的影响
Preference
https://www.rareskills.io/post/solidity-staticcall