二十四千米的围墙拆到哪了:EIP-7907 与合约体积上限的十二年 图 1
二十四千米的围墙拆到哪了:EIP-7907 与合约体积上限的十二年 · 图 1

一道 2016 年划下的线

以太坊对单个合约的字节码长度有一条老规矩:最多 24576 字节。这条限制由 EIP-170 写入,随二〇一六年十一月的 Spurious Dragon 分叉激活(区块 2675000),动机当年很朴素——防止一笔交易用天文数字的合同数据把验证者拖进昂贵的哈希与存储负担。此后近十年,它长成智能合约工程里最著名的墙:功能多的项目被迫拆成多个合约互相调用,代理模式、Diamond 切分、库链接的繁荣,一半是架构审美,一半是这堵墙逼出来的空间工程学。

EIP-7907 试图做一件直接的事:把墙抬高。提案把代码上限从 24KB 提到 64KB,给运行代码上限翻倍的部署码上限同步翻倍到 128KB——这个数字游戏延续了 EIP-3860 定下的“initcode 上限是运行码两倍”的既有模式。但真正的主角不是新数字,而是它给墙加的那扇计价门。

二十四千米的围墙拆到哪了:EIP-7907 与合约体积上限的十二年 图 2
二十四千米的围墙拆到哪了:EIP-7907 与合约体积上限的十二年 · 图 2

按字收钱的逻辑

单纯抬上限等于免费发放资源,提案用计费堵这个口子:合约代码加载操作(CALL、STATICCALL、DELEGATECALL、EXTCODECOPY 这一族)在原有访问成本之上,对超过 24KB 的部分按每三十二字节一个字、每字二气加收,且只对冷代码收取——同一笔交易里第二次碰同一段代码按热价走。照提案里的数字粗算,一个贴着 64KB 上限长大的合约,每次被冷访问大约要多付两千六百气上下的超额费(三十六字节的 40KB 超额除以三十二再乘二)。这笔钱的意义不是创收而是定价:让“塞大合约”这件事的资源消耗和账单继续成比例,延续以太坊燃气模型“为消耗的资源付费”的一贯哲学。

64KB 这个刻度本身也有讲究。提案明确它不是为了功能上限而是为了让燃气预算涨上去时 p2p 层不出意外——devp2p 的消息包上限在十兆量级、快照同步的单包更小,过大的单体对象会让网络层要为最坏情况重新算账。换句话说,这是给“未来更大燃气”预留的结构常数,而不是“社区调研后的理想合约大小”。

从 48KB 到 128KB 的镜像翻倍

initcode 的翻倍走的是同一条逻辑的镜像:部署时执行的构造函数代码不永久驻留状态,但它跑一次也要花节点的资源。二〇二三年四月随上海分叉激活的 EIP-3860 给 initcode 划了 49152 字节上限并加了按字计费;7907 把它的上限跟着运行码一起抬到 128KB——两倍关系保持原样,计费公式沿用 3860 那套。对合约作者,这套数字的实际含义是:部署一个塞满逻辑的大合约不再需要先做“把构造产物切出 24KB”的杂耍,工厂类协议(CREATE2 部署器、工厂即服务的账户抽象服务)也顺带解开一类历史包袱——部署码的尺寸曾直接限制“一个地址背后能藏多少创世逻辑”。

至于状态,提案特意给空代码账户留了豁免:空代码(keccak 空串哈希)永远算热——这类账户在余额转账里出场频率极高,不该为每次转账多收一笔固定的加载费。这种细节读起来枯燥,但恰恰是这类“体积提案”最难的部分:规则好写,谁不该多付难定。

停在哪一步

截至本次核验,EIP-7907 的状态是 Draft(草案),创建于二〇二五年三月,声明依赖 EIP-170、2929、3860 与 7702 四项前作,尚未进入任何已激活分叉。客户端侧曾有工作分支在 Fusaka 的开发网里试验,随后被移出该次升级的纳入清单——从“实验分支撤下”到“提案重开讨论”,这条代码大小路线的时间线仍然开放。对读者的现实结论因此很简单:把它当一份设计得相当仔细的说明书来读,不要当既成事实来用;今天部署合约,24KB 与 49152 依然是那两道真实存在的墙,代理与切片仍是必修课。

一笔体积的算术

把数字掰开算一遍能看清这堵墙的手感。24576 字节能装 768 个三十二字字节词,按部署期每字节燃气计费,一个贴墙合约光代码 Deposit 就是天文量级——这正是“墙”曾经只是软约束的注脚:2016 年之前有人用巨型合约把一笔交易的验证成本推到离谱;EIP-170 之后,最坏情况有了常数上限,客户端的资源预算第一次能写成闭区间。EIP-7907 抬高上限但保留常数的做法,本质是在复述同一条经验:自由可以加,但自由必须带着计价器。

快速问答

问:24KB 限制现在还在吗? 答:在。EIP-170 未撤,EIP-7907 仍是草案,没有进入任何已激活分叉。

问:为什么提案先动计价再动上限? 答:上限决定最坏情况,计价决定日常成本;只抬上限等于送资源,先给超额部分装电表才能安全抬墙。

问:initcode 和运行码什么关系? 答:前者是部署时跑一次的构造代码,产物才是写进状态的运行码;一个管进门,一个管住下。

风险提示:合约设计涉及 Gas 成本与安全风险,架构迁移请经专业审计;本文不构成投资建议。