Alert Source Discuss
🚧 Stagnant Standards Track: Core

EIP-6189: 别名合约

允许创建将调用转发到其他合约的合约

Authors Gavin John (@Pandapip1)
Created 2022-12-20
Discussion Link https://ethereum-magicians.org/t/eip-6190-functional-selfdestruct/12232
Requires EIP-2929, EIP-6188

摘要

本 EIP 允许使用一个魔法 nonce 将合约转换为“别名合约”。别名合约会自动将调用转发到其他合约。

动机

本 EIP 本身并不是非常有用,因为它增加了额外的计算和 gas 成本,而没有任何有用的副作用。但是,与 EIP-6190 结合使用,它可以用于使 SELFDESTRUCT 与 Verkle 树兼容。

规范

本文档中使用的关键词“MUST”,“MUST NOT”,“REQUIRED”,“SHALL”,“SHALL NOT”,“SHOULD”,“SHOULD NOT”,“RECOMMENDED”,“MAY”和“OPTIONAL”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。

定义

如果一个合约的 nonce 为 2^64-1,并且其合约代码等于 0x1,则该合约为别名合约。

前提条件

必须使用 EIP-6188 来保护魔法 nonce 值 2^64-1

操作码变更

CALL, CALLCODE, DELEGATECALL, STATICCALL, PAY 和 EOA 交易

“callee”指的是被调用或被支付的帐户。

如果 callee 的 nonce 是 2^64-1,则调用必须被转发到存储在 callee 的第 0 个存储槽中的地址(就像 callee 是存储在 callee 的第 0 个存储槽中的地址一样)。这必须重复,直到到达非别名合约。CALLER 必须保持不变。

如果链中有多个别名合约,则原始 callee 和所有后续 callees(除了最后一个)必须将其第 0 个存储槽设置为最终非别名合约的地址。然后,调用必须像往常一样转发。即使在像 STATICCALL 这样的只读上下文中,也必须发生这种情况。

例如,如果 A 是一个将调用转发到 B 的别名合约,而 B 是一个将调用转发到 C 的别名合约,那么 A 的第 0 个存储槽将被设置为 C 的地址。然后,调用将被转发到 C

最后,操作码必须像往常一样进行,使用最终的非别名合约。

CALLCALLCODEDELEGATECALLSTATICCALL 操作码和 EOA 交易必须为此类访问的每个帐户(包括最后一个帐户,以及是否未使用别名帐户)花费 25 gas,此外还要加上访问帐户所产生的所有常规成本(参见 EIP-2929)。对于每个更新了第 0 个存储槽的账户,这些操作码还必须花费额外的 5000 gas。

如果发生无限循环,则交易必须耗尽 gas 并回滚。

EXTCODEHASH, EXTCODECOPY, EXTCODESIZEBALANCE

“访问的帐户”指的是正在访问的帐户(即,正在访问其代码的帐户,或者正在访问其余额的帐户)。

CALL 系列操作码类似,如果被访问的帐户的 nonce 为 2^64-1,则被访问的帐户的地址必须替换为存储在被访问的帐户的第 0 个存储槽中的地址。这必须重复,直到到达非别名合约。

如果链中有多个别名合约,则原始被访问的帐户和所有后续被访问的帐户(除了最后一个)必须将其第 0 个存储槽设置为最终非别名合约的地址。然后,必须像往常一样替换被访问的帐户。即使在像 STATICCALL 这样的只读上下文中,也必须发生这种情况。

最后,操作码必须像往常一样进行,使用最终的非别名合约。

EXTCODEHASHEXTCODECOPYEXTCODESIZEBALANCE 操作码必须为此类访问的每个帐户(包括最后一个帐户,以及是否未使用别名帐户)花费 25 gas,此外还要加上访问帐户所产生的所有常规成本(参见 EIP-2929)。对于每个更新了第 0 个存储槽的账户,这些操作码还必须花费额外的 5000 gas。

如果发生无限循环,则交易必须耗尽 gas 并回滚。

CREATECREATE2

如果 CREATECREATE2 将在某个地址创建一个帐户(或未能创建,取决于使用的 EIP),并且该帐户的代码是 0x1,并且其 nonce 是 2^64-1,那么不是回滚,而是必须尝试在现有帐户的第 0 个存储槽中存储的地址处创建一个合约。这必须重复,直到到达非别名合约。

如果链中有多个别名合约,则原始被访问的帐户和所有后续被访问的帐户(除了最后一个)必须将其第 0 个存储槽设置为最终非别名合约的地址。

最后,操作码必须像往常一样进行,返回新创建的合约的地址。

CREATECREATE2 操作码必须为此类访问的每个帐户(包括最后一个帐户,以及是否未使用别名帐户)花费 25 gas,此外还要加上访问帐户所产生的所有常规成本(参见 EIP-2929)。对于每个更新了第 0 个存储槽的账户,这些操作码还必须花费额外的 5000 gas。

如果发生无限循环,则交易将耗尽 gas 并回滚。

ADDRESS

此操作码保持不变;ADDRESS 指向没有 nonce 为 2^64-1 的地址。

转移到零地址

转移到零地址继续具有与 CREATE 操作码相同的效果,并且将花费额外的 gas,如 CREATECREATE2 部分中所讨论的那样。

交易有效性

“origin”指的是将交易发送以进行验证的帐户。

如果 origin 的 nonce 是 2^64-1,则必须将 origin 更新为存储在当前 origin 的第 0 个存储槽中的地址(就像 origin 是存储在当前 origin 的第 0 个存储槽中的地址一样)。这必须重复,直到到达非别名合约。

如果链中有多个别名合约,则原始 origin 和所有后续 origins(除了最后一个)必须将其第 0 个存储槽设置为最终非别名合约的地址。然后,必须像往常一样转发调用。

为此类访问的每个帐户(包括最后一个帐户,以及是否未使用别名帐户)额外添加 25 gas,此外还要加上访问帐户所产生的所有常规成本(参见 EIP-2929)被添加到验证成本中。对于每个更新了第 0 个存储槽的账户,它还会花费额外的 5000 gas。

最后,验证照常进行。

RPC 端点变更

eth_getStorageAt

如果目标合约的合约代码为 0x1 且 nonce 为 2^64-1,则 eth_getStorageAt RPC 端点必须出错。

理由

25 的额外 gas 成本表示获取 nonce 并将其与给定值进行比较的成本。

修改了 eth_getStorageAt 以抛出错误,因为别名合约的特殊行为。

选择 nonce 2^64-1 是因为它是由 EIP-6188 保护的 nonce。

合约代码 0x1 是任意选择的。选择非零代码是为了防止 nonce 为 2^64-1 的非别名合约以某种方式将其代码设置为 0x0,或者 EOA 将其 nonce 设置为 2^64-1

向后兼容性

此 EIP 需要一个协议升级,因为它修改了共识规则。不应影响任何现有合约,因为它们不会具有 2^64-1 的 nonce,也不会具有合约代码 0x1

安全注意事项

如果额外的 gas 成本访问任意合约的数据或频繁停用合约,则可能导致潜在的 DoS 攻击。合约作者必须注意并相应地设计合约。可能会对执行自主销毁和复兴的现有已部署代码产生影响。

版权

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

Citation

Please cite this document as:

Gavin John (@Pandapip1), "EIP-6189: 别名合约 [DRAFT]," Ethereum Improvement Proposals, no. 6189, December 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6189.