普通CREATE部署的合约地址与创建者nonce有关;CREATE2换了一套输入,让地址能在部署发生前确定。它的核心不是“随机挑一个好看的地址”,而是把部署条件固定后计算结果:同一个部署者、同一个32字节salt、同一份init code,会得到同一个目标地址。任何一项变化,地址都可能变化。
地址公式由四段材料组成
EIP-1014规定,CREATE2取下面四段字节拼接后做keccak256,再保留结果后20字节:
- 固定前缀0xff;
- 执行CREATE2的部署者地址;
- 32字节salt;
- init code的keccak256哈希。
固定前缀用于把CREATE2地址空间与普通交易编码分开。salt只是计算输入,不等于密码;如果工厂合约、交易或事件公开它,任何人都可以复算目标地址。
部署者不是发交易的钱包
最常见的误算,是把外部钱包地址代入“部署者”。如果钱包调用工厂合约,再由工厂执行CREATE2,公式中的部署者是工厂合约地址。换一个工厂,即使salt和字节码相同,也会得到另一个地址。
核验入口时应先确认网络与工厂地址。代币同名、地址外观相近都不能替代来源核验,可对照代币合约地址核验方法。准备与工厂交互前,还应按连接智能合约前的检查清单确认域名、链和调用对象。
init code不等于最终运行时代码
init code是创建阶段执行的代码,通常还包含构造参数;它运行后返回的字节才成为合约的runtime code。因此,两个合约即使最终运行时代码相同,只要构造参数或创建代码不同,init code哈希仍可能不同,预计算地址也会改变。
反过来,知道目标地址也不能仅凭地址推出最终代码。你还需要取得工厂实现、salt、完整init code或可重建这些材料的部署参数,然后独立计算,并在部署后读取链上codeHash核对。
| 要素 | 从哪里取得 | 误差会造成什么 |
|---|---|---|
| 链与工厂 | 官方文档、链上交易 | 部署者地址错误 |
| salt | 工厂参数、事件或协议规则 | 目标地址不同 |
| init code | 已验证源码和编译产物 | 哈希不同 |
| runtime code | 部署后的链上字节码 | 判断实际执行逻辑 |
“地址可预测”有什么实际用途
智能合约钱包可以先公布未来账户地址,用户或系统在代码部署前就把它当作标识;跨链工厂可在多个网络使用相同规则部署对应地址;协议也能先签署或建立依赖,满足条件时再完成部署。这常被称为反事实部署。
但“可以先向地址转账”不代表“资金一定能取回”。若部署条件、工厂权限、salt或init code与预期不一致,目标代码可能永远无法部署;即使成功部署,运行逻辑仍可能存在升级、管理员或资产转移权限。
地址碰撞时会发生什么
EIP-1014引用的创建碰撞规则要求:目标地址若已有非零nonce或已经有代码,新创建会失败。不能把CREATE2理解为可覆盖任意现有合约。一次失败创建也可能改变交易结果与Gas消耗,工厂是否回滚还取决于它自己的错误处理。
此外,不要把“这个地址当前没有代码”解释为普通EOA。它可能是尚未部署的CREATE2目标,也可能永远为空。向空地址发送资产之前,必须证明谁控制未来部署过程和最终代码。
可执行的验证流程
第一步,固定网络和执行CREATE2的工厂地址。第二步,从已验证实现还原salt的生成方式,注意项目可能对用户输入再次哈希。第三步,用完全相同的编译产物、链接地址和构造参数重建init code。第四步按EIP-1014公式复算。第五步部署后读取实际code,并核对实现、代理和升级权限。
若目标是代理地址,还要继续追踪implementation和admin;预计算只证明入口怎样得到,不证明入口背后的逻辑不会变化。验证交易完成情况可结合以太坊交易回执字段读取contractAddress与事件。
本文用于智能合约机制与防御性核验,不构成部署、投资或资产保管建议。不要仅凭项目给出的预测地址转入大额资产;应独立复算、检查工厂权限、审阅最终代码,并在目标网络先做小额验证。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。