Skip to main content

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 mempool holds submitted transactions before they are included in a block, handling ordering, nonce gap queuing, and fee-based prioritization across both EVM and Cosmos transactions. The EVM mempool is enabled by default in evmd. For conceptual information about mempool design and architecture, see the Mempool Concepts page. The mempool setup is split across two locations:
  • evmd/mempool.goconfigureEVMMempool must be called from your app.go after setAnteHandler
  • mempool/ — the mempool implementation (EVMMempool,TxPool, Rechecker, ReapList, RecheckPool, etc)
The most common EVM Mempool, Legacy pool parameters, MinTip are exposed via app.toml and require no code changes. The legacy pool (legacypool.LegacyPool) is a port of go-ethereum’s transaction pool and handles all EVM transaction ordering and fee enforcement. Some advanced settings are not covered by app.toml, and require modifying createMempoolConfig in evmd/mempool.go. BlockGasLimit is read from consensus_params.block.max_gas in genesis.json.

Configuration Options

The Config struct controls mempool behavior:
mempool/mempool.go
type Config struct {
    LegacyPoolConfig *legacypool.Config                                // Optional: port of Geth's txpool — see Custom Legacy Pool below
    CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]  // Optional: Cosmos pool tuning — see Custom Cosmos Mempool below
    AnteHandler      sdk.AnteHandler                                   // Required: transaction validation

    BlockGasLimit    uint64                                            // Required: gas limit for block selection
    MinTip           *uint256.Int                                      // Optional: minimum tip for EVM txs

	PendingTxProposalTimeout time.Duration                             // Optional but recommended: max amount of time to allocate to fetching pending execution txs
	InsertQueueSize int                                                // Optional: how many txs can be pending insertion at once
	EnableTxTracker bool                                               // Optional: if tracking transaction inclusion metrics is enabled
}

Defaults and Fallbacks

  • If BlockGasLimit is 0, the mempool uses a fallback of 100_000_000 gas.
  • If LegacyPoolConfig is not provided, defaults from legacypool.DefaultConfig are used.
  • If CosmosPoolConfig is not provided, a default PriorityNonceMempool is created with:
    • Priority = (fee_amount / gas_limit) in the EVM coin denom
    • Comparator = big-int comparison (higher is selected first)
    • MinValue = 0
  • MinTip is optional. If unset, selection uses the effective tip from each tx (min(gas_tip_cap, gas_fee_cap - base_fee)).
  • If PendingTxProposalTimeout is not provided, 0 is used. This means unlimited timeout and always wait for all tx rechecking to finish before creating a proposal.
  • If InsertQueueSize is 0, the mempool uses a fallback of 5000.
  • If EnableTxTracker is not provided, it is kept false.

Custom Legacy Pool Configuration

Customize EVM transaction pool parameters:
evmd/mempool.go
// EVM legacy txpool tuning
legacyCfg := legacypool.DefaultConfig
legacyCfg.PriceLimit = 2                // Minimum gas price (wei)
legacyCfg.PriceBump = 15                // 15% price bump to replace
legacyCfg.AccountSlots = 32             // Slots per account
legacyCfg.GlobalSlots = 10240           // Total executable slots
legacyCfg.AccountQueue = 128            // Non-executable per account
legacyCfg.GlobalQueue = 2048            // Total non-executable
legacyCfg.Lifetime = 6 * time.Hour      // Max queue time
legacyCfg.IncludedNonceCacheSize = 5000 // Max cache size for tracking account nonces

mempoolConfig.LegacyPoolConfig = &legacyCfg

Custom Cosmos Mempool Configuration

The mempool uses a PriorityNonceMempool for Cosmos transactions by default. You can customize the priority calculation:
evmd/mempool.go
// Define custom priority calculation for Cosmos transactions
cosmosCfg := sdkmempool.PriorityNonceMempoolConfig[math.Int]{}
cosmosCfg.TxPriority = sdkmempool.TxPriority[math.Int]{
    GetTxPriority: func(goCtx context.Context, tx sdk.Tx) math.Int {
        feeTx, ok := tx.(sdk.FeeTx)
        if !ok {
            return math.ZeroInt()
        }

        // Get fee in bond denomination
        bondDenom := "uatom" // or your chain's bond denom
        fee := feeTx.GetFee()
        found, coin := fee.Find(bondDenom)
        if !found {
            return math.ZeroInt()
        }

        // Calculate gas price: fee_amount / gas_limit
        gasPrice := coin.Amount.Quo(math.NewIntFromUint64(feeTx.GetGas()))
        return gasPrice
    },
    Compare: func(a, b math.Int) int {
        return a.BigInt().Cmp(b.BigInt()) // Higher values have priority
    },
    MinValue: math.ZeroInt(),
}

mempoolConfig.CosmosPoolConfig = &cosmosCfg

Custom Block Gas Limit

BlockGasLimit is read automatically from consensus_params.block.max_gas in genesis.json — it is not an app.toml setting. To change it, update the genesis file before chain start. The value can also be overridden in code:
evmd/mempool.go
// Example: 50M gas limit for lower capacity chains
mempoolConfig := &evmmempool.Config{
    BlockGasLimit: 50_000_000,
}

Event Bus Integration

Users must connect the mempool to CometBFT’s EventBus so it can react to finalized blocks:
evmd/app.go
// After starting the CometBFT node
if m, ok := app.GetMempool().(*evmmempool.EVMMempool); ok {
    m.SetEventBus(bftNode.EventBus())
}
This enables chain-head notifications so the mempool can promptly promote/evict transactions when blocks are committed.

app.toml Configuration

The following settings can be configured in app.toml and take effect at node startup without code changes:
KeyDefaultDescription
evm.min-tip0Minimum tip (priority fee) in wei; transactions below this are excluded from block selection
evm.mempool.price-limit1Minimum gas price in wei to accept a transaction into the pool
evm.mempool.price-bump10Minimum % increase required to replace a pending transaction with the same nonce
evm.mempool.account-slots16Max executable transactions per account
evm.mempool.global-slots5120Max total executable transactions across all accounts
evm.mempool.account-queue64Max queued (non-executable) transactions per account
evm.mempool.global-queue1024Max total queued transactions across all accounts
evm.mempool.lifetime3hMax time a transaction can remain queued before eviction
evm.mempool.included-nonce-cache-size4096Max amount of nonces to track for eviction. Should be set to the maximum number of accounts you expect to see in a single block, given your chains block gas limit.
evm.mempool.pending-tx-proposal-timeout0msMax time to wait for fetching pending execution transaction when creating a proposal. 0 means wait for all transactions to be validated before creating a proposal. Note that this may take a significant amount of time under high load and can degrade performance. We’ve found setting this to ~250ms strikes the right balance between performance and rechecking a sufficient amount of transactions per block.
evm.mempool.check-tx-timeout5sTimeout to wait for CheckTx on Cosmos txs insertion.
evm.mempool.insert-queue-size5000Max amount of transactions that can be pending insertion before returning an error. Note that EVM & Cosmos transaction use separate queues. So you may have insert-queue-size EVM transactions pending insertion, and insert-queue-size Cosmos transactions pending insertion.
evm.mempool.enable-tx-trackerfalseIf metrics for tracking EVM transaction inclusion latencies should be enabled.

Monitoring and Debugging

Use the txpool RPC methods to monitor mempool state:
  • txpool_status: Get pending and queued transaction counts
  • txpool_content: View all transactions in the pool
  • txpool_inspect: Get human-readable transaction summaries
  • txpool_contentFrom: View transactions from specific addresses