01 · Name the mechanism
先别谈贵不贵:Gas 到底是什么?
Gas 是以太坊协议用来衡量一笔交易需要多少执行工作的抽象单位。它与 ETH、价格和最终账单有关,但不是同一个东西。[1]
想象一个允许陌生人上传程序的公共计算系统。程序可以做一次加法,也可以读取成千上万个状态位置,还可以因为错误写成永不结束的循环。如果系统只说“程序可以运行”,却不规定“最多运行多少”,开放性就会直接变成拒绝服务入口。
以太坊的做法不是预先判断一段任意程序会不会结束,而是给每次执行发放一个有限预算。协议为交易本身与 EVM 操作规定 Gas 成本;执行时,所有节点按照同一规则逐步扣减。预算能覆盖下一步就继续,不能覆盖就异常停止。
因此,本课最重要的定义不是“Gas 是手续费”,而是:Gas 是共识规则里的资源计量单位;Gas fee 才是为已用 Gas 支付的 ETH。 ethereum.org 也把 Gas 定义为执行特定操作所需计算工作的计量单位,并明确把防垃圾交易与防无限循环列为它存在的原因。[1]
Measure
Gas抽象工作量单位。协议规定某类操作在当前上下文里要扣多少 Gas。
work unitCeiling
Gas limit这次交易最多允许消耗多少 Gas,相当于执行的硬预算和熔断线。
maximum budgetReceipt
Gas used实际执行后计入收据的消耗量;成功和失败都可能已经使用 Gas。
actual consumptionInvoice
Gas fee用 ETH 支付的实际执行费用。它把工作量与每单位价格相乘。
gas used × effective price本课只把 Gas Fee 讲到足以分清概念。第 7 章第 2 课再系统拆解 Gas 与 Gas Fee;第 3 课再进入 Base Fee、Priority Fee 与销毁机制。
02 · One request, repeated work
你点一次确认,为什么不是“一台服务器算一次”?
以太坊没有一台被所有人信任的中央机器。许多独立执行节点会按同一规则验证区块中的交易;一次请求因此会变成许多机器重复承担的工作。
普通网站可以让自己的服务器决定是否接受某个请求,也能直接中止异常进程。以太坊不同:执行结果将改变所有人共同承认的状态,所以验证者不能只相信“打包者说算过了”。执行节点需要独立重放交易,确认状态根、Gas 消耗与成功状态都符合协议。
这带来一个关键外部性:提交者只发送一份数据,成本却由网络中的许多节点共同承担。若最昂贵的操作与最便宜的操作在协议里都“免费”,攻击者可以用很小的发送成本制造很大的全网验证成本。
Replication lens
展开同一笔交易的执行扇出
节点方格只用来显示“重复验证”的方向,不代表主网节点总数。
12 个抽象视角:发送动作只有一次,验证工作却被许多独立节点重复。Gas 要计量的是这份公共执行负担。
为什么不用“运行了几毫秒”直接计费?
时间依赖硬件、操作系统、缓存、客户端实现和当时负载。同一段字节码在不同机器上耗时不同,如果“先跑完的人说用了 8 毫秒,后跑完的人说用了 13 毫秒”,节点就无法从时间得出唯一的共识结果。
Gas 改用协议定义的抽象成本:只要输入、状态、代码与分叉规则相同,各客户端都必须算出同样的 Gas 变化。Gas schedule 尝试让这些抽象数字大致反映 CPU、内存扩展、状态访问和持久化等真实负担,但它首先必须是确定性的共识规则。
Not wall-clock time
不是秒表节点硬件不同,真实耗时无法直接进入共识;Gas 是协议层的确定性代理指标。
Not one server bill
不是单机账单它要约束的是可被许多节点重复验证的公共执行,不只是一台电脑的电费。
03 · Inside the gasometer
Gas 表如何把一笔交易变成有限过程?
交易先声明 Gas 上限,再扣除交易固有成本;EVM 每执行一个操作,都先检查剩余预算是否足够。黄皮书把 gasLimit 定义为执行这笔交易可使用的最大 Gas,且执行开始后不能再提高。[2]
Transaction gasometer
从进入区块到提交状态
签名、nonce、余额、Gas 上限与交易固有成本等先过规则检查。
交易外壳、calldata、创建行为等尚未进入合约代码就有成本。
每个 opcode 及其上下文成本都从剩余 Gas 中扣除。
正常返回、主动 REVERT,或因预算不足异常停止。
提交或回滚相应状态,并记录 status 与累计 Gas 使用量。
“每个操作都有一个固定数字”只是入门近似。有些操作成本很简单;有些取决于输入大小、内存扩展、首次还是重复访问状态、写入前后的存储值、是否创建新账户,以及调用给子执行帧分配多少 Gas。Gas schedule 是一组带上下文的计量规则,不是一张永远不变的价目表。
一笔空 calldata、无 access list、无 EIP-7702 authorization,且接收地址没有合约代码或 delegation 的普通 ETH 转账,通常以 21,000 Gas 作为交易固有成本的典型例子。若声明上限低于交易本身所需的固有 Gas,交易在执行前就无效;若固有检查通过,但合约运行到一半把预算耗尽,则是执行期的 Out of Gas。ethereum.org 对这两种情况作了明确区分。[1]
| 结果 | 什么时候发生 | 状态变化 | 剩余 Gas |
|---|---|---|---|
| 正常完成 | 所有操作完成,预算仍足够 | 提交本次成功作用域的状态 | 未使用部分不按“已用 Gas”收费 |
| 主动 REVERT | 合约发现条件不满足并执行 REVERT | 回滚当前失败作用域 | REVERT 本身不会自动吞掉全部剩余 Gas[9] |
| Out of Gas | 下一步成本超过当前执行帧剩余预算 | 回滚当前失败作用域 | 该失败执行帧获分配的 Gas 被耗尽 |
| 执行前无效 | 例如 gasLimit 低于 intrinsic gas | 根本不进入 EVM 执行 | 不会形成一笔已执行交易 |
顶层交易在执行中 OOG,会显示失败、回滚该 EVM 执行作用域的效果并消耗提供的 Gas;但发送者 nonce 已因这笔已包含交易而前进,执行资源也不会“因为状态回滚就没有发生”。在嵌套调用里,子调用 OOG 先耗尽分给该子帧的 Gas;若父合约检查失败返回值并仍有预算,它可以继续执行。不要把“任何子调用 OOG”误说成“整笔交易必然耗尽所有 Gas”。更现代的边界是:EIP-7702 authorization list 在 EVM 正文执行前处理,其中已落下的 delegation indicator 不会因为后续 OOG 或 REVERT 自动回滚。[12]
04 · Termination without prediction
协议不知道循环会不会结束,为什么仍能保证停下来?
Gas 不需要破解“任意程序是否终止”这个一般性难题。它只要求:每次继续执行都必须支付非零成本,而一次交易拿到的预算永远有限。
假设合约里写了 while (true) { counter += 1; }。程序自身没有出口。若执行免费,打包这个调用就可能让所有验证它的节点永久忙下去,后续交易也无法被验证。
有了 Gas,循环每走一轮都会执行若干需要扣减预算的操作。无论循环是恶意还是开发者手误,只要预算有限,剩余 Gas 终会小于下一步成本,EVM 就以 Out of Gas 终止当前执行帧。ethereum.org 将防止意外或恶意无限循环明确列为 Gas 的核心作用。[1]
Boundary switch
同一段死循环,切换有无预算
counter = 0
while (true) {
counter = counter + 1
}
STOP
预算随每轮执行递减;不足以支付下一步时,协议强制停止。
有限预算:协议无需预言程序的未来,只需确保继续运行会持续消耗有限资源。
终止不是免费撤销
Out of Gas 会回滚当前失败作用域里的状态写入,是为了避免留下“只执行一半”的中间状态;但已经做过的计算、读取与传播是真实资源成本。若失败可以退回全部执行成本,攻击者就能反复制造昂贵失败而无需承担代价。
这也是“失败交易为什么仍可能花费 Gas”的根本原因:状态原子性解决账本一致性,Gas 计费解决公共资源消耗,两者处理的不是同一个问题。
05 · Price the attack surface
只防死循环还不够:昂贵但会结束的程序怎么办?
攻击者不一定写无限循环。他也可以把大量状态读取、账户访问、内存扩展或密码学计算塞进会结束的交易,试图让区块验证时间远高于它消耗的 Gas。
Gas schedule 的第二个安全任务,是让协议成本与节点真实负担保持足够合理的对应。如果读取磁盘状态实际很慢,却只扣与一次简单加法相近的 Gas,攻击者就会选择这个“低估的操作”,用相同区块 Gas 制造更长验证时间。
这不是只影响某个合约的性能问题。一个有效区块必须能在网络时序要求内被其他节点下载、执行和验证;最坏情况太慢,会扩大重组风险、提高节点硬件门槛,并伤害去中心化。
协议扣很少 Gas,客户端却需要做昂贵 I/O 或计算。
把区块预算集中在性价比最高的攻击路径上。
同样的 gasUsed 对应异常长的真实处理时间。
传播、同步与重组风险上升,弱硬件节点更难跟上。
Gas 成本不是自然常数,而是可升级的安全参数
2016 年拒绝服务攻击暴露了若干状态树读取操作被低估的问题。EIP-150 随后提高 I/O 密集型操作的 Gas 成本,理由正是近期攻击表明这些操作相对真实负担定价过低。[3]
随着链上状态增长,同一个状态访问的实际负担也可能变化。EIP-1884 再次调整依赖 trie 大小的操作,并明确指出:低估会让相似 Gas 的区块出现很不稳定的执行时间。[4]
EIP-2929 又为首次“冷”访问账户或存储槽设置更高成本,同一交易里后续“热”访问更便宜,试图反映首次载入与缓存后的差异。它的动机同样回溯到 2016 年攻击,并把 Gas 上限与区块处理时间的对应关系视为目标。[5]
提高状态树读取、CALL 等操作成本,回应真实 DoS 攻击暴露的低估。
状态规模增长后,再校准 SLOAD、BALANCE 与 EXTCODEHASH。
把首次状态访问与同交易内重复访问分开计量,改善最坏情况边界。
这种校准并没有停在早期升级。Fusaka 激活的 EIP-7883 又提高了 MODEXP 预编译的最低与大输入成本,因为旧定价低估了某些模幂计算的真实处理时间,阻碍安全提高区块 Gas limit。[13]
Gas 让已纳入区块的 EVM 执行有限且有成本,但不会“消灭所有 DoS”。P2P、mempool 垃圾流量需要网络限流与传播规则;区块字节大小另有 EIP-7934 等约束;长期状态增长也不是一维 Gas 能完美解决。Opcode 的具体成本还会随升级或上下文变化,理解重定价的原因比背旧数字更重要。
06 · A budget around the budget
一笔交易有限还不够,为什么区块也要有 Gas 上限?
若每笔交易都有限,但一个区块可以塞进无限多笔交易,节点仍可能被一整个区块拖垮。区块 Gas limit 给一批交易的总执行量再加一层边界。
区块是按顺序执行的交易批次。协议要求候选交易的 Gas 上限能放进区块当时的剩余预算,并记录累计 gasUsed;区块不能让总执行消耗越过其 Gas limit。黄皮书的交易有效性条件直接约束交易 Gas 上限与区块剩余 Gas 的关系。[2]
区块 Gas limit 不是字节大小,也不是保证“每个区块恰好运行这么多 Gas”。它是执行工作量的上界。实际区块可以更空;交易实际消耗低于自己声明的上限后,剩余容量仍可用于后续交易。
每次 CALL 可把部分 Gas 分配给子调用;子帧有自己的递减余额。
发送者声明的整笔交易上限;Fusaka 后协议另设 2²⁴ Gas 的单笔硬上限。
一批交易的总执行包络;可由验证者在协议允许范围内协同调整。
2026 年的一个重要更新:单笔交易不能再吃完整个区块
Fusaka 升级已于 2025 年 12 月 3 日上线。随升级激活的 EIP-7825 把单笔交易可声明的 gasLimit 硬性限制为 2²⁴ = 16,777,216 Gas;超过上限的交易无效。这个上限独立于更大的区块 Gas limit,用来约束单笔交易的最坏验证成本并改善区块装填。[7][8]
不要把区块 Gas limit 当成永久写死的常量。验证者可以在协议规则内调整它,客户端也会围绕安全值协调默认配置。EIP-7935 为 Fusaka 协调 60M 默认值,但它是 Informational EIP,表达客户端配置与测试共识,而不是把 60M 变成永远不变的共识常数。[6][11]
Gas limit约束执行工作;交易/区块字节大小约束传播数据;Blob gas属于数据可用性的独立资源市场。它们可能共同影响容量,却不是同一把尺。本课只讨论 EVM 执行 Gas。
07 · What the meter approximates
Gas 衡量“工作”,但它不是现实世界资源的完美镜子
Gas schedule 把多种资源压缩成一个确定性标量,方便节点共识与区块装填。它是安全工程中的近似模型,不是物理定律。
不同 EVM 行为给节点造成的负担不同。简单栈运算通常便宜;内存扩展随范围增长;首次访问链上状态可能触发更昂贵的数据读取;永久写入状态还会增加长期维护负担。协议用不同规则尝试把这些差异映射到 Gas。
但一个数字不可能完美代表 CPU 时间、内存、磁盘 I/O、网络传播、状态增长与未来证明成本。客户端优化或硬件变化后,旧映射可能失真,所以 Gas schedule 需要测量、审计与升级。
Gas does measure
协议定义的执行工作交易固有成本、opcode、内存扩展、状态访问、调用与某些输入规模相关成本。
Gas does provide
确定性预算与装填单位所有节点能重算同一余额,交易与区块因此都有可验证的执行上界。
Gas does not measure
业务价值或代码质量昂贵交易不等于有用;便宜合约不等于安全。Gas 只回答资源,不回答意图。
Gas does not fix
法币价格与所有扩容问题Gas 数量与每单位 Gas 的市场价格分离;容量、安全与状态增长仍需持续升级。
为什么“计算步数”也只是一个不完整说法?
两个 opcode 都算“一步”,但一次简单加法与一次冷状态访问对客户端的成本显然不同。更准确的说法是:Gas 计量的是协议为特定操作及上下文规定的抽象成本。它常被解释为计算工作量,是因为“工作量”比“指令条数”更接近真实设计。
08 · Budget laboratory
亲手把预算调到刚好不够
下面不是主网 Gas 估算器,而是一个保留核心语义的抽象模型:初始化要成本,每轮工作要成本,最后提交也要成本;任何一步预算不足,状态就不提交。
Interactive gasometer
执行预算实验室
教学单位故意缩小,不对应真实 opcode 数字。
模型:初始化 34 Gas;每轮 7 Gas;最终提交 20 Gas。提高上限不会强迫程序花完,只是给它更高的可用边界。
刚好成功:需要 96,Gas 上限也是 96。状态提交,未使用 Gas 为 0。
从实验里读出四条真实规则
- Gas limit 是上限,不是预付后必定烧光的数量。若程序提前完成,未使用预算不会被当作 gasUsed。
- 工作量可以依赖输入与状态。循环轮数、数据大小与冷 / 热访问等都会让同一函数不同调用消耗不同。
- “只差一点”仍然是失败。最后一步提交也要 Gas;预算无法覆盖下一步时,协议不会允许半成品状态落链。
- 回滚状态不等于返还已做工作的成本。节点确实执行到失败点,资源消耗仍需由发起者承担。
09 · Read the interface correctly
钱包和区块浏览器里的 Gas 字段,应该按什么顺序读?
先看执行有没有成功,再看预算与实际消耗;最后才把 gasUsed 与有效单价组合成费用。不要只看到一个“Gas”数字就猜含义。
发送前:钱包为什么要先估算?
钱包或 RPC 节点通常会在当前状态上模拟交易,估计足以完成的 Gas。估算不是协议对未来的保证:从估算到真正执行之间,合约状态可能改变;某些分支、价格或数据规模也可能不同。好的钱包会留出合理余量,但余量不是“多付给验证者的奖金”。
把 gasLimit 调得很低,不能让一笔复杂交易“便宜完成”;它只会让交易更可能 OOG。把 gasLimit 调得很高,也不会自动让合约安全,只是允许它最多消耗更多 Gas。恶意合约、错误收款地址和危险授权属于意图与权限问题,不会被 Gas 估算替你判断。
执行后:按四步读收据
- 看 status。先确认交易成功还是失败;“已经上链”并不等于业务调用成功。
- 看 gasUsed。这是本次执行实际计量的 Gas,不是发送前的预算上限。
- 对照 gasLimit。若失败且 gasUsed 贴近上限,OOG 是重要线索,但仍需查看回滚原因与调用轨迹。
- 最后看有效单价与 fee。这一步进入下一课:工作量与每单位价格如何共同形成 ETH 费用。
Misconception 01
“Gas 就是 ETH”错。Gas 是工作量单位;ETH 是为每单位 Gas 支付的资产。
Misconception 02
“上限设高就会全花掉”错。正常完成后,费用按实际 gasUsed 与有效单价计算。
Misconception 03
“失败就不该收费”错。状态可回滚,已经被全网验证的执行工作不能被撤销。
Misconception 04
“Gas 成本永远固定”错。成本可能依赖上下文,也会在协议升级时重定价。
Misconception 05
“区块 Gas limit 是字节数”错。它是执行工作量上界;数据大小另有独立约束。
Misconception 06
“Gas 能判断交易是否值得”错。它不理解经济价值、合约意图、授权范围或骗局。
10 · Close the model
把 Gas 压缩成一条因果链
不要靠“燃料”比喻记忆。只要能从开放执行推导出计量、预算、终止与区块边界,你就真正掌握了这一课。
01 · Externality
一笔请求被许多节点复算提交者制造的是公共执行负担,不能把资源成本留给全网。
02 · Meter
协议为操作规定确定性成本节点不用比较秒表,只需按同一 schedule 扣除同一 Gas。
03 · Boundary
交易携带有限 Gas 预算预算不足就停止,因而任意代码的一次具体执行都有上界。
04 · Security
区块再约束一批交易单次和整批工作都被限制,Gas 成本还能随攻击面重新校准。
五题校准
1. 哪个定义最准确?
Gas 首先是共识计量单位;小费与有效单价属于费用机制,真实时间又不能在异构节点之间直接形成确定共识。
2. 合约出现无限循环时,Gas 如何保证一次调用会停?
Gas 不需要预测程序未来。有限预算加上持续扣减,就足以给每次具体执行设置硬边界。
3. 把 gasLimit 从 100,000 提到 200,000,正常完成的交易会怎样?
Gas limit 是允许的最大预算,不是必须消费的数量,也不评价业务安全。
4. 为什么 Gas schedule 需要升级?
EIP-150、1884 与 2929 都体现了同一原则:计量需要持续贴近最坏情况下的真实资源负担。
5. 交易 OOG 后,哪句话最可靠?
账本状态回滚与资源成本承担是两条不同规则;顶层已包含失败交易还会留下失败收据与前进的 nonce。
完成任意一题后,这里会显示进度。
11 · Glossary and primary sources
把术语钉在正确层级上
以下定义只保留本课需要的精度;具体数值与分叉规则,以当前主网规范和激活升级为准。
- Gas
- 协议用于计量交易固有成本与 EVM 执行工作的抽象单位。
- Gas schedule
- 当前分叉下,不同操作及上下文对应的 Gas 成本规则集合。
- Intrinsic gas
- 进入合约执行前,交易外壳、calldata、创建等行为先消耗的 Gas。
- gasLimit
- 交易声明的最大 Gas 预算;Fusaka 后还受 2²⁴ 的协议级单笔上限约束。
- gasUsed
- 交易执行后计入收据的实际 Gas 消耗量。
- Out of Gas · OOG
- 当前执行帧无法支付下一步成本时发生的异常终止。
- REVERT
- 主动中止并回滚当前作用域、可返回原因且不自动吞掉全部剩余 Gas 的 EVM 指令。
- Block gas limit
- 区块内一批交易可使用的总执行预算上界,不等同于字节大小。
- Cold / warm access
- 同一交易内首次访问账户或存储位置,与后续重复访问的计量差异。
- Gas fee
- gasUsed 与有效每单位 Gas 价格共同形成的 ETH 执行费用。
官方与规范原文
-
ethereum.org · Gas and fees Gas 定义、存在原因、21,000 Gas 基础示例、Gas limit 与执行期 OOG 的官方入门说明。
-
Ethereum Yellow Paper · Transaction execution gasLimit、intrinsic gas、交易有效性、状态转换、Gas 余额与收据的形式化定义。
-
EIP-150 · Gas cost changes for IO-heavy operations 2016 年 DoS 攻击后对状态树读取、CALL 等 I/O 密集操作的重定价。
-
EIP-1884 · Repricing for trie-size-dependent opcodes 状态规模增长造成旧成本失真,以及低估如何让区块执行时间不稳定。
-
EIP-2929 · Gas cost increases for state access opcodes 冷 / 热账户与存储访问、状态访问最坏成本,以及 Gas 与区块处理时间的安全关系。
-
ethereum.org · Blocks 区块 Gas 目标、Gas limit 与验证者在协议规则内调整上限的官方概览。
-
EIP-7825 · Transaction Gas Limit Cap 单笔交易 16,777,216(2²⁴)Gas 的协议级硬上限及其 DoS 安全理由。
-
ethereum.org · Fusaka Fusaka 于 2025-12-03 上线,以及 EIP-7825、区块 Gas 默认值协调和相关安全更新。
-
EIP-140 · REVERT instruction REVERT 的回滚、错误数据与“不自动消耗全部剩余 Gas”语义。
-
EIP-1559 · Fee market change Gas 工作量与 Base Fee、Priority Fee、有效单价的费用层分离;第 7 章第 3 课将深入。
-
EIP-7935 · Set default gas limit to 60M Fusaka 客户端围绕 60M 区块 Gas limit 的配置、测试与协调;性质为 Informational。
-
EIP-7702 · Set Code for EOAs Authorization list 的预执行处理、delegation indicator,以及后续执行失败时不回滚的现代边界。
-
EIP-7883 · ModExp gas cost increase Fusaka 对模幂预编译成本的再校准,展示 Gas schedule 仍在随最坏执行负担更新。
资料核对:2026-07-25 · 技术事实以已激活主网升级、EIP / Yellow Paper 与 ethereum.org 一手资料为基线。
本课严格对应目录 PDF 第 4 页“第 7 章:Gas 机制”的第一项:为什么需要 Gas:为计算计价,并防止无限循环与滥用网络资源。Gas 与 Gas Fee 的区别、Base Fee / Priority Fee 与销毁机制分别留给本章后两课。