以太坊开发者必看 | Polkadot 的 Gas 不是你以为 的 Gas——区块、交易与手续费机制拆解
原文作者:PaperMoon 团队
你写了一个 Solidity 合约,用 Revive 编译器打包,部署到 Polkadot 的 Asset Hub 上,一切顺利。然后你调了一个合约方法,Gas 消耗跟你在以太坊上估算的对不上。不是多了一点,是逻辑不一样。
这不是 bug。Polkadot 的资源计费模型从底层开始就跟以太坊走了不同的路。表面上它支持 EVM 交易格式、兼容 MetaMask、能跑你的 Solidity 代码,但"怎么算钱"这件事被重新设计过。搞清楚这套机制,能省掉你很多对着 Gas 估算发愣的时间。
一、区块结构:平行链区块,不是独立链区块
先理解一个前提:Polkadot 上的智能合约跑在 Asset Hub 上。Asset Hub 是 Polkadot 的一条系统平行链——它不是一条独立的区块链,而是挂在中继链下面的。
这意味着 Asset Hub 的区块要经过中继链验证人的审核才能最终确认。区块结构继承了平行链的所有标准组件,pallet_revive(Polkadot 上实现 EVM 兼容的核心模块)在这个基础上加了 EVM 相关的功能。
对开发者来说,直接影响是:你的合约交易不只是在一条链上被确认,而是要通过平行链 → 中继链的两层验证。好处是继承了 Polkadot 整个网络的安全性;代价是确认逻辑比以太坊多了一层。
二、交易类型:以太坊的四种格式都支持
Asset Hub 通过 `eth_transact` 接口处理以太坊格式的交易。用 MetaMask 或 ethers.js 发交易,底层走的就是这个接口。它接受原始的以太坊签名交易数据,包装成 Substrate 链上能处理的格式。
四种以太坊交易格式全部支持:
**Legacy 交易**
最原始的以太坊交易格式,手续费 = gasPrice × gasUsed。简单直接,但没有拥堵时的自适应定价。
**EIP-1559 交易**
以太坊伦敦升级引入的格式。手续费拆成 baseFee(由网络自动调节)和 priorityFee(你愿意额外付多少给出块者)。Gas 估算更可预测,是目前以太坊上最主流的交易类型。
**EIP-2930 交易**
引入了"访问列表"——你可以在交易里预先声明会访问哪些合约地址和存储槽。好处是链上执行时不需要再"发现"这些访问,Gas 消耗更低。在 Polkadot 上同样有效。
**EIP-4844 交易**
为 L2 Rollup 设计的 blob 交易格式,在交易里塞入一块专用数据空间。Polkadot 的 Asset Hub 也支持这种格式。
这四种格式每一种都有签名和未签名两种状态,验证和处理机制各自独立。
三、手续费核心差异:从一维 Gas 到三维资源计量
这是跟以太坊最不一样的地方。
以太坊怎么算
以太坊用一个数字衡量所有东西:Gas。不管你的操作是计算密集型(循环一百万次)还是存储密集型(写一大堆状态),都统一折算成 Gas 单位,乘以 Gas Price 就是手续费。
简单,但粗糙。一次计算操作和一次存储写入对网络的压力完全不同——计算是一次性的,存储是永久的——但在 Gas 模型里它们被混在一起了。
Polkadot 怎么算
Polkadot 把"一次操作消耗多少资源"拆成了三个独立维度:
| 维度 | 对应什么 | 类比 |
|---|---|---|
| ref_time | 计算时间 | 以太坊的 Gas,衡量 CPU 消耗 |
| proof_size | 验证证明大小 | 以太坊没有的概念——衡量验证人验证这笔交易需要多大的状态证明 |
| storage_deposit | 存储押金 | 类似以太坊的存储 Gas,但机制完全不同——是押金制,释放存储时退还 |
逐个拆开来说。
ref_time:你的代码跑了多久
这是最接近以太坊 Gas 的维度。每个操作(加法、乘法、读取状态、调用合约)消耗一定的 ref_time,衡量的是实际的计算资源用量。
跟以太坊的 Gas 有什么不同?Polkadot 的 ref_time 做了动态缩放,计算类指令和 I/O 类指令的定价比例跟以太坊不一样。具体来说,纯计算操作相对更便宜,因为计算只是一次性的 CPU 消耗;而读写操作(涉及磁盘 I/O)定价更高,因为它对节点硬件的压力更大。
实际影响:如果你的合约是计算密集型的(大量循环、数学运算),在 Polkadot 上的手续费可能比以太坊低。如果是存储密集型的(频繁读写状态),可能不会便宜。
proof_size:验证人需要多大的证明
这个维度以太坊没有。
为什么 Polkadot 需要它?因为 Asset Hub 是一条平行链,它的区块不是由自己的节点最终确认的而是由中继链的验证人检查。验证人不持有 Asset Hub 的完整状态,他们需要一份"状态证明"来验证交易是否合法。这份证明越大,验证人的工作量越大。
所以 proof_size 衡量的是:执行你这笔交易,需要把多少状态数据打包成证明发给验证人。涉及的合约越多、读取的存储槽越多,proof_size 越大。
对开发者的启示:在以太坊上你可能不太在意一笔交易"摸了"多少状态,反正都算在 Gas 里。在 Polkadot 上,减少不必要的状态读取不仅省 ref_time,还省 proof_size——两个维度都在计费。
storage_deposit:存储是租的,不是买的
以太坊的存储模型是"一次付费,永久占用"——你写了一个 SSTORE,付了 Gas,这块存储就永远在链上了(除非你手动 SSELFDESTRUCT)。这导致以太坊的状态膨胀问题越来越严重。
Polkadot 换了一个思路:**押金制**。你的合约要占用链上存储?先交一笔押金。等你释放这块存储(删除数据、销毁合约),押金原路退还。
这意味着:
- 部署合约时,除了执行费,还需要支付一笔与合约大小相关的存储押金
- 合约运行中写入新的存储槽,需要额外押金
- 删除存储槽时,对应的押金退回
- 长期占用链上存储是有持续成本意识的——虽然不是真的按天收租,但押金锁住的 DOT 有机会成本
对习惯了以太坊的开发者来说,这个模型最大的心智转换是:你不能假设"存储是免费的长期资源"。设计合约时需要考虑存储生命周期——什么数据应该上链,什么数据应该放在链下。
四、手续费的三个组成部分
每笔交易的手续费由三部分加在一起:
**基础费用(Base Fee)**
合约部署时的存储押金 + 最低交易手续费 + 网络维护成本。这部分不管你做什么操作都要付。
**执行费用(Execution Fee)**
根据 ref_time 和 proof_size 的实际消耗计算,按网络定义的汇率折算成 DOT。这是手续费的主体部分,反映你的操作真正消耗了多少资源。
**存储费用(Storage Fee)**
新增的链上存储对应的押金。不是永久支出——释放存储时退还。
系统内部维护着 Substrate 权重(weight)和 EVM Gas 单位之间的精确换算。你用 ethers.js 估算出来的 Gas 数字,底层会被转换成 ref_time + proof_size 的组合,再折算成 DOT 计价的手续费。
五、对开发者的实际影响
别硬编码 Gas
以太坊上有些开发者习惯在合约里硬编码 Gas 数值(比如给内部调用指定固定的 Gas Limit)。在 Polkadot 上不要这样做。动态缩放意味着同一个操作在不同网络状态下的 Gas 消耗可能不同。用灵活的 Gas 估算方式,让钱包或前端动态计算。
减少不必要的状态访问
在以太坊上,读取一个存储槽是 2100 Gas(冷访问),这只是 Gas 里的一个小数字。在 Polkadot 上,同样的操作会同时增加 ref_time 和 proof_size 两个维度的消耗。如果你的合约有大量的跨合约调用和状态读取,考虑用 EIP-2930 的访问列表预声明。
合约设计要考虑存储生命周期
发 ERC-20 代币时,每个持有者地址都要占用一个存储槽。在以太坊上这是"一次性成本"。在 Polkadot 上,每个新地址的存储都需要押金。如果你的代币预期会有大量持有者,这笔押金的总量可能不小。
思路转换:能用事件(Event/Log)记录的信息就别写存储。历史数据可以放链下索引。只有合约运行时必须读取的状态才上链。
交易和合约都有资源上限
跟以太坊的 Block Gas Limit 类似,Polkadot 对单笔交易和单个合约调用都有 ref_time、proof_size 的上限。如果你的合约操作特别重(比如一次性处理大量数据),可能需要拆分成多笔交易。
以太坊用一把尺子量所有东西——简单,但也因为简单而粗糙,存储膨胀就是这个代价。Polkadot 选了三把尺子,各量各的。对开发者来说,这意味着更多的思考量——但如果你愿意理解这三个维度背后的物理含义,你能写出比以太坊上更节省资源的合约。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)