0x01碰到的问题比如下面的代码:我们想从store合约里通过调用getValue方法来获取数据。但问题是,我们并不能确定store合约一定实现了getValue方法。很典型的一种情况是,我们需要将StoreReader不同的环境,不同的环境都有自己的store实现,一
比如下面的代码: 我们想从 store 合约里通过调用 getValue 方法来获取数据。但问题是,我们并不能确定 store 合约一定实现了 getValue 方法。很典型的一种情况是,我们需要将 StoreReader 不同的环境,不同的环境都有自己的 store 实现,一些比较老的 store 实例是没有 getValue 方法的。如果某个环境的 store 合约没有 getValue 实现,这个调用可能就会失败,并会导致其它相关联的业务操作失败。
contract StoreReader {
address store;
function readStoreValue() external view returns (uint256) {
return StoreInterface(store).getValue();
}
}
升级 store 合约 研究发现, store 合约是不可升级的,升级 store 合约,因为着要对这个合约进行整体替换。因为 store 里面存储的还有其它各种状态变量,替换合约要把这些状态变量的值一个不差的迁移过去,还是有一定风险的。
staticcall 最终想起了 staticcall 调用,这种调用当发生调用失败时并不会把交椅 revert,而是返回 bool 类型的状态,这样我们就能动态判断目标合约 store 是否实现 getValue 方法了。 示例代码如下:
function readStoreValue() external view returns (uint256) {
(bool success, bytes memory rtValue) = store.staticcall(abi.encodeWithSignature("getValue()"));
if (success) {
return (abi.decode(rtValue, (uint256)));
} else {
// return another value
}
}
需要注意的是,staticcall 返回的数据都是 bytes 类型,我们需要使用 abi.decode 对bytes 数据进行进一步的解析。
为啥不用 ERC165? 如果是全新的设计,是可以考虑 ERC165 的,现在是想着对现有代码做最小程度的改动和最大程度的兼容。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!