以太坊的 Gas 机制是什么?如何计算和优化 Gas 费用?
Gas 是以太坊中计量计算资源消耗的单位——每笔转账、每次合约调用、每个存储操作都要消耗 Gas,用 ETH 付费。核心作用就两个:防攻击(恶意循环代码的攻击成本随计算量增长),激励验证者(处理交易就能收 Gas 费)。
Gas 费用计算方式
EIP-1559 之后公式:Gas 费 = Gas Used × (Base Fee + Priority Fee)
| 参数 | 含义 | 谁决定 |
|---|---|---|
| Base Fee | 基础费用,按区块拥堵自动调整 | 协议算法 |
| Priority Fee | 给验证者的小费,出价高排前面 | 用户自设 |
| Gas Limit | 愿意消耗的最大 Gas 量,没用完退还 | 用户自设 |
实际算一笔:转账 21,000 Gas,Base Fee 10 Gwei,Priority Fee 2 Gwei:
shell21,000 × (10 + 2) = 252,000 Gwei = 0.000252 ETH
简单转账固定 21,000 Gas。合约调用的 Gas 取决于代码复杂度:SSTORE 新写存储要 20,000 Gas,改写 5,000 Gas,加法运算只要 3 Gas——存储操作是算术的几千倍,这是优化 Gas 的核心切入点。
追问
EIP-1559 前后有什么区别?
之前是拍卖制:用户设 Gas Price,矿工挑高价先打包,手续费全部归矿工。EIP-1559 改成 Base Fee + 小费双轨制,Base Fee 由算法自动调整,且被销毁而非给矿工——这是 ETH 通缩机制的关键来源。用户端也变简单了:大部分情况只设 Priority Fee 就行,不用猜 Gas Price。
交易失败 Gas 退不退?
已消耗的不退,剩余的退还。 两种失败场景:Gas Limit 不够(out of gas)和合约 revert(比如 require 检查不通过)。无论哪种,验证者已经执行了计算,已经花掉的 Gas 是沉没成本。这也是为什么设置 Gas Limit 时要留余量——但别设太大,多余的部分不会多扣,只是暂时锁定。
开发中怎么优化 Gas 成本?
实战踩坑总结:
- 存储是最大的开销:一次 SSTORE ≈ 5000 Gas,够做几千次加法。能用 memory 和 calldata 就别碰 storage
- 变量打包存储:EVM 一个 slot 32 字节,struct 里用 uint8/uint128 把多个变量塞进一个 slot,省的不是一点
- 循环里绝对不要反复读写 storage:先读到 memory,算完一次写回
- unchecked 块省溢出检查:Solidity 0.8+ 默认安全检查,确定不溢出时 unchecked 每次省 30-80 Gas
- 事件代替链上存储:不需要合约逻辑读取的数据用 event 记录,成本是 SSTORE 的几十分之一
solidity// 贵:循环里反复读 storage function bad(uint256[] calldata ids) external { for (uint i = 0; i < ids.length; i++) { balances[msg.sender] -= ids[i]; // 每次 SLOAD + SSTORE } } // 省:读到 memory 批量处理 function good(uint256[] calldata ids) external { uint256 b = balances[msg.sender]; // 一次 SLOAD for (uint i = 0; i < ids.length; i++) { b -= ids[i]; // memory 操作 } balances[msg.sender] = b; // 一次 SSTORE }
Layer 2 对 Gas 费有什么影响?
Arbitrum、Optimism、Base 等 Rollup 把执行挪到链下,只把结果数据提交到主链,Gas 费降了 90-99%。但 L2 费用 = L2 执行费 + L1 数据发布费,拥堵时 L1 部分仍然不便宜。2024 年 Dencun 升级引入 Blob 后,L1 数据费已大幅下降,L2 平均 Gas 费从几美分降到了不到一美分。
怎么判断该设多少 Gas?
不要拍脑袋。用 eth_estimateGas RPC 先模拟交易消耗;开发时在 Hardhat 用 hardhat-gas-reporter、Foundry 用 forge test --gas-report 跑出每个函数的实际消耗。MetaMask 的建议值日常够用,但紧急交易建议手动拉高 Priority Fee 抢确认。看 Etherscan Gas Tracker 的 Base Fee 趋势图,选低谷时段(通常是 UTC 凌晨)发交易最划算。