空账户早已清零,为何还要明令禁止:EIP-7523 与历史包袱的收尾 图 1
空账户早已清零,为何还要明令禁止:EIP-7523 与历史包袱的收尾 · 图 1

以太坊早期有一类奇怪的账户:余额为零、nonce 为零、也没有代码,三条全空的「空账户」。它们大多诞生于自毁指令的边角行为和早年缺乏约束的交易格式,是创世年代留下的历史产物。EIP-161 在 2016 年教会了客户端「碰到就删」,主网上最后残存的空账户则在第 14049881 块被一笔专门的交易清空。按理说故事到这里就结束了,但规范里没有:只要「空账户可以存在」还写在纸面上,每一个新客户端、每一条新规则都得继续为它写边界情况。EIP-7523 就是冲着这笔尾巴去的——它提议宣布合并后的网络禁止持有空账户,让这套补丁规则正式退休。提案的官方状态是最后召集(Last Call),作者 Peter Davies,2023 年 9 月起草,依赖 EIP-161。

规范层面的债比链上的债贵

空账户在现实里已经不产生任何成本,成本全部在纸面上。EIP-161 的「触碰即删」规则本身就不直观:什么时候算触碰、转账给一个空地址会发生什么、自毁路径上如何清算,每一条都要规范写清楚、客户端实现、测试套件覆盖。更麻烦的是叠加效应——协议每演进一次,都可能造出「新规则撞上旧空账户」的新角落,这些角落在真实链上永远不会被触发,却必须有人在评审桌上讨论、在测试网里验证。提案文档里给了一个直白的观察:一个只想支持合并后区块的新实现,仅仅为了通过测试套件,就得实现一套永远不会用上的空账户处理逻辑。这就是典型的技术债:债务不在链上,在每一个后来者的维护账单里。

空账户早已清零,为何还要明令禁止:EIP-7523 与历史包袱的收尾 图 2
空账户早已清零,为何还要明令禁止:EIP-7523 与历史包袱的收尾 · 图 2

为什么选合并当刀口

禁止一条规则,需要一条清晰的时间分界。候选方案里有「以清空交易所在的第 14049881 块为界」这种更精确的选项,但 EIP-7523 选了合并区块作为切点,理由很实用:合并是一个所有人都认得的重大事件,边界好辨认,验证成本低。规范还给了免扫描的白名单——主网合并区块哈希被直接写进文档,任何创世即处于合并后状态、且创世起就适用 Spurious Dragon 之后规则的链(也就是绝大多数新 EVM 链),默认视为无空账户。剩下真正需要逐块核对的,只有老主网那一段历史。

这条线划上之后

对工具开发者来说,这个提案的价值是删代码:状态管理的分支少一类、测试用例删一捆、文档里关于「给空地址转账会不会创建幽灵账户」的注释可以整段撤下。对协议设计者来说,它清理的是一类长期干扰判断的僵尸行为——讨论未来的状态改动时,不用再替一种五年内不可能再出现的账户形态保留兼容性。当然禁令也有生效范围:它只覆盖合并后的网络,合并前的主网历史里空账户确实存在过,任何声称「以太坊从来没有空账户」的说法都不准确,冷启动同步到合并前区块的实现仍然要面对旧规则。

快速问答

问:空账户和零余额账户是一回事吗? 答:不是。有代码或有 nonce 的账户即使余额为零也是正常账户,禁令只针对「无代码、nonce 为零、余额为零」三条全空的形态。零余额是常态,三条全空才是历史异常。往一个新地址转钱之后该地址余额非零,不属于被禁对象。

问:这会影响我现在往一个新地址转钱吗? 答:不会。外部账户收到转账后 nonce 或余额至少一项非零,不属于被禁的空账户。

一次扫描的完整旅程

把「禁止」二字想象成一道安检门,就能看懂为什么刀口要选在合并。实现者最偷懒的做法是启动时全量扫一遍状态树,把每个账户头读出来检查是否三条全空——主网状态以亿计,这一扫可能要花掉数小时磁盘读取。白名单机制把扫描变成了查表:客户端只需核对链的合并区块哈希是否等于文档里那串字符,等于就直接跳过整套空账户逻辑;新建的测试链则核对创世配置里有没有塞进空地址、创世规则是否从 Spurious Dragon 之后开始。两条规则覆盖了几乎所有真实场景,剩下的小概率链各自实现自己负责。一次全量扫描换一次字符串比对,这种「用已知历史事件替代在线计算」的手法,在协议清理工程里反复出现,值得记住。

风险提示:本文讨论协议规范的历史遗留问题,不构成投资建议;跑独立 EVM 链或测试网时,创世配置的合法性请以当期客户端文档为准。