【开发提效工具】gas优化报告的详细使用方法

hardhat 中使用 gas reporter 来优化 gas 的详细说明。

之前文章中提到了在 hardhat 中使用 gas reporter 来优化 gas,因为篇幅有限,所以另开一篇文章来详细介绍 gas reporter 的使用场景及优化策略。

作用

Gas Reporter 是一个 Hardhat 插件,用于分析智能合约的 Gas 消耗,帮助开发者:

  1. 量化函数成本:精确测量每个函数调用消耗的 Gas。
  2. 优化合约代码:定位高 Gas 消耗的函数,针对性优化。
  3. 预估费用:根据当前 Gas 价格估算实际费用(支持 ETH/USD 等货币单位)。

安装与配置

  1. 安装插件

    npm install --save-dev hardhat-gas-reporter
  2. 配置文件 (hardhat.config.js)

    require("hardhat-gas-reporter"); // 引入插件
    
    module.exports = {
     solidity: "0.8.20",
     gasReporter: {
       enabled: true,       // 开启报告
       currency: "USD",     // 费用单位(ETH/USD/EUR等)
       gasPrice: 20,        // Gas 单价(单位:Gwei,默认取当前网络价格)
       coinmarketcap: process.env.COINMARKETCAP_KEY, // API 获取实时价格
       outputFile: "gas-report.txt", // 输出到文件
       noColors: true,      // 文件输出时禁用颜色
       excludeContracts: ["MockToken"] // 排除特定合约
     }
    };

    运行 gas 报告

  3. 执行测试时生成报告

    npx hardhat test

    报告会在测试完成后自动打印在控制台。

  4. 示例输出

    ·----------------------------|----------------------------|-------------|----------------------------·
    |     Solidity Contract      ·          Method            ·  Min (Gas)  ·  Max (Gas)  ·  Avg (Gas)  ·
    ·----------------------------|----------------------------|-------------|-------------|-------------·
    |  MyContract                · transfer                  ·      28912  ·      51234  ·      43210  ·
    |  MyContract                · approve                   ·       2345  ·       2345  ·       2345  ·
    ·----------------------------|----------------------------|-------------|-------------|-------------·
    ·-------------------------|---------------------------|-------------·
    |  Network                ·  Eth Price (USD)          ·  Gas Price  ·
    ·-------------------------|---------------------------|-------------·
    |  sepolia                ·  $1,800                  ·  20 Gwei    ·
    ·-------------------------|---------------------------|-------------·

    报告解读

  5. 核心字段

    • Method: 合约函数名称。
    • Min/Max/Avg Gas: 单次调用消耗的 Gas 范围及平均值。
    • Eth Price: 当前 ETH 价格(需配置 coinmarketcap API)。
    • Gas Price: 当前网络的 Gas 单价(Gwei)。
    • Cost (USD): 根据 Gas 消耗和 ETH 价格计算的预估费用。
  6. 关键指标

    • Storage 操作: 存储(SSTORE/SLOAD)是 Gas 消耗的大头。
    • Calldata 使用: 减少 calldata 体积可降低 Gas(如使用 bytes 压缩数据)。
    • 循环复杂度: 避免大循环和嵌套逻辑。

      gas 优化常用策略

      1. 减少存储(Storage)操作

// 优化前:多次修改存储变量
function updateValue(uint256 newValue) public {
    value = newValue; // 第一次 SSTORE(消耗 Gas)
    lastUpdate = block.timestamp; // 第二次 SSTORE(更高 Gas)
}

// 优化后:合并存储变量或使用 Memory
struct State {
    uint256 value;
    uint256 lastUpdate;
}
State private state;

function updateValue(uint256 newValue) public {
    state = State(newValue, block.timestamp); // 单次 SSTORE
}

2. 使用常量(constant/immutable

// 优化前:每次读取需 SLOAD
address public owner;

// 优化后:编译时确定值,Gas 为 0
address public constant OWNER = 0x...;

3. 变量打包(Packing)

// 优化前:浪费存储槽
uint128 a;
uint256 b; // 单独占用一个槽
uint128 c;

// 优化后:将 a 和 c 打包到同一槽
uint128 a;
uint128 c;
uint256 b;

4. 使用 unchecked 块

// 优化前:安全但消耗更多 Gas
function increment(uint256 x) public pure returns (uint256) {
    return x + 1;
}

// 优化后:明确无需溢出检查时节省 Gas
function increment(uint256 x) public pure returns (uint256) {
    unchecked { return x + 1; }
}

5. 避免重复计算

// 优化前:重复计算相同值
function calculate(uint256 a, uint256 b) public pure {
    uint256 sum = a + b;
    require(sum > 100, "Invalid sum");
    return sum * 2;
}

// 优化后:缓存中间结果
function calculate(uint256 a, uint256 b) public pure {
    uint256 sum = a + b;
    require(sum > 100, "Invalid sum");
    uint256 result = sum * 2;
    return result;
}

之前还写过一篇gas优化必须掌握的知识点 这里可以算是对 gas 优化内容的补充,需要的同学自行查阅。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
mengbuluo222
mengbuluo222
前端开发求职中... 8年+开发经验,拥有丰富的开发经验,擅长VUE、React开发。