每一次以太坊交易都在“烧钱”。掌握 GAS 优化,等同给项目装上省钱外挂。
以太坊的核心魅力是“代码即法律”,但每一次执行代码都要支付 GAS。对于 Solidity 开发者来说,写出“跑得快又便宜”的合约,不仅是技术进阶,更是商业竞争力。本文把GAS 优化技巧拆成 3 大环节、9 项细节,配合 Remix 实测与常见问答,帮助你直接把“成本”变成“利润”。
目录
- 用 Remix 透视 GAS:一招看懂 Transaction 与 Execution Cost
- 结构优化篇:创建、存储、变量排序
- 交互优化篇:输入数据、转账、调用
- 9 个最易忽略的陷阱
- FAQ:主流疑问一次答
用 Remix 透视 GAS:一招看懂 Transaction 与 Execution Cost {#用-remix-透视-gas}
在谈省钱之前,先学会看“账”。
复制合约代码
pragma solidity ^0.8.0; contract Demo { uint256 public b; function saveB(uint256 _b) external { b = _b; } }
- 在 Remix 运行
调用saveB(5)
,观察控制台(Log)里的:
指标 | 含义 | 计算公式 |
---|---|---|
Transaction Cost | 交易基础费用 + 数据大小 | 21 k + calldata cost |
Execution Cost | EVM 真正执行费用 | SSTORE、指令阶梯 |
举例:Remix 显示
- Transaction Cost:41 642
- Execution Cost:20 178
41 642 − 20 178 = 21 464(与黄皮书公式 21000 + (5×68) + (31×4) ≈ 21464 对得上)
结构优化篇:创建、存储、变量排序 {#结构优化篇}
创建合约的避坑姿势
- 不要为每条记录单独 deploy
差:批量用户各自合约,> 40 000 GAS / 份
优:统一用mapping
,< 20 000 GAS / 份
// ❌ 错:每条数据都要新建合约
contract User { /*...*/ }
// ✅ 对:所有数据放在同一份合约
mapping(address => UserProfile) public profiles;
存储优化的三字诀:少写、晚写、打包写
避免循环累加
// ❌ 每次循环都 SSTORE,一次 5 000 for (uint i = 0; i < n; ++i) count++; // ✅ 一次性存储 count += n;
- 利用“清零返现”
把变量置 0 可以获 15 000 GAS 退款(Refund),在批量结算场景尤其实用。
变量排序:32 字节打包法则
EVM 每 32 字节视为 1 个 slot。把常一起访问的变量放在同一 slot,能减少 SSTORE 次数:
// ❌ 跨 slot
uint128 a; uint8 flag; uint128 b; // a+b 两次写入
// ✅ 合 slot
uint128 a; uint128 b; uint8 flag;
交互优化篇:输入数据、转账、调用 {#交互优化篇}
压缩 calldata,直接省 30 %
每笔交易有 21 000 基础费,但含参数时按字节收费:非零 68 GAS,零字节 4 GAS。把高位不用的 0 合并进一个小技巧:
// 原本 11 个 uint256 参数 → 11×32×4 = 1 408 GAS
// 打包成 1 个 uint256 + 位运算 → 省 60 % 数据费
👉 想给 DApp 压成本?立刻体验压缩 calldata 的实战思路
转账方法 3 选 1:Gas 最少是 .transfer
.transfer
:2300 GAS 固定,失败即回滚.call
:可自定义 Gas,安全系数低.send
:同 call 但失败不抛错,多数场景需额外检查
如无复杂逻辑,优先用 .transfer
保安全与省费兼顾。
9 个最易忽略的陷阱
陷阱 | 纠正 |
---|---|
1. 在循环里 SSTORE | 改成内存变量,循环外再存 |
2. 循环内外两层 | 合并循环,减少跳转 |
3. 不同字节数组混用 | 小长度用 bytes32 ,大长度用 bytes |
4. if + revert 逻辑跑遍分支 | 用 require 短路 |
5. 废弃代码未删 | 用编译器 --optimize |
6. sha256/ripemd160 闲置 | 改用 keccak256 |
7. 滥用多重继承 | 避免回溯深度报错 |
8. 重复二次函数修饰器 | 合并成单一修饰器 |
9. 给空地址转账 | 确认地址非零,省 25 000 |
FAQ {#faq}
Q1:把函数拆成多个文件会省 GAS 吗?
不会,编译器和字节码大小有关,与文件数量无关,注释也会被剔除。
Q2:升级合约一定贵?
使用代理模式(Proxy + Impl)时,只需扭转一次 DelegateCall,实际交易费只增加 2 100 左右,却能节省后续所有升级。
Q3:部署时能预估准确 GAS 吗?
Remix 的 Gas Profiler 插件会在编译后给出“部署上限”。若想再精准,用 Anvil/Hardhat 在本地 fork 主网,跑完整脚本即可。
Q4:Cost 不仅跟代码有关,还跟链上拥堵程度?
对。GAS Price 由市场决定,可用 实时推荐表(如 Etherscan Gas Now)选低峰部署。合约逻辑层面仍靠手码优化,省下的 Gas Limit 绝不打折。
Q5:清零能给回 15 000 GAS 退款,会不会被矿工滥用?
退款有整体上限——交易后 Gas Used 的 50 %。所以退款机制是平衡,不会无限制套利。
结语:把省下的 GAS 转化为产品竞争力
以太坊网络是一张 24×7 运行的金融高速公路,省下的 GAS 就是高额利润。
跟着本文一步步实操:
- 调试工具 → 能用 Remix 算清每一笔
- 结构设计 → 从创建、存储、变量到函数,层层减费
- 交互手法 → 压缩数据、最简转账、合并循环
把优化写进团队的 Code Review Checklist,下次上线,把成本降到最低,把性能留在用户端。祝你的合约更快、更轻、更便宜。