合约能部署到”存过东西”的地址上吗?以太坊早期的答案含糊:部署检查只看 nonce 与代码长度两个量,唯独漏了存储槽。于是一小批历史账户卡在规则缝里——没有 nonce、没有代码、存储却有内容,能不能再被部署一次,各家客户端各有一套理解。EIP-7610 把这条缝焊死:任何合约创建,只要目标地址非零 nonce、非零代码或非空存储占了任意一样,直接整体回滚。本文讲这段历史边角怎么形成、规则怎么统一、为什么不选更”省事”的清空方案。
三不像账户的成因
合约创建要先确认目标”干净”。按 EIP-684 的定义,检查的是 nonce 为零且代码长度为零——没有提存储。这个口径在 2016 年 11 月 Spurious Dragon 升级前留下了破绽:当时新部署合约的 nonce 会一直留在零,如果执行顺序导致构造阶段先往地址写了存储槽,就会诞生”nonce 零、代码零、存储非空”的三不像。EIP-7610 正文明确记录:主网某一时点这样的账户有二十八个。数量小得惊人,危险却不成比例——同一笔部署交易,一套实现选择先重置存储再部署成功,另一套判定目标非空直接失败,两条路径算出的状态哈希不同,属于典型的客户端分歧素材。测试生态的分歧更直接:Reth 与 EELS 曾为通过旧测试专门实现账户重置,py-evm 则认定场景不可能发生而从未实现。同一部历史,各客户端各读各的。

四类路径,同一条规则
EIP-7610(作者 Gary Rong 与 Martin Holst Swende)是执行层硬分叉变更,措辞刻意滴水不漏:无论创建来自普通创建交易、CREATE、CREATE2 还是”任何其他原因”,目标地址满足三项非空之一就抛错回滚,且”对全部既有区块追溯适用”。追溯这两个字最要紧——它要求实现重放历史时也必须得出同样失败,旧区块不许再各自发明清理逻辑。同期的另一半工作负责现场清理:EIP-158 与 EIP-161 先后把空账户体系收拾过一轮,7610 的角色则是把”别再碰”写进规则。EIP 仓库当前记录的状态字段是 Last Call(最后召集期,公告截止日标注为 2024 年 11 月 20 日),本文据此描述规则文本、不下激活状态结论,各执行层客户端支持情况以当期文档为准。
为什么是回滚而不是重置
先清存储再部署看起来更宽容,放弃它有实打实的理由。其一,重置等于让创建行为拥有”抹掉他人历史状态”的权力,被抹内容可能正被其他协议当作登记数据,销毁语义需要一整套补偿规则,复杂度陡增。其二,部署撞上有存储的地址,绝大多数是 CREATE2 盐值碰撞或工厂算错目标——静默覆盖会把一次可排查的事故升级成不可逆的事故。其三,清空要先读后删,Gas 与日志归属都要重定义,历史重放的改造成本比回滚高。回滚的代价是那批三不像账户的存储永远躺在状态树里当化石,用少量永久冗余换全网规则的确定性,这正是以太坊处理历史惯用的交换率。
对使用者意味着什么
判断线很短:合约创建失败报出目标非空,先查地址来历而不是重试。CREATE2 场景用区块浏览器或 getStorageAt 类接口抽查目标地址的存储与历史交易;确认是盐值碰撞就换盐重算,确认是化石地址则换部署路径。反复重发同样的失败交易只会白烧 Gas——回滚规则面前没有重试玄学。
快速问答
问:EOA 之间转账会触发 7610 吗? 答:不会,规则只约束合约创建行为。
问:那二十八个地址的存储后来清掉了吗? 答:7610 选择禁止触碰而非清理;存储留在状态树里,规则只保证无人能覆盖。
问:和 EIP-3860 有什么关系? 答:两者都管部署但维度正交:3860 给初始化代码设体积上限,7610 管目标地址的状态条件。
风险提示:本文只解释协议规则与历史事实,不构成投资建议。部署与授权前请核对目标地址状态与当期规范。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。