5

There are numerous articles describing that after EIP1559 the blocks baseFeePerGas is based on the previous blocks baseFeePerGas, gasUsed and gasLimit and that it can change by a maximum of ±12.5% from block to block.

But what is the exact formula to compute the next blocks baseFeePerGas? E.g.: How is the baseFeePerGas of block 13031168 computed?

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

1 Answer 1

6

you can find the exact formula in the EIP 1559 specs:

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'

Or in the official sources:

// 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.