Eip-1559

如何計算新區塊的“每 Gas 基本費用”?

  • August 15, 2021

有很多文章描述了在 EIP1559 之後的塊baseFeePerGas是基於之前的塊baseFeePerGasgasUsed並且gasLimit它可以在每個塊之間變化最大 ±12.5%。

但是計算下一個塊的確切公式是什麼baseFeePerGas?例如:如何baseFeePerGas計算塊 13031168 的?

Block 13031167:
Gas Used: 23798810 (79.10%) +58% Gas Target
Gas Limit: 30087944
Base Fee Per Gas: 47.209136185 Gwei

Block 13031168:
Gas Used: 892841 (2.96%) -94% Gas Target
Gas Limit: 30117325
Base Fee Per Gas: 50.643305194 Gwei

您可以在 EIP 1559 規範中找到確切的公式:

https://eips.ethereum.org/EIPS/eip-1559

   # check if the base fee is correct
   if INITIAL_FORK_BLOCK_NUMBER == block.number:
       expected_base_fee_per_gas = INITIAL_BASE_FEE
   elif parent_gas_used == parent_gas_target:
       expected_base_fee_per_gas = parent_base_fee_per_gas
   elif parent_gas_used > parent_gas_target:
       gas_used_delta = parent_gas_used - parent_gas_target
       base_fee_per_gas_delta = max(parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1)
       expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta
   else:
       gas_used_delta = parent_gas_target - parent_gas_used
       base_fee_per_gas_delta = parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR
       expected_base_fee_per_gas = parent_base_fee_per_gas - base_fee_per_gas_delta
   assert expected_base_fee_per_gas == block.base_fee_per_gas, 'invalid block: base fee not correct'

或者在官方來源:

// CalcBaseFee calculates the basefee of the header.
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
   // If the current block is the first EIP-1559 block, return the InitialBaseFee.
   if !config.IsLondon(parent.Number) {
       return new(big.Int).SetUint64(params.InitialBaseFee)
   }

   var (
       parentGasTarget          = parent.GasLimit / params.ElasticityMultiplier
       parentGasTargetBig       = new(big.Int).SetUint64(parentGasTarget)
       baseFeeChangeDenominator = new(big.Int).SetUint64(params.BaseFeeChangeDenominator)
   )
   // If the parent gasUsed is the same as the target, the baseFee remains unchanged.
   if parent.GasUsed == parentGasTarget {
       return new(big.Int).Set(parent.BaseFee)
   }
   if parent.GasUsed > parentGasTarget {
       // If the parent block used more gas than its target, the baseFee should increase.
       gasUsedDelta := new(big.Int).SetUint64(parent.GasUsed - parentGasTarget)
       x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
       y := x.Div(x, parentGasTargetBig)
       baseFeeDelta := math.BigMax(
           x.Div(y, baseFeeChangeDenominator),
           common.Big1,
       )

       return x.Add(parent.BaseFee, baseFeeDelta)
   } else {
       // Otherwise if the parent block used less gas than its target, the baseFee should decrease.
       gasUsedDelta := new(big.Int).SetUint64(parentGasTarget - parent.GasUsed)
       x := new(big.Int).Mul(parent.BaseFee, gasUsedDelta)
       y := x.Div(x, parentGasTargetBig)
       baseFeeDelta := x.Div(y, baseFeeChangeDenominator)

       return math.BigMax(
           x.Sub(parent.BaseFee, baseFeeDelta),
           common.Big0,
       )
   }
}

https://github.com/ethereum/go-ethereum/blob/0a68558e7e025afebf67b81bf48ecb8b0fa7c06d/consensus/misc/eip1559.go#L54

引用自:https://ethereum.stackexchange.com/questions/107173