calldata 是什么?交易数据为什么这么贵 图 1
calldata 是什么?交易数据为什么这么贵 · 图 1

结论先说

calldata 是交易里”调用数据”字段:方法选择器(4 字节)+ 参数编码(ABI 编码的字节串)——合约”要执行什么、用什么参数”的完整描述。它的 gas 定价有一个反直觉的历史:早年 calldata 每字节极贵(15/20 gas 级别),因为”把数据塞进区块”是 miner 的存储负担;EIP-2 之后降到 16/4 gas(零字节 4、非零 16),因为”数据上链”(存储证明、DAO 参数、后来的 L2 数据)的价值被重新定价。理解 calldata 的成本逻辑,是理解”数据上链路径选型”(calldata vs 状态存储 vs blob)的基础——三条路径的价格结构完全不同,选错路径 = DApp/L2 成本结构错误。

calldata 装什么

一笔合约调用交易:to = 合约地址,data = [4 字节方法选择器][ABI 编码的参数]。选择器 = 函数签名哈希的前 4 字节(调用方与合约”对上函数”的钥匙);参数按 ABI 规则编码(定长直接放,变长带偏移/长度头)。外部调用链里 calldata 逐层传递(A 调 B 调 C,C 的 calldata 是 B 构造的)——“调用数据”和”交易数据”是两个概念:交易 calldata 进区块(有 gas 成本、永久可查),内部调用的 calldata 只在执行时存在(不进区块)。用户能控制的是”交易 calldata 的体积”(参数多/参数大 = 交易贵),内部调用的数据体积是合约代码决定的。

gas 定价:为什么”进区块的字节”单独计价

区块的容量约束有两个维度:计算(EVM 操作)与数据(区块体积/传播/存储)。calldata 是”数据维度”的直接输入——每个字节都要被全网节点接收、存储(区块永久保留 calldata)、传播。gas 规则对 calldata 按”零字节/非零字节”分别计价(非零贵,因为非零字节的”信息熵/压缩成本”更高——这是历史规则,直觉上”越难压缩的字节越贵”)。对比另外两条数据路径:一,状态存储(SSTORE):写入 gas 远高于 calldata(状态要进状态树 + 长期维护 + 每个节点持续存储),“最贵的数据路径”;二,blob(EIP-4844):专为”临时数据”定价(比 calldata 便宜一个量级,但不进状态、长期可查性依赖归档生态)——“最便宜的大数据路径”。三条路径的定价梯度(blob 低于 calldata,calldata 低于状态存储)就是”数据上链选型”的价格地图。

三种路径的选型逻辑

状态存储:适合”需要长期链上可读/可验证”的数据(账户、仓位、所有权)——贵,但”读它的是链上逻辑”(合约 SLOAD/证明)。calldata:适合”需要永久可查 + 链上处理”的交易数据(L2 的交易批次——Optimistic Rollup 的经典路径:L2 交易数据塞进 L1 交易的 calldata,任何人可永久查询 + 欺诈证明依赖它)——中等价,永久可查(区块不修剪 calldata)。blob:适合”大体积 + 临时”的数据(L2 交易批次的新一代路径、DA 类应用)——便宜,但”不进状态、长期归档依赖生态”(见归档专题)。L2 的成本演化(calldata → blob)就是这个地图上的”路径迁移”:数据量涨 → 换便宜路径 → 代价是”可查性从协议层降到生态层”。DApp 开发者选型时问三个问题:谁读(链上逻辑/链下应用/审计)、读多久(永久/挑战窗口/短期)、读多少(KB 级/MB 级)——答案直接映射到路径。

用户/开发者的成本实践

用户:交易 gas 的构成 = 内在 gas(21000 基础 + calldata 每字节)+ 执行 gas。“交易莫名贵”的常见原因:参数多/大的合约调用(calldata 体积)、或执行路径重。检查:浏览器显示的交易 data 字段体积,对照 gas 估算的”数据部分”。开发者:一,参数精简(大参数走”存槽位传索引”——calldata 里传槽位号(32 字节)而不是整个大结构;批量操作打包时注意”每字节都付钱”);二,冷启动设计(合约部署交易的 calldata = 整个字节码,大合约部署贵——“初始化器/工厂”模式拆分部署成本);三,blob 可用性(L2/DA 场景评估 blob 路径时,配套设计”数据归档”与”挑战窗口覆盖”——blob 的便宜是有前提的)。“数据体积 × 单价”的账要按”整条生命周期”算(上链 + 读取 + 归档),不是只看上链价。

常见误读

“calldata 免费/很便宜”——EIP-2 后比早年便宜,但”每字节 × 每块保留”的累计成本在大数据场景显著(L2 早期费用结构的核心项);“data 字段 = 合约代码”——交易的 data 是”调用数据”(选择器 + 参数),合约代码在”部署交易”的 data 里(部署 = 代码上链,所以部署贵);两个语境都叫 data,含义不同。“blob 便宜所以全面替代 calldata”——blob 不进状态(链上逻辑读不了 blob 内容,执行层看不到)、长期可查性弱——“需要链上读”的数据只能走状态/calldata,路径选择是”需求匹配”不是”价格优先”。

风险提示

gas 参数(calldata 单价、blob 基础费机制、状态写入分级)随升级调整,引用以当前规范/文档为准;L2 的数据路径(calldata/blob/混合)是该 L2 的架构参数,评估其费用结构时查”数据在哪 + 单价机制 + 归档策略”三项。本文为成本结构解释,不构成对任何链/L2/DApp 的费用预测或推荐;具体 gas 值以实时 gas 追踪与合约实际执行为准。

小结

一句话记忆:calldata = 交易的方法选择器 + ABI 参数,“进区块永久保留的字节”,按字节单独计价;数据上链三条路径的价格梯度(blob 低于 calldata,calldata 低于状态存储)对应”临时大体积/永久可查/长期链上可读”三种需求。选数据路径 = 回答”谁读、读多久、读多少”三问——价格最低的路径不是正确答案,需求匹配的路径才是。