Skip to main content
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 and createMempoolConfig, called automatically from NewExampleApp
  • mempool/ — the mempool implementation (ExperimentalEVMMempool, CheckTxHandler, TxPool)
Legacy pool parameters and MinTip can be set via app.toml without code changes. CosmosPoolConfig and BroadCastTxFn require modifying createMempoolConfig in evmd/mempool.go. BlockGasLimit is read from consensus_params.block.max_gas in genesis.json.

Configuration Options

The EVMMempoolConfig struct controls mempool behavior:
type EVMMempoolConfig struct {
    AnteHandler      sdk.AnteHandler                                    // Required: transaction validation
    BlockGasLimit    uint64                                             // Required: gas limit for block selection
    LegacyPoolConfig *legacypool.Config                                 // Optional: EVM pool tuning — see Custom Legacy Pool below
    CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]   // Optional: Cosmos pool tuning — see Custom Cosmos Mempool below
    BroadCastTxFn   func(txs []*ethtypes.Transaction) error             // Optional: custom promotion broadcast — see Custom Broadcast below
    MinTip           *uint256.Int                                       // Optional: minimum tip for EVM txs
}

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
  • If BroadCastTxFn is not provided, a default is created that uses the app clientCtx/txConfig to broadcast EVM transactions when they are promoted from queued → pending.
  • MinTip is optional. If unset, selection uses the effective tip from each tx (min(gas_tip_cap, gas_fee_cap - base_fee)).

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

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 Broadcast Function

Override the default broadcast behavior for promoted EVM transactions:
evmd/mempool.go
// Custom EVM broadcast (optional)
mempoolConfig.BroadCastTxFn = func(txs []*ethtypes.Transaction) error {
    // Custom logic for broadcasting promoted transactions
    return nil
}

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.EVMMempoolConfig{
    AnteHandler:   app.GetAnteHandler(),
    BlockGasLimit: 50_000_000,
}

Event Bus Integration

For best results, 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.ExperimentalEVMMempool); 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
CosmosPoolConfig and BroadCastTxFn have no app.toml equivalent and require code changes in createMempoolConfig.

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