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 |
Table of Contents
摘要
本提案在 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_COST
为0
,否则为COLD_ACCOUNT_ACCESS_COST
。 - 如果存储密钥已在
accessed_storage_keys
集中,则STORAGE_READ_COST
为WARM_STORAGE_READ_COST
,否则为COLD_STORAGE_READ_COST
。
Verkle 更改后的 Gas 成本
重要的是要考虑到在 Verkle 树更改之后,将不再需要 ACCOUNT_ACCESS_COST
,因为单个帐户的存储将分布在整个全局 trie 中。 因此,Verkle 树更改后要收取的 Gas 费用仅为 STORAGE_READ_COST
,如 Verkle 更改前的 Gas 成本 中所述。
原理
- 如果没有此 EIP,合约仍然可以选择使其整个状态公开,方法是使用一个简单地 SLOAD 并返回值的方法(示例)。 Gas 成本的复杂性可以看作是
1
x CALL 成本 +N
x SLOAD 成本。 因此,对于在帐户上使用 EXTSLOAD 操作码N
次指定的 Gas 成本,特此证明了收取1
xCOLD_ACCOUNT_ACCESS_COST
和N
xSTORAGE_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.