CREATE2:确定性合约地址

本文详细介绍了以太坊 CREATE2 操作码的规范、动机、原理和使用方法。它允许通过预先确定的合约创建参数(如发送方地址、盐值和初始化代码)来计算合约地址,即使合约尚未部署,从而支持状态通道等需要预判合约地址的场景。

规范

0xf5 处新增了一个操作码(CREATE2),它接受 4 个堆栈参数:endowment(保证金)、memory_start(内存起始)、memory_length(内存长度)、salt(盐)。它的行为与 CREATE (0xf0) 完全相同,但用于初始化合约的地址是 keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:],而不是通常的发送方-和-nonce-哈希。

CREATE2gas 方案与 CREATE 相同,但还额外增加了 hashcost,即 GSHA3WORD * ceil(len(init_code) / 32),以计入必须执行的哈希操作。hashcost 与内存扩展 gas 和 CreateGas计算最终地址和执行 init_code 之前同时扣除。

  • 0xff 是一个单字节,
  • address 始终是 20 字节,
  • salt 始终是 32 字节(一个堆栈项)。

因此,最终哈希轮的 preimage 始终是 85 字节长。

2018-08-10 的核心开发者会议决定采用上述公式。

动机

允许与链上尚不存在但可以确信最终只可能包含由特定初始化代码创建的代码的地址进行交互(无论是实际交互还是通道中的 counterfactual 交互)。这对于涉及与合约进行 counterfactual 交互的 state-channel 用例非常重要。

原理

地址公式

  • 确保使用此方案创建的地址不会与使用传统 keccak256(rlp([sender, nonce])) 公式创建的地址发生冲突,因为 0xff 只能作为数 PB 长数据的 RLP 起始字节。
  • 确保哈希 preimage 具有固定大小。

Gas 成本

由于地址计算依赖于对 init_code 进行哈希,如果执行可以重复导致对大型 init_code 进行哈希而内存扩展只支付一次,那么客户端将容易受到 DoS 攻击。此 EIP 采用与 SHA3 操作码相同的每字成本。

澄清

init_code 是在执行时生成将被放置到状态中的运行时字节码的代码,通常由高级语言用于实现“构造函数”。

此 EIP 使得冲突成为可能。冲突时的行为由 EIP-684 规定:

如果尝试创建合约(无论是由于创建交易还是 CREATE(或未来的 CREATE2)操作码),并且目标地址已具有非零 nonce 或非空代码,则创建会立即失败,其行为与 init_code 中第一个字节是无效操作码时完全相同。这从创世块开始追溯适用。

具体来说,如果 noncecode 非零,则创建操作失败。

根据 EIP-161

账户创建交易和 CREATE 操作应该在初始化代码执行之前,将 nonce 在其正常起始值之上增加一

这意味着如果在一个交易中创建了合约,nonce 会立即变为非零,其副作用是即使冲突是 init_code 本身执行的,同一交易中的冲突也总是会失败。

还应注意,SELFDESTRUCT (0xff) 对 noncecode 没有直接影响,因此合约不能在单个交易中被销毁和重新创建。

示例

示例 0

  • 地址 0x0000000000000000000000000000000000000000
  • 0x0000000000000000000000000000000000000000000000000000000000000000
  • 初始化代码 0x00
  • gas(假设没有内存扩展):32006
  • 结果:0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38

示例 1

  • 地址 0xdeadbeef00000000000000000000000000000000
  • 0x0000000000000000000000000000000000000000000000000000000000000000
  • 初始化代码 0x00
  • gas(假设没有内存扩展):32006
  • 结果:0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3

示例 2

  • 地址 0xdeadbeef00000000000000000000000000000000
  • 0x000000000000000000000000feed000000000000000000000000000000000000
  • 初始化代码 0x00
  • gas(假设没有内存扩展):32006
  • 结果:0xD04116cDd17beBE565EB2422F2497E06cC1C9833

示例 3

  • 地址 0x0000000000000000000000000000000000000000
  • 0x0000000000000000000000000000000000000000000000000000000000000000
  • 初始化代码 0xdeadbeef
  • gas(假设没有内存扩展):32006
  • 结果:0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e

示例 4

  • 地址 0x00000000000000000000000000000000deadbeef
  • 0x00000000000000000000000000000000000000000000000000000000cafebabe
  • 初始化代码 0xdeadbeef
  • gas(假设没有内存扩展):32006
  • 结果:0x60f3f640a8508fC6a86d45DF051962668E1e8AC7

示例 5

  • 地址 0x00000000000000000000000000000000deadbeef
  • 0x00000000000000000000000000000000000000000000000000000000cafebabe
  • 初始化代码 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
  • gas(假设没有内存扩展):32012
  • 结果:0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C

示例 6

  • 地址 0x0000000000000000000000000000000000000000
  • 0x0000000000000000000000000000000000000000000000000000000000000000
  • 初始化代码 0x
  • gas(假设没有内存扩展):32000
  • 结果:0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0
  • 原文链接: github.com/nerolation/EI...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Nerolation
Nerolation
江湖只有他的大名,没有他的介绍。