Alert Source Discuss
🚧 Stagnant Standards Track: Core

EIP-2330: EXTSLOAD 操作码

一个新的 EVM 操作码,用于读取外部合约存储数据。

Authors Dominic Letz (@dominicletz), Santiago Palladino (@spalladino)
Created 2019-10-29
Discussion Link https://ethereum-magicians.org/t/eip-2330-extsload-and-abi-for-lower-gas-cost-and-off-chain-apps/3733
Requires EIP-2929

摘要

本提案在 0x5c 处添加一个新的操作码 EXTSLOAD,它从堆栈中弹出两个项目:<account address> <storage key>,并推送一个项目:<storage value>。Gas 成本是帐户访问成本和基于 EIP-2929 访问列表的存储读取成本之和。

动机

虽然任何链下应用程序都可以读取所有合约的所有合约存储数据,但已部署的智能合约本身无法做到这一点。 它们必须使用合约调用进行任何交互,包括从其他合约读取数据。 此 EIP 添加了一个 EVM 操作码,可直接读取外部合约存储。

从注册表样式合约(如EIP-20s,ENS 和其他数据合约)读取数据时的 Gas 成本非常高,因为它们会产生跨合约调用成本、ABI 编码成本、解码和调度成本以及最终加载数据。 在许多情况下,被查询的底层存储只是一个简单的映射。 最重要的是,view 函数可能会 SLOAD 许多调用者不感兴趣的其他插槽,这进一步增加了 Gas 成本。 在这些情况下,直接访问存储中映射的新 EXTSLOAD 调用不仅可以将交互的 Gas 成本降低 10 倍以上,而且还可以使读取合约的 Gas 成本可预测

规范

一个新的 EVM 指令 EXTSLOAD (0x5c) 的工作方式类似于 SLOAD (0x54),但有一个额外的参数表示要从中读取的合约。

EXTSLOAD (0x5c)

EXTSLOAD 指令从堆栈中弹出 2 个值,首先是 contract,即合约地址,然后是 slot,即 contract 中的存储地址。 作为结果,EXTSLOAD 将合约 contract 的合约存储中位于存储 slot 地址处的值或当帐户 contract 不存在时将 0 推送到堆栈上。

Verkle 更改前的 Gas 成本

Verkle 树更改之前要收取的 Gas 费用指定为 ACCOUNT_ACCESS_COST + STORAGE_READ_COST,其中:

  • 如果帐户地址已在 accessed_addresses 集中,则 ACCOUNT_ACCESS_COST0,否则为 COLD_ACCOUNT_ACCESS_COST
  • 如果存储密钥已在 accessed_storage_keys 集中,则 STORAGE_READ_COSTWARM_STORAGE_READ_COST,否则为 COLD_STORAGE_READ_COST

Verkle 更改后的 Gas 成本

重要的是要考虑到在 Verkle 树更改之后,将不再需要 ACCOUNT_ACCESS_COST,因为单个帐户的存储将分布在整个全局 trie 中。 因此,Verkle 树更改后要收取的 Gas 费用仅为 STORAGE_READ_COST,如 Verkle 更改前的 Gas 成本 中所述。

原理

  • 如果没有此 EIP,合约仍然可以选择使其整个状态公开,方法是使用一个简单地 SLOAD 并返回值的方法(示例)。 Gas 成本的复杂性可以看作是 1x CALL 成本 + Nx SLOAD 成本。 因此,对于在帐户上使用 EXTSLOAD 操作码 N 次指定的 Gas 成本,特此证明了收取 1xCOLD_ACCOUNT_ACCESS_COSTNx STORAGE_READ_COST 是合理的。
  • 如果没有此 EIP,合约仍然可以使用其他合约的内部状态。 外部方可以向合约提供一个值和证明,合约可以使用 BLOCKHASH 验证该值和证明。 这仅适用于之前的区块,而不适用于最新状态(因为当前区块哈希无法在执行之前确定)。
  • 此操作码可以被视为破坏了面向对象 (OO) 模型,因为它允许读取其他合约的存储。 在通常的系统中,使用 OO 是净收益,因为机器代码没有限制,并且添加更多方法或使用单个方法来获取大量数据而调用者只需要一小部分数据几乎不会增加任何成本。 然而,在 EVM 上,存在可见的成本,即每次 SLOAD 约 0.2 美元(20 gwei 和 ETHUSD 2000)。 此外,OO 导致了对开发人员的误导性假设,即智能合约中标记为“私有”的变量以某种方式加密/不可能读取,这导致了糟糕的设计。 因此,此 EIP 在使智能合约系统更高效以及防止误解方面可能是有益的。

向后兼容性

此更改是完全向后兼容的,因为它添加了一条新指令。

安全考虑

  • 由于操作码类似于 SLOAD,因此应该很容易在各种客户端中实现。
  • 此操作码允许被调用者 A 重新进入调用者合约 B 并读取 B 的状态,并且 B 无法阻止 A 这样做。 由于这不会改变任何状态,因此不应成为安全问题。 合约通常使用重入保护,但这仅添加到写入方法。 因此,即使目前没有 EXTSLOAD,A 也可以重新进入 B 并读取任何 view 方法公开的状态,并且这还没有成为问题。

版权

CC0 下放弃版权及相关权利。

Citation

Please cite this document as:

Dominic Letz (@dominicletz), Santiago Palladino (@spalladino), "EIP-2330: EXTSLOAD 操作码 [DRAFT]," Ethereum Improvement Proposals, no. 2330, October 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2330.