在区块链领域,Gas(燃料费) 是用来衡量和支付在网络上执行操作(如交易或智能合约)所需计算资源的一种机制。
它是防止网络滥用和资源浪费的关键组成部分,尤其在以太坊(Ethereum)中最为常见。
    #
    一、Gas的核心概念
| 术语 | 
含义 | 
| Gas | 
执行某个操作所需的“单位计算资源”。 | 
| Gas Price(Gas价格) | 
用户愿意为每单位Gas支付多少“币”(如Gwei)。 | 
| Gas Limit | 
用户愿意为某笔交易最多支付多少Gas(防止无限消耗)。 | 
| Gas Used | 
实际执行中消耗的Gas数量。 | 
 
    #
    二、对某笔交易进行分析

观察上面该笔交易, 可以发现程序能够决定的值有:
- GasLimit: gas使用量限制
 
- GasFeeMax: 每gas的价格限制
 
- MaxPriority: 支付给矿工的费用
 
这三个数据对应到DynamicFeeTx类型字段分别为:
- GasLimit -> Gas
 
- GasFeeMax -> GasFeeCap
 
- MaxPriority -> GasTipCap
 
    #
    程序如何决定这三个值的合理值呢?
    #
    GasLimit
一般转账固定21000,如果是合约调用,则使用EstimateGas估算limit, 下面是使用EstimateGas的示例。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  | 
// 这是以太坊主网的RPC地址
client, _ := ethclient.DialContext(ctx, "https://mainnet.infura.io/v3/b6bf7d3508c941499b10025c0776eaf8")
gasLimit, _ := client.EstimateGas(ctx, ethereum.CallMsg{
    From:      publicKey,
    To:        &toAddr,
    GasFeeCap: feeCap,
    GasTipCap: tipCap,
    Value:     value,
    Data:      data,
})
  | 
 
    #
    MaxPriority
矿工费用可以使用SuggestGasTipCap进行动态估算:
1
2
3
  | 
// 这是以太坊主网的RPC地址
client, _ := ethclient.DialContext(ctx, "https://mainnet.infura.io/v3/b6bf7d3508c941499b10025c0776eaf8")
maxPriority, _ := client.SuggestGasTipCap(ctx)
  | 
 
    #
    GasFeeMax
每gas的单价限制可以使用和MetaMusk(小狐狸)钱包的计算公式:
基础费用 * 1.25 + 矿工费用(gasFeeBase * 1.25) + gasFeeMaxPriority,
示例代码如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  | 
func main() {
    // 这是以太坊主网的RPC地址
    client, _ := ethclient.DialContext(ctx, "https://mainnet.infura.io/v3/b6bf7d3508c941499b10025c0776eaf8")
    // 获取基础费用()
    header, _ := client.HeaderByNumber(ctx, nil)
    baseFee := header.BaseFee
    // 获取tipCap
    tipCap, _ := client.SuggestGasTipCap(ctx)
    feeCap := FeeCapCalc(baseFee, tipCap)
}
// FeeCapCalc 计算FeeCap
func FeeCapCalc(baseFee, tipCap *big.Int) *big.Int {
    multiplier := big.NewFloat(1.25)
    feeCapF := new(big.Float).Add(new(big.Float).SetInt(baseFee), multiplier)
    feeCapF.Add(feeCapF, new(big.Float).SetInt(tipCap))
    feeCap, _ := feeCapF.Int(nil)
    return feeCap
}
  | 
 
实际交易的时候,gasPrice的值是根据链上实时的基础费用 + 设定的矿工费用来决定,
如果超过了feeCap(基础费用是动态的),交易可能会处于pending状态直到链上base+tip降低到feeCap或以下,
交易才会被成功打包。
    #
    三、如何理解三方工具的实时GAS价格呢?

使用三方工具查看GAS的实时价格推荐使用gasnow,
不推荐CoinTool的GAS实现查看面板, 最大优先费用不准确.
可以看到上面比较醒目的数字即为基础费用(gasFeeBase), 在通过代码进行转账,
如果要让代码在基础费用过高的情况下停止工作, 则可以使用baseFee来控制, 下面是示例代码:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  | 
func main() {
    client, _ := ethclient.DialContext(ctx, "https://mainnet.infura.io/v3/b6bf7d3508c941499b10025c0776eaf8")
    // 获取baseFee
    header, _ := client.HeaderByNumber(ctx, nil)
    baseFee := header.BaseFee
    if baseFee.Cmp(evmutils.EtherInt64(1)) >= 0 { // 当网络基础费用超过1Gwei时不进行工作
        return kerr.WrapTraceStack(
            fmt.Errorf("当前网络基础费用过大, 可以换个时间再重试. 基础费用: %s",
                baseFee.String(),
            ),
        )
    }
	// do something...
}
  |