Alert Source Discuss
⚠️ Draft Standards Track: Core

EIP-7819: SETDELEGATE 指令

引入一条新的指令,允许合约使用 EIP-7702 委托指定来创建克隆

Authors Hadrien Croubois (@amxx), Danno Ferrin (@shemnon)
Created 2024-11-18
Discussion Link https://ethereum-magicians.org/t/eip-7819-create-delegate/21763
Requires EIP-7702

摘要

引入一条新的指令,允许智能合约创建(和更新)与 EIP-7702 设计相匹配的委托账户。这些账户可以像 ERC-1167 克隆一样使用,但具有显著的优势。

动机

许多链上应用涉及到在不同位置创建相同代码的多个实例。这些应用通常依赖于克隆或代理来降低部署成本。

克隆,例如 ERC-1167 中描述的克隆,是包含目标地址直接在代码中的最小代码片段。这使得它们非常轻量,但也阻止了任何形式的重新配置(可升级性)。

可升级代理与克隆的不同之处在于,它们从存储中读取实现的地址。这使得它们用途更广泛,但使用起来也更昂贵。

在这两种情况下,使用 EVM 代码将接收到的调用委托给实现都存在一些缺点:

  • 在执行委托调用之前,必须将 Calldata 复制到内存中
  • 如果启用了 EOF,则用 EOF 编写的克隆和代理不支持委托给用传统 EVM 代码编写的实现,因此受到限制或可能存在危险。这鼓励了传统 EVM 代码的持续使用。

EIP-7702 引入了一种新型对象,它具有预期的行为:指示器。这些对象旨在在 EOA 的地址上实例化,但相同的行为可以被重用以在协议级别实现克隆。如果调用 SETDELEGATE 的合约允许,则使用指示器用于此用例可以在不需要存储查找的情况下提供可升级性。它还消除了与代码版本不兼容相关的任何问题。

规范

0xf6 处添加了一个新的指令 (SETDELEGATE)。

行为

执行此指令会执行以下操作:

  1. 扣除 EMPTY_ACCOUNT_COST gas
  2. 如果当前帧处于 static-mode,则停止
  3. 从操作数堆栈中弹出 salttarget
  4. location 计算为 keccak256(MAGIC ++ address ++ salt)[12:]
  5. 如果 location 处的代码不为空且不以 0xEF0100 开头(非空且不是指示器),则停止
  6. 如果 location 存在于 trie 中,则将 EMPTY_ACCOUNT_COST - BASE_COST gas 添加到全局退款计数器。
  7. location 的代码设置为 MAGIC || target,与 EIP-7702 中定义的委托过程相匹配。
    • 与 EIP-7702 类似,如果 target0x0000000000000000000000000000000000000000,则不要写入指定。清除 location 处的代码,并将 location 的代码哈希重置为空哈希 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
  8. location 推送到堆栈上

location 创建的指示器的行为与 EIP-7702 创建的指示器的行为相同。

注意:委托在操作完成后立即生效。在下一个操作执行后立即调用该地址将执行新委托的代码。

参数

Constant Value
MAGIC 0xef0100
EMPTY_ACCOUNT_COST 25000
BASE_COST 12500

理由

Gas 成本

SETDELEGATE 指令的执行涉及的活动部件比 EIP-7702 gas 成本考虑的要少:

  • 没有签名恢复
  • 没有必须在交易级别已经支付的专用 calldata
  • 没有 nonce 更新

因此,执行此指令的成本可能低于 EIP-7702。为简单起见,重用了 EIP-7702 中的数字。它们低于 CREATECREATE2 操作,使得此指令的使用对于预期用例具有竞争力。

向后兼容性

TODO

安全考虑

委托者升级和删除

重用 EIP-7702 的行为,包括如果目标为 0 则清除代码,从而可以升级甚至“删除”创建的指示器。此过程由工厂(调用 SETDELEGATE 的合约)控制(并且可以限制)。一些工厂会添加检查,以防止使用已使用的 salt 重新执行 SETDELEGATE,从而使创建的指示器不可变。其他工厂可能允许访问受限的升级,但会阻止删除。在任何情况下,关于使用 SETDELEGATE 创建的指示器的生命周期的保证由调用它的合约提供,而不是由协议提供。

委托者链接

如 EIP-7702 中所述,指示器链或循环未解决。这意味着,与克隆不同,链接是一个问题。然而,这是开发人员已经习惯的事情,因为链接代理可能导致奇怪的行为,包括无限委托循环。

工厂可能希望通过验证 target 不包含指示器来防止这种风险。这可以使用可以访问 EXTCODEHASH 的传统合约助手来实现。也可以使用其他形式的自省,例如 ACCOUNT_TYPE 指令。

抢跑初始化

与 EIP-7702 签名不同,EIP-7702 签名可以包含在任何交易中,因此如果实现不检查初始化参数的真实性,则可能导致初始化抢跑,CREATE_DELEGATION 由智能合约执行,该智能合约可以在创建委托后立即原子地执行初始化逻辑。此过程对于在创建后立即初始化克隆和代理的开发人员来说是众所周知的。

在单个交易中进行多次委托更改。

如果合约在同一个交易中执行多个 SETDELEGATE 操作,但使用相同的 salt 但目标不同,同时执行与相应地址的调用,这将在同一个交易中,且没有回滚的情况下,使一个地址具有与之关联的多个不同的代码,其中两个或多个代码被执行。这包括在交易期间多次删除/重置委托。

这种行为使用更传统的、可升级的合约已经基本可以实现。

版权

版权及相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Hadrien Croubois (@amxx), Danno Ferrin (@shemnon), "EIP-7819: SETDELEGATE 指令 [DRAFT]," Ethereum Improvement Proposals, no. 7819, November 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7819.