Documentation Index Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
Use this file to discover all available pages before exploring further.
The feemarket module from cosmos/evm implements EIP-1559 dynamic fee pricing for Cosmos SDK chains with EVM compatibility.
This is part of cosmos/evm, not standard Cosmos SDK. For conceptual understanding of EIP-1559, see EIP-1559 Fee Market .
Parameters
The module contains the following parameters (types , proto ):
Parameter Type Default Description NoBaseFeebool falseDisables EIP-1559 base fee (enables legacy pricing) BaseFeeChangeDenominatoruint32 8Controls max base fee change per block (higher = more stable) ElasticityMultiplieruint32 2Determines target block utilization (2 = 50% target) EnableHeightint64 0Block height to activate fee market (0 = genesis) BaseFeesdk.Dec 1000000000Current base fee (auto-adjusts each block) MinGasPricesdk.Dec 0Minimum gas price floor (cannot go below) MinGasMultipliersdk.Dec 0.5Minimum gas used multiplier for gas wanted
Parameter Details
Show BaseFeeChangeDenominator
Controls fee volatility by limiting the maximum change per block: Value Max Change/Block Blocks to 10x Use Case 4 ±25% ~10 blocks Testnets, rapid price discovery 8 ±12.5% ~20 blocks Ethereum standard, balanced 16 ±6.25% ~40 blocks Stable fees, production chains 32 ±3.125% ~80 blocks Very stable, enterprise chains
Show ElasticityMultiplier
Sets the target block utilization: Value Target % Behavior Recommended For 1 100% Only increases at full blocks Maximum throughput chains 2 50% Balanced (Ethereum standard) General purpose chains 4 25% Aggressive fee increases Anti-spam focused chains 10 10% Very aggressive pricing High-value transaction chains
Sets the absolute price floor: BaseFee = max(CalculatedBaseFee, MinGasPrice)
This prevents fees from dropping too low during periods of low activity, maintaining spam resistance.
sdk.Dec (LegacyDec) values are stored as strings with 18 decimal precision (cosmos-sdk ):
Human Value Stored String Formula 1 unit ”1000000000000000000” 1 × 10^18 0.5 (50%) “500000000000000000” 0.5 × 10^18 1 billion ”1000000000000000000000000000” 10^9 × 10^18
Configuration
Adjust parameters to achieve specific network behaviors (params validation ):
Goal Parameter Adjustment Effect Faster fee response base_fee_change_denominator8 → 4 2x faster adjustments (±25% vs ±12.5%) More stable fees base_fee_change_denominator8 → 16 2x slower adjustments (±6.25% vs ±12.5%) Earlier fee increases elasticity_multiplier2 → 4 Fees rise at 25% vs 50% utilization Stronger spam deterrent min_gas_priceLow → High Higher transaction cost floor
Configuration Profiles
Ethereum-Compatible
High-Volume-Stable
Aggressive-Anti-Spam
{
"no_base_fee" : false ,
"base_fee_change_denominator" : 8 , // ±12.5% max per block
"elasticity_multiplier" : 2 , // 50% target utilization
"enable_height" : 0 , // Active from genesis
"base_fee" : "1000000000000000000000" , // Starting base fee
"min_gas_price" : "1000000000000000000" , // Price floor
"min_gas_multiplier" : "500000000000000000" // 0.5 (anti-manipulation)
}
// Behavior: Standard Ethereum, balanced for general use
// 100k gas tx: ~0.1 tokens at base, up to 10x during congestion
Scenario Comparisons
Config 5 Blocks 10 Blocks 10x Time Ethereum (d=8, e=2)+34% +79% ~20 blocks Stable (d=16, e=2)+16% +34% ~40 blocks Aggressive (d=4, e=4)+101% +304% ~8 blocks
Config 5 Blocks 10 Blocks Floor Ethereum -26% -45% ~15 blocks Stable -14% -26% ~30 blocks Aggressive -61% -85% ~6 blocks
Decimal Precision Support
The module supports different token decimal configurations:
Decimals Conversion Factor Min Unit Gas Example 6 10^12 10^-12 USDC 8 10^10 10^-10 BTC-wrapped 18 1 1 ETH, most EVM
Configuration In Production
Parameters can be updated through governance proposals (msg server ):
// MsgUpdateParams structure
// Source: github.com/cosmos/evm/blob/v0.4.1/proto/cosmos/evm/feemarket/v1/tx.proto
{
"@type" : "/cosmos.evm.feemarket.v1.MsgUpdateParams" ,
"authority" : "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" ,
"params" : {
"no_base_fee" : false ,
"base_fee_change_denominator" : 16 ,
"elasticity_multiplier" : 2 ,
"enable_height" : 100000 ,
"base_fee" : "1000000000000000000000" ,
"min_gas_price" : "1000000000000000000" ,
"min_gas_multiplier" : "500000000000000000"
}
}
Submit with:
# Submit governance proposal
# Source: github.com/cosmos/evm/blob/v0.4.1/x/feemarket/keeper/msg_server.go#L17-L39
evmd tx gov submit-proposal update-feemarket-params.json \
--from < ke y > \
--deposit 1000000000stake
Best Practices
Parameter Selection by Use Case
Chain Type Denominator Elasticity MinGasPrice Why Testing/Development 8 2 Zero/Low Quick iteration Production General 8-16 2 Medium Balance stability and responsiveness High-Frequency Trading 16-32 1-2 Low Predictable fees, high throughput Enterprise/Private 32 2-3 High Maximum stability, cost predictability Gaming/Micro-tx 4-8 1 Very Low Fast adjustments, minimal fees
Block Time Correlation
Faster blocks require higher denominators to maintain stability:
Recommended Denominator = 8 × (6s / YourBlockTime)
Examples:
1s blocks → denominator ≥16 (prevents wild swings)
6s blocks → denominator = 8 (Ethereum standard)
12s blocks → denominator = 4 (can be more responsive)
Monitoring Key Metrics
Metric Formula Healthy Action if Unhealthy Fee Volatility σ(fees)/μ(fees)<20% daily Increase denominator Utilization Rate gasUsed/maxGas40-60% avg Adjust elasticity Floor Hit Rate count(fee==min)\/blocks<10% Lower min_gas_price Recovery Speed Blocks to return to baseline 20-40 Tune denominator
Integration Examples
Wallet-Integration
Fee-Monitoring
// Get current base fee from latest block
const block = await provider. getBlock ( 'latest' );
const baseFee = block.baseFeePerGas;
// Add buffer for inclusion certainty (20% buffer)
const maxFeePerGas = baseFee * 120 n / 100 n ;
const maxPriorityFeePerGas = ethers. parseUnits ( "2" , "gwei" );
// Send EIP-1559 transaction
const tx = await wallet. sendTransaction ({
type: 2 ,
maxFeePerGas,
maxPriorityFeePerGas,
to: "0x..." ,
value: ethers. parseEther ( "1.0" ),
gasLimit: 21000
});
Interfaces
EVM JSON-RPC
The fee market integrates with standard Ethereum JSON-RPC methods (RPC backend ):
Returns the current base fee as hex string. In EIP-1559 mode, returns the base fee; in legacy mode, returns the median gas price. // Request
{ "jsonrpc" : "2.0" , "method" : "eth_gasPrice" , "params" :[], "id" : 1 }
// Response
{ "jsonrpc" : "2.0" , "id" : 1 , "result" : "0x3b9aca00" } // 1 gwei in hex
Returns suggested priority fee (tip) per gas. In cosmos/evm with the experimental mempool, transactions are prioritized by effective gas tip (fees), with ties broken by arrival time. // Request
{ "jsonrpc" : "2.0" , "method" : "eth_maxPriorityFeePerGas" , "params" :[], "id" : 1 }
// Response
{ "jsonrpc" : "2.0" , "id" : 1 , "result" : "0x77359400" } // Suggested tip in wei
Returns base fee and gas utilization history for a range of blocks. Number of blocks to return (hex or decimal)
Latest block to include (“latest”, “pending”, or block number)
Array of percentiles for priority fee calculations
// Request
{
"jsonrpc" : "2.0" ,
"method" : "eth_feeHistory" ,
"params" :[ "0x5" , "latest" , [ 25 , 50 , 75 ]],
"id" : 1
}
// Response
{
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" :{
"baseFeePerGas" : [
"0x3b9aca00" ,
"0x3c9aca00" ,
"0x3d9aca00" ,
"0x3e9aca00" ,
"0x3f9aca00"
],
"gasUsedRatio" : [ 0.5 , 0.55 , 0.6 , 0.48 , 0.52 ],
"oldestBlock" : "0x1234" ,
"reward" : [
[ "0x0" , "0x0" , "0x0" ],
[ "0x0" , "0x0" , "0x0" ],
[ "0x0" , "0x0" , "0x0" ],
[ "0x0" , "0x0" , "0x0" ],
[ "0x0" , "0x0" , "0x0" ]
]
}
}
Block responses include baseFeePerGas field when EIP-1559 is enabled. {
"jsonrpc" : "2.0" ,
"id" : 1 ,
"result" :{
"number" : "0x1234" ,
"hash" : "0x..." ,
"baseFeePerGas" : "0x3b9aca00" , // Base fee for this block
// ... other block fields
}
}
Transaction Types
The fee market supports both legacy and EIP-1559 transaction types (types ):
Legacy-Transaction
EIP-1559-Transaction
{
"type" : "0x0" ,
"gasPrice" : "0x3b9aca00" , // Must be >= current base fee
"gas" : "0x5208" ,
"to" : "0x..." ,
"value" : "0x..." ,
"data" : "0x..."
}
CLI
Query-Parameters
Query-Base-Fee
Query-Block-Gas
# Query module parameters
# Source: github.com/cosmos/evm/blob/v0.4.1/x/feemarket/client/cli/query.go
evmd query feemarket params
gRPC
Query-Parameters
Query-Base-Fee
Query-Block-Gas
// Request all module parameters
// Proto: github.com/cosmos/evm/blob/v0.4.1/proto/cosmos/evm/feemarket/v1/query.proto
grpcurl -plaintext localhost:9090 feemarket.Query/Params
// Response
{
"params": {
"no_base_fee": false,
"base_fee_change_denominator": 8,
"elasticity_multiplier": 2,
"enable_height": 0,
"base_fee": "1000000000000000000000",
"min_gas_price": "1000000000000000000",
"min_gas_multiplier": "500000000000000000"
}
}
REST
Query-Parameters
Query-Base-Fee
Query-Block-Gas
# REST endpoint for parameters
# Proto: github.com/cosmos/evm/blob/v0.4.1/proto/cosmos/evm/feemarket/v1/query.proto
GET /cosmos/feemarket/v1/params
// Response
{
"params" : {
"no_base_fee" : false ,
"base_fee_change_denominator" : 8 ,
"elasticity_multiplier" : 2 ,
"enable_height" : 0 ,
"base_fee" : "1000000000000000000000" ,
"min_gas_price" : "1000000000000000000" ,
"min_gas_multiplier" : "500000000000000000"
}
}
Technical Implementation
State
The module maintains the following state (genesis proto ):
State Objects
State Object Description Key Value Store BlockGasWanted Gas wanted in the current block []byte{1}[]byte{uint64}Transient BaseFee Current base fee Params.BaseFeesdk.DecKV Params Module parameters []byte{0x00}ParamsKV
Genesis State
type GenesisState struct {
Params Params
BaseFee sdk . Dec
}
Begin Block
At the beginning of each block, the module calculates and sets the new base fee (source ):
func ( k Keeper ) BeginBlock ( ctx sdk . Context ) error {
baseFee := k. CalculateBaseFee (ctx)
// Skip if base fee is nil (not enabled)
if baseFee. IsNil () {
return nil
}
// Update the base fee in state
k. SetBaseFee (ctx, baseFee)
// Emit event with new base fee
ctx. EventManager (). EmitEvent (
sdk. NewEvent (
"fee_market" ,
sdk. NewAttribute ( "base_fee" , baseFee. String ()),
),
)
return nil
}
End Block
At the end of each block, the module updates the gas wanted for base fee calculation (source ):
func ( k Keeper ) EndBlock ( ctx sdk . Context ) error {
gasWanted := k. GetTransientGasWanted (ctx)
gasUsed := ctx. BlockGasMeter (). GasConsumedToLimit ()
// Apply MinGasMultiplier to prevent manipulation
// gasWanted = max(gasWanted * MinGasMultiplier, gasUsed)
minGasMultiplier := k. GetParams (ctx).MinGasMultiplier
limitedGasWanted := NewDec (gasWanted). Mul (minGasMultiplier)
updatedGasWanted := MaxDec (limitedGasWanted, NewDec (gasUsed)). TruncateInt ()
// Store for next block's base fee calculation
k. SetBlockGasWanted (ctx, updatedGasWanted)
ctx. EventManager (). EmitEvent (
sdk. NewEvent (
"block_gas" ,
sdk. NewAttribute ( "height" , fmt. Sprintf ( " %d " , ctx. BlockHeight ())),
sdk. NewAttribute ( "amount" , fmt. Sprintf ( " %d " , updatedGasWanted)),
),
)
return nil
}
Base Fee Calculation Algorithm
The calculation follows the EIP-1559 specification with Cosmos SDK adaptations (source , utils ):
Show View calculation implementation
func CalcGasBaseFee ( gasUsed , gasTarget , baseFeeChangeDenom uint64 ,
baseFee , minUnitGas , minGasPrice LegacyDec ) LegacyDec {
// No change if at target
if gasUsed == gasTarget {
return baseFee
}
// Calculate adjustment magnitude
delta := abs (gasUsed - gasTarget)
adjustment := baseFee. Mul (delta). Quo (gasTarget). Quo (baseFeeChangeDenom)
if gasUsed > gasTarget {
// Increase base fee (minimum 1 unit)
baseFeeDelta := MaxDec (adjustment, minUnitGas)
return baseFee. Add (baseFeeDelta)
} else {
// Decrease base fee (not below minGasPrice)
return MaxDec (baseFee. Sub (adjustment), minGasPrice)
}
}
The minUnitGas is calculated as 1 / 10^decimals to ensure minimum increments based on token precision (source ).
Keeper
The keeper manages fee market state and calculations (source ):
Method Description Usage GetBaseFee() / SetBaseFee()Current base fee Read/update during block processing GetParams() / SetParams()Module parameters Governance updates GetBlockGasWanted() / SetBlockGasWanted()Gas tracking Base fee calculation CalculateBaseFee()Compute next base fee Called in BeginBlock
The module also implements PostTxProcessing hooks for EVM transaction processing (source ).
Events
The module emits the following events (types ):
Fee Market Block Fees
Attribute Key Attribute Value height Current block height base_fee New base fee gas_wanted Total gas wanted in block gas_used Total gas used in block
Example:
{
"type" : "fee_market_block_fees" ,
"attributes" : [
{ "key" : "height" , "value" : "12345" },
{ "key" : "base_fee" , "value" : "1000000000" },
{ "key" : "gas_wanted" , "value" : "5000000" },
{ "key" : "gas_used" , "value" : "4800000" }
]
}
AnteHandlers
The module integrates with EVM transactions through the EVMMonoDecorator, which performs all fee-related validations in a single pass (source ):
EVMMonoDecorator
The primary ante handler that validates and processes EVM transaction fees (mono_decorator.go ):
Show Key validation steps
// 1. Check mempool minimum fee (for pre-London transactions)
if ctx. IsCheckTx () && ! simulate && ! isLondon {
requiredFee := mempoolMinGasPrice. Mul (gasLimit)
if fee. LT (requiredFee) {
return ErrInsufficientFee
}
}
// 2. Calculate effective fee for EIP-1559 transactions
if ethTx. Type () >= DynamicFeeTxType && baseFee != nil {
feeAmt = ethMsg. GetEffectiveFee (baseFee)
fee = NewDecFromBigInt (feeAmt)
}
// 3. Check global minimum gas price
if globalMinGasPrice. IsPositive () {
requiredFee := globalMinGasPrice. Mul (gasLimit)
if fee. LT (requiredFee) {
return ErrInsufficientFee
}
}
// 4. Track gas wanted for base fee calculation
if isLondon && baseFeeEnabled {
feeMarketKeeper. AddTransientGasWanted (ctx, gasWanted)
}
Fee Validation Functions
CheckMempoolFee
Validates transaction fees against the local mempool minimum (source ):
Show Implementation details
func CheckMempoolFee ( fee , mempoolMinGasPrice , gasLimit LegacyDec , isLondon bool ) error {
// Skip for London-enabled chains (EIP-1559 handles this)
if isLondon {
return nil
}
requiredFee := mempoolMinGasPrice. Mul (gasLimit)
if fee. LT (requiredFee) {
return ErrInsufficientFee
}
return nil
}
Note : This check is bypassed for London-enabled chains since EIP-1559 base fee mechanism handles minimum pricing.
CheckGlobalFee
Enforces the chain-wide minimum gas price set via governance (source ):
Show Implementation details
func CheckGlobalFee ( fee , globalMinGasPrice , gasLimit LegacyDec ) error {
if globalMinGasPrice. IsZero () {
return nil
}
requiredFee := globalMinGasPrice. Mul (gasLimit)
if fee. LT (requiredFee) {
return ErrInsufficientFee
}
return nil
}
For EIP-1559 transactions, if the effective price falls below MinGasPrice, users must increase the priority fee (tip) until the effective price meets the minimum. In cosmos/evm’s experimental mempool, transactions are ordered by effective gas tip (calculated as min(maxPriorityFeePerGas, maxFeePerGas - baseFee)), with higher tips getting priority. When tips are equal, transactions are ordered by arrival time (source ).
CheckGasWanted
Tracks cumulative gas wanted for base fee calculation (source ):
Show Implementation details
func CheckGasWanted ( ctx Context , feeMarketKeeper FeeMarketKeeper , tx Tx , isLondon bool ) error {
if ! isLondon || ! feeMarketKeeper. GetBaseFeeEnabled (ctx) {
return nil
}
gasWanted := tx. GetGas ()
blockGasLimit := BlockGasLimit (ctx)
// Reject if tx exceeds block limit
if gasWanted > blockGasLimit {
return ErrOutOfGas
}
// Add to cumulative gas wanted for base fee adjustment
feeMarketKeeper. AddTransientGasWanted (ctx, gasWanted)
return nil
}
This cumulative gas wanted is used at the end of the block to calculate the next block’s base fee.
Module Distinctions
cosmos/evm vs Standard Cosmos SDK
This fee market module from cosmos/evm differs from standard Cosmos SDK fee handling:
Aspect Standard Cosmos SDK cosmos/evm Feemarket Fee Model Static, validator-configured min gas prices Dynamic EIP-1559 base fee Price Discovery Manual adjustment by validators Automatic based on utilization Transaction Types Cosmos SDK Tx only Both Cosmos & Ethereum txs Decimal Handling Chain-specific precision 18-decimal EVM compatibility State Storage Not tracked Base fee in state, gas in transient store Consensus Impact No consensus on fees Base fee part of consensus
Key Integration Points
The module integrates with EVM through:
AnteHandlers : Custom decorators for EVM transaction validation (source )
Hooks : PostTxProcessing for EVM state updates (source )
RPC : Ethereum JSON-RPC methods for fee queries (source )
References
Source Code
Specifications