以太坊燃料费用定价机制Ethereum Gas Fee Pricing Mechanism
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
1 以太坊燃料的作用
以太坊燃料在交易过程中起着重要作用。从以太坊系统的角度通过燃料费用提高恶意交易的成本减少攻击者的攻击收益增强了以太坊交易的安全性也促使合约开发者优化设计减少合约对以太坊算力的消耗从交易发起者角度通过设定燃料相关的参数以尽可能小的代价完成交易以及通过燃料费用上限的设置防止合约自身漏洞或者调用不安全合约导致的攻击。
2 以太坊燃料的构成
以太坊交易的燃料费用GasFee是燃料价格Gasprice与实际使用燃料Gasused的乘积即GasFee = Gasprice × Gasused当实际消耗的燃料费用大于交易发起者在交易中预设的燃料上限Gaslimit时当前交易所做的所有状态修改将回滚但燃料费用不会退回。
3 以太坊燃料定价机制的缺陷
伦敦分叉之前和之后采用不同的燃料定价机制。
伦敦分叉之前燃料价格由交易发起者根据历史交易的统计值预先设定矿工选择出价高的交易打包。这种类似于拍卖的燃料价格生成机制导致四方面的低效
1交易费用水平的波动与交易的社会成本不匹配。交易发起者自主设定的燃料价格通常导致交易费用的变化远大于交易成本的变化。
2非必要的用户交易延迟。每个区块总燃料的硬性限制以及交易数量的自然波动导致交易经常需要等好几个区块才能被打包。
3低效的首次出价。交易发起者为了提高交易成功概率会设置较高的交易费用导致经常性的多支付交易费用。
4没有出块奖励时区块链变得不稳定。矿工通过挖掘“姐妹区块”的方式“偷取”交易手续费导致了区块链的不稳定。
4 伦敦分叉燃料定价机制的优化
4.1 新定价机制
为了解决以太坊燃料定价机制的缺陷EIP-1559提出了燃料费用生成机制的优化EIP-1559是伦敦分叉引入的主要变化。
EIP-1559引入每份燃料最大小费maxPriorityFeePerGas、每份燃料最大费用maxFeePerGas、每份燃料基础费用baseFeePerGas这几个新的参数。
maxPriorityFeePerGas代表每份燃料支付给矿工的最大小费。
maxFeePerGas代表每份燃料支付给矿工的最大费用包含baseFeePerGas和maxPriorityFeePerGas。
baseFeePerGas代表每份燃料的基础费用由系统自动生成且会被以太坊系统燃烧掉。
交易所消耗的燃料费用计算公式是
GasFee = Gasused × (maxFeePerGas) = Gasused × (baseFeePerGas + maxPriorityFeePerGas)。
4.2 基础燃料费的算法
go-ethereum的eip1559.go实现了基础燃料费的算法算法总结如下
伦敦分叉之后的初始基础燃料费InitialBaseFee是1Gwei基础费用变化因子BaseFeeChangeDenominator定义了区块间基础费用变化值的边界值为8弹性倍乘系数ElasticityMultiplier定义了燃料上限的最大倍乘边界值为2
父区块的燃料目标值parentGasTarget = parent.GasLimit / ElasticityMultiplier
当父区块的实际燃料值parent.GasUsed等于父区块的燃料目标值parentGasTarget时当前区块的基础费用就等于父区块的基础费用parent.BaseFee
当父区块的实际燃料值parent.GasUsed大于父区块的燃料目标值parentGasTarget时说明当前区块的基础费用应该增加以减小区块包含交易的计算量基础费用的增加值取1parent.BaseFee * gasUsedDelta / parentGasTarget / BaseFeeChangeDenominator的最大值
当父区块的实际燃料值parent.GasUsed小于父区块的燃料目标值parentGasTarget时说明当前区块的基础费用应该减小以增加区块包含交易的计算量基础费用的减小值取0parent.BaseFee * gasUsedDelta / parentGasTarget / BaseFeeChangeDenominator的最大值。
实现基础燃料费算法的代码如下
// 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)
}
parentGasTarget := parent.GasLimit / params.ElasticityMultiplier
// 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)
}
var (
num = new(big.Int)
denom = new(big.Int)
)
if parent.GasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
// max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parent.GasUsed - parentGasTarget)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(params.BaseFeeChangeDenominator))
baseFeeDelta := math.BigMax(num, common.Big1)
return num.Add(parent.BaseFee, baseFeeDelta)
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parentGasTarget - parent.GasUsed)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(params.BaseFeeChangeDenominator))
baseFee := num.Sub(parent.BaseFee, num)
return math.BigMax(baseFee, common.Big0)
}
}
5 以太坊燃料价格查询
在网站中https://ethereumprice.org/gas/可以查询到最近一周的平均燃料价格。
参考
[1] 以太坊开发文档 Gas and fees | ethereum.org
[2] 以太坊改进提议EIP-1559 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
[3] 开源以太坊客户端go-ethereum源代码eip1559.gogo-ethereum/eip1559.go at master · ethereum/go-ethereum · GitHub
[4] 以太坊燃料费用查询网站Ethereum Gas Price Charts & Historical Gas Fees – ethereumprice