资讯动态

EIP-7907 深度解析:将合约代码上限提升至 64KB 并为超额代码加载引入 Gas 计量

发布时间:2026/9/16 9:32:59 来源:尧图企业网站定制
EIP-7907 深度解析将合约代码上限提升至 64KB 并为超额代码加载引入 Gas 计量【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-7907Meter Contract Code Size And Increase Limit是一项处于 Draft 状态的以太坊 Core 类标准它把 EIP-170 于 2016 年引入的 24KB24576 字节合约运行时代码大小上限提升到 64KB65536 字节同时仿照 EIP-3860 的计量思路对超过 24KB 的代码加载按每个 32 字节 word 收取 2 gas 的超额费用并将 initcode 上限从 48KB 同步提升至 128KB。读完本文你将完整掌握该 EIP 的动机、参数变更、冷/热代码访问的 Gas 定价模型、状态迁移方案以及它与 EIP-170、EIP-2929、EIP-2930、EIP-3860、EIP-7702 之间的依赖关系与兼容性影响。为什么需要提高合约代码上限从 24KB 限制到 Gas 化计费EIP-170 的 24KB 上限及其代价EIP-170 在 Spurious Dragon 分叉主网FORK_BLKNUM 2,675,000中引入了MAX_CODE_SIZE 0x6000即2**14 2**13 24576字节的硬上限当合约创建初始化返回的数据长度超过MAX_CODE_SIZE字节时合约创建将以 out-of-gas 错误失败。该限制的初衷是抑制一种轻微二次方级漏洞当合约被调用时调用本身消耗恒定 Gas但该调用可能触发 O(n) 级别的成本——从磁盘读取代码、为 VM 执行预处理代码JUMPDEST 分析、以及向区块的 Merkle proof正确性证明中追加 O(n) 数据。这些成本都不直接由 Gas 补偿。在当时的 Gas 上限下尚可接受但在动态 Gas 上限可能推高区块 Gas 的背景下这会对未来验证 proof 的轻客户端造成不便因此需要硬性封顶可写入链上对象的体积。24KB 天花板对开发者的现实束缚EIP-7907 明确指出提升合约代码大小限制的首要动机是改善开发者体验。当前的 24KB 上限迫使开发者将功能拆分到多个合约引入代理proxy或基于 delegatecall 的间接层依赖 Diamond Standard 之类的架构模式——即使这些模式本身并非必要。这些变通手段会显著增加代码复杂度、部署成本和审计面。提高上限后开发者可以把更多逻辑保留在单个合约内提升可读性并通过减少不必要的跨合约调用降低 Gas 消耗同时降低新开发者入门门槛让他们无需先学习复杂的合约组合模式即可从想法直接走到部署。为什么选 64KB 作为新上限新上限被设定为 64KB而不是直接取消限制目的是保证提升 Gas 上限不会在 db 或 p2p 层产生意外副作用。以 devp2p 为例其最大数据包大小为 10MB见caps/eth.md的 basic operation 部分而 snap sync 的最大数据包甚至更低约为 96KB。将上限控制在 64KB 使得该 EIP 与现有 p2p 层假设兼容避免突破协议层约束。规格解析参数、Helper 函数与行为变更新增与更新的常量EIP-7907 定义了以下新常量NameValueDescriptionCOLD_SLOAD_COST2100由 EIP-2929 定义冷加载存储的成本WARM_STORAGE_READ_COST100由 EIP-2929 定义热加载存储的成本COLD_ACCOUNT_ACCESS_COST2600由 EIP-2929 定义冷加载账户的成本GAS_PER_CODE_WORD2对超出初始24KB部分按 word 计量的单价FORK_BLKNUMTBD该 EIP 激活的硬分叉区块号尚未确定同时更新两个既有常量NameOld ValueNew ValueDescriptionMAX_CODE_SIZE24KB0x600064KB0x10000EIP-170 设定的代码最大尺寸MAX_INITCODE_SIZE48KB0xc000128KB0x20000EIP-3860 设定的 initcode 最大尺寸恒为2 * MAX_CODE_SIZE注意MAX_INITCODE_SIZE的数值取0x10000128KB规范中沿用 EIP-3860 的模式始终与2 * MAX_CODE_SIZE保持一致。Helper 函数def ceil32(n: int) - int: return ((n 31) // 32) * 32 def excess_code_size(n: int) - int: return max(0, n - 0x6000)ceil32把字节数向上取整到 32 字节对齐excess_code_size计算超出 24KB0x6000的字节数未超出时返回 0。这是超额计费公式的两个基础构件。行为变更为代码加载引入冷/热状态EIP-7907 共包含五条核心行为变更将 EIP-170 引入的MAX_CODE_SIZE常量从 24KB0x6000字节更新为 64KB0x10000字节。为合约代码引入新的冷/热cold/warm状态。具体来说修改加载代码的操作的 Gas 调度——CALL、STATICCALL、DELEGATECALL、CALLCODE和EXTCODECOPY这些操作码在代码为冷cold状态时需在访问成本之上额外加上动态费用EXCESS_CODE_COST ceil32(excess_code_size(len(code))) * GAS_PER_CODE_WORD // 32当代码是 EIP-7702 对另一账户的委托delegation时如果目标账户代码为冷状态也应计入额外的 Gas。合约代码的变热过程受 journaling 约束可像 EIP-2930 中的其他状态预热一样在回滚revert时被撤销。将 EIP-3860 引入的MAX_INITCODE_SIZE上限从 48KB0xc000字节更新为 128KB0x10000字节。如果一个大型合约是某笔交易的入口点entry point则第 2 条中计算的费用会在执行前收取并将该合约代码标记为热。此费用不计入初始 Gas 费用initial gas fee。若发生 out-of-gas 中止执行将停止且余额不会被转移。空代码keccak() 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470始终被视为热状态。三种访问场景的 Gas 定价表场景Gas 变化仅针对加载代码的操作码触发条件冷账户 冷代码加收COLD_SLOAD_COST2100、EXCESS_CODE_COST、COLD_ACCOUNT_ACCESS_COST2600合约既不在访问列表中也未在本笔交易中先被访问过热账户 冷代码加收COLD_SLOAD_COST2100、EXCESS_CODE_COST、WARM_STORAGE_READ_COST100余额、存储已被访问过或已包含在 EIP-2930 访问列表中热账户 热代码WARM_STORAGE_READ_COST100账户代码已被访问过COLD_ACCOUNT_ACCESS_COST、COLD_SLOAD_COST、WARM_STORAGE_READ_COST均定义于 EIP-2929 的参数节。这里值得展开的是与既有状态访问定价框架的衔接。EIP-2929 在交易执行期间维护accessed_addresses与accessed_storage_keys两个集合SLOAD首次访问一个(address, storage_key)对时收取COLD_SLOAD_COST之后仅收WARM_STORAGE_READ_COSTEXT*与*CALL系列首次访问账户时收取COLD_ACCOUNT_ACCESS_COST之后收WARM_STORAGE_READ_COST。EIP-7907 在这一框架之上新增了代码冷/热维度即便账户已热例如已通过BALANCE或访问列表触达其代码本身若尚未加载过仍需为超额部分支付EXCESS_CODE_COST。而 EIP-2930 的可选访问列表机制允许交易预声明将要访问的地址与存储槽从而将冷访问降为热访问价格——这也自然适用于将大合约代码预热规避 EIP-7907 带来的额外成本。与 EIP-7702 的交互也需要特别说明。EIP-7702 引入的委托指示符0xef0100 || address使所有执行代码的操作必须加载并执行被委托地址处的代码。EIP-7907 明确当加载的代码是委托指示符时若委托目标账户的代码为冷状态则同样需要计收额外 Gas这使得大代码委托在 EOA 场景下也无法绕过计量。状态迁移账户元组新增codesize字段本 EIP 为账户元组新增一个字段codesize账户元组由原来的四个字段(nonce, balance, storage_root, code_hash)变为五个字段(nonce, balance, storage_root, code_hash, codesize)。新增该字段的原因是生产客户端使用的大多数键值数据库不允许在未实际加载 value 全部内容的情况下探查某 key 指向的 value 的大小。若没有codesize客户端为计算excess_code_size就必须先完整拉取代码这恰恰是本 EIP 试图避免的高成本路径。为避免强制全量迁移EIP-7907 规定了以下两条规则在FORK_BLKNUM或之后创建或更新的任何账户应额外将其 codesize 写入账户元组。任何不含codesize字段的账户一律假定其 codesize 小于 24KB。这条惰性迁移策略保证了分叉时既有账户无需一次性重写全部状态未迁移账户因被假定为小于 24KB其EXCESS_CODE_COST恒为 0行为与迁移前完全一致。设计权衡与 Rationale 详解为什么每 word 收 2 gasGAS_PER_CODE_WORD 2的取值用于覆盖三大类成本读取更大合约代码所需的额外磁盘 I/O为执行而预处理更大代码即JUMPDEST 分析所增加的计算资源包含更大合约的区块其 Merkle proof 体积的增长。这一计量思路与 EIP-3860 一脉相承。EIP-3860 以 geth 1.10.9 的KECCAK256性能为基线4.0GHz x86_64 CPU 上约 70 Mgas/s 的 Gas 上限目标测得 geth 的 jumpdest 分析吞吐约 1091 MB/s、每 32 字节成本约 2.0 gas从而将INITCODE_WORD_COST定为 2。EIP-7907 将同一量级的价格水平迁移到运行时代码加载上。为什么保留 24KB 免税额本 EIP 将 Gas 成本设定为超出 24KB 部分的附加成本。从简洁性看本可以采用不带硬编码下限的ceil32(contract_size) * GAS_PER_CODE_WORD // 32公式但那样会提高加载小合约24KB 以下的成本。出于保守考虑并避免抬高现有合约的加载成本公式中保留了 24KB 的免税额floor使绝大多数既有合约的加载费用保持不变。为什么EXTCODECOPY不豁免理论上EXTCODECOPY可以豁免计量因为客户端可以只加载实际请求的那部分字节码。但完整代码是区块 witness 所必需的若豁免则可能需要协议层面的改动。因此EXTCODECOPY也被纳入定价方案未来可再考虑单独 carveout豁免。为什么 initcode 上限提升到 128KBinitcode 与部署后的代码不同它不常驻状态因此在 devp2p 或 db 中不可见。但完全移除 initcode 上限可能带来不可预见的后果因此沿用 EIP-3860 确立的initcode 上限为运行时代码上限的两倍模式将其提升到 128KB。向后兼容性EIP-7907 为特定操作引入了额外 Gas 成本CALL、STATICCALL、DELEGATECALL、CALLCODE、EXTCODESIZE和EXTCODECOPY在访问冷合约代码时可能需要额外 Gas。从结构上看这与 EIP-2929 的兼容性风险模式相似——依赖固定 Gas 成本的合约可能受影响但 EIP-2929/EIP-2930 中已建立的缓解手段访问列表预热、同一交易内重复访问降温同样适用于本 EIP只要合约代码在交易中被访问过一次或通过 EIP-2930 访问列表预先声明后续访问即可按热代码计价规避超额费用。任何依赖这些操作码精确 Gas 消耗的合约例如向子调用传递固定 Gas 上限的合约都应在激活前进行审计。测试用例与参考实现规范中的待补全部分截至当前版本EIP-7907 的Test Cases与Reference Implementation章节仍为空。参考 EIP-3860 的测试思路合理的测试矩阵至少应包括加载大小恰为 24KB 的代码EXCESS_CODE_COST 0加载大小恰为 64KBMAX_CODE_SIZE与 64KB 1 字节的代码触发上限失败路径冷账户 冷代码、热账户 冷代码、热账户 热代码三种定价场景的边界EXCESS_CODE_COST与ceil32取整行为的边界如 24KB 1 字节、24KB 32 字节、24KB 33 字节大合约作为交易入口点时执行前预收费、代码预热以及 out-of-gas 中止时余额不转移的语义EIP-7702 委托目标为冷代码时的附加计费代码预热随子作用域回滚被撤销journaling/revert的行为。安全考虑EIP-7907 的核心安全立场是以 Gas 计量替代硬上限让加载大代码的成本与其实际消耗的资源成正比从而在不牺牲可用性的前提下维持对 DoS 攻击的防护。具体而言24KB 以内的代码加载成本与现状完全一致不存在回归超出部分按每 word 2 gas 计量覆盖磁盘 I/O、JUMPDEST 预处理与 Merkle proof 增长三项资源开销攻击者无法再以近乎免费的方式让验证者承受 O(n) 成本64KB 硬上限保留了协议层db、p2p、devp2p 10MB 与 snap sync ~96KB 数据包的边界假设避免 Gas 上限提升引发 p2p 层意外交易入口点为大合约时的执行前预收费 标记热设计确保大合约的加载成本在交易开始时即被锁定无法通过后续状态回滚规避。结语EIP-7907 代表了以太坊在合约大小限制问题上的一次范式转变从 EIP-170 的硬性 24KB 封顶转向更高的 64KB 上限 基于 Gas 的超额计量。它与 EIP-2929 的冷/热状态框架、EIP-2930 的访问列表、EIP-3860 的 initcode 计量、EIP-7702 的代码委托机制深度耦合构成了一套自洽的定价体系。对于开发者而言这意味着单合约可承载的逻辑量大幅提升代理与 Diamond 等组合模式的必要性显著下降对于客户端实现者而言账户元组新增codesize字段的惰性迁移方案则给出了明确的落地路径。该 EIP 目前仍为 DraftFORK_BLKNUM待定测试用例与参考实现章节尚待补充实际生效以官方后续发布为准。版权声明本文内容基于 EIP-7907 及其关联文档整理相关权利依 CC0 放弃。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价