Coreum Fee Model
Abstract
This document specifies the feemodel
module. The module is responsible for calculating minimum gas
price required by the chain based on the parameters of fee model.
Two charts are presented below, showing how the implemented fee model behaves. Keep in mind that
data presented on those charts were generated using MaxGasPrice
set to 0.15
for better
readability, while in reality we use 62.5
.
TERMS:
- long average block gas is the EMA (exponential moving average) of gas consumed by previous
blocks using
LongEmaBlockLength
parameter for computing the EMA. - short average block gas is the EMA (exponential moving average) of gas consumed by previous
blocks using
ShortEmaBlockLength
parameter for computing the EMA. MaxGasPrice = InitialGasPrice * MaxGasPriceMultiplier
EscalationStartBlockGas = MaxBlockGas * EscalationStartFraction
The chart below presents the dependency between short average block gas and minimum gas price required by the network on next block.
There are four regions on the fee model curve:
- green - between 0 and long average block gas where gas price goes down exponentially from
InitialGasPrice
to gas price with maximum discount (InitialGasPrice * (1 - MaxDiscount)
), - red - between long average block gas and
EscalationStartBlockGas
where we offer gas price with maximum discount all the time, - yellow - between
EscalationStartBlockGas
andMaxBlockGas
where price goes up rapidly (being an output of a power function) from gas price with maximum discount toMaxGasPrice
, - blue - above
MaxBlockGas
(if it happens for any reason) where price is equal toMaxGasPrice
.
The input (x value) for that function is calculated by taking short block gas average. Price (y value) being an output of the fee model is used as the minimum gas price for the next block.
The second chart presents the model behavior over time, presenting how changes in gas consumed by
blocks affect the minimum gas price required by the network. The chart was calculated using fixed
long average block gas
equal to 5 millions.
- x axis represents block number
- left y axis is related to
ShortEMA
(red line) andLongEMA
(orange line), - right axis presents the minimum gas price computed after a particular block,
- blue line (almost completely covered by the red one) represents the raw gas consumed by blocks,
- red line is the short average block gas,
- orange line is the long average block gas,
- green line is the minimum gas price required by the network.
A few things to note:
- whenever
ShortEMA
goes aboveMaxBlockGas
price is set toMaxGasPrice
, - whenever
ShortEMA
goes aboveEscalationStartBlockGas
price starts growing rapidly up toMaxGasPrice
, - whenever
ShortEMA
is 0, price is set toInitialGasPrice
, - whenever
ShortEMA
is equal to or greater thanLongEMA
maximum discount (MaxDiscount
) is applied on top ofInitialGasPrice
, - when
ShortEMA
goes from 0 toLongEMA
price drops until price with maximum discount is reached.
State
The x/feemodel
module at the end of each block computes the minimum gas price required by the
chain for the next block.
State managed by feemodel module:
- MinGasPrice:
0x01 | -> string(minGasPrice)
- ShortEMAGas:
0x02 | -> int64(shortEMAGas)
- LongEMAGasKey:
0x03 | -> int64(longEMAGas)
MinGasPrice
Minimum gas price required by chain
ShortEMAGas
Short moving average of gas consumed by previous blocks
LongEMAGasKey
Long moving average of gas consumed by previous blocks
Keeper
The feemodel module provides a keeper providing these methods:
type Keeper interface {
// TrackedGas returns gas limits declared by transactions executed so far in current block
TrackedGas(ctx sdk.Context) int64
// TrackGas increments gas tracked for current block
TrackGas(ctx sdk.Context, gas int64)
// SetParams sets the parameters of the model
SetParams(ctx sdk.Context, params types.Params)
// GetParams gets the parameters of the model
GetParams(ctx sdk.Context) types.Params
// GetShortEMAGas retrieves average gas used by previous blocks, used as a representation of smoothed gas used by latest block
GetShortEMAGas(ctx sdk.Context) int64
// SetShortEMAGas sets average gas used by previous blocks, used as a representation of smoothed gas used by latest block
SetShortEMAGas(ctx sdk.Context, emaGas int64)
// GetLongEMAGas retrieves long average gas used by previous blocks, used for determining average block load where maximum discount is applied
GetLongEMAGas(ctx sdk.Context) int64
// SetLongEMAGas sets long average gas used by previous blocks, used for determining average block load where maximum discount is applied
SetLongEMAGas(ctx sdk.Context, emaGas int64)
// GetMinGasPrice returns current minimum gas price required by the network
GetMinGasPrice(ctx sdk.Context) sdk.DecCoin
// SetMinGasPrice sets minimum gas price required by the network on current block
SetMinGasPrice(ctx sdk.Context, minGasPrice sdk.DecCoin)
}
From all of these methods only GetMinGasPrice
should be used by other modules. All the other ones
serve internal needs of feemodel module.
Parameters
The feemodel module contains the following parameters:
InitialGasPrice
InitialGasPrice
is the minimum gas price required when block gas short average is 0. It happens
when there are no transactions being broadcasted. This value is also used to initialize gas price on
a brand-new chain.
MaxGasPriceMultiplier
MaxGasPriceMultiplier
is used to multiply InitialGasPrice
to get the minimum gas price required
when block gas short average is greater than or equal to MaxBlockGas
.This value is used to limit
gas price escalation to avoid having possible infinity gas price value otherwise.
MaxDiscount
MaxDiscount
is the maximum discount we offer on top of InitialGasPrice
if short average block
gas is between long average block gas and EscalationStartBlockGas
(EscalationStartBlockGas = MaxBlockGas * EscalationStartFraction
).
EscalationStartFraction
EscalationStartFraction
is used to multiply MaxBlockGas
to get the block gas usage where gas
price escalation starts if short average block gas is higher than this value.
MaxBlockGas
MaxBlockGas
sets the maximum capacity of a block. This is enforced on tendermint level in genesis
configuration. Once short average block gas goes above this value, gas price is a flat line equal to
MaxGasPrice
(MaxGasPrice = InitialGasPrice * MaxGasPriceMultiplier
).
ShortEmaBlockLength
ShortEmaBlockLength
defines inertia for short average long gas in EMA model. The equation is:
NewAverage = ((ShortAverageBlockLength - 1)*PreviousAverage + GasUsedByCurrentBlock) / ShortAverageBlockLength
The value might be interpreted as the number of blocks which are taken to calculate the average. It would be exactly like that in SMA model, in EMA this is an approximation.
LongEmaBlockLength
LongEmaBlockLength
defines inertia for long average block gas in EMA model. The equation is:
NewAverage = ((LongAverageBlockLength - 1)*PreviousAverage + GasUsedByCurrentBlock) / LongAverageBlockLength
The value might be interpreted as the number of blocks which are taken to calculate the average. It would be exactly like that in SMA model, in EMA this is an approximation.