EVM Mempool Integration

Integrate the EVM mempool with your Ontomir EVM chain

Overview

This guide provides step-by-step instructions for integrating the EVM mempool into your Ontomir EVM chain. For conceptual information about mempool design and architecture, see the Mempool Concepts page.

Step 1: Add EVM Mempool to App Struct

Update your app/app.go to include the EVM mempool:

type App struct {
    *baseapp.BaseApp
    // ... other keepers

    // Ontomir EVM keepers
    FeeMarketKeeper   feemarketkeeper.Keeper
    EVMKeeper         *evmkeeper.Keeper
    EVMMempool        *evmmempool.ExperimentalEVMMempool
}

Step 2: Configure Mempool in NewApp Constructor

The mempool must be initialized **after** the antehandler has been set in the app.

Add the following configuration in your NewApp constructor:

```go // Set the EVM priority nonce mempool if evmtypes.GetChainConfig() != nil { mempoolConfig := &evmmempool.EVMMempoolConfig{ AnteHandler: app.GetAnteHandler(), BlockGasLimit: 100_000_000, }

}

Full Configuration Options

Defaults and Fallbacks

  • If BlockGasLimit is 0, the mempool uses a fallback of 100_000_000 gas.

  • If OntomirPoolConfig is not provided, a default PriorityNonceMempool is created with:

    • Priority = (fee_amount / gas_limit) in the chain bond 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)).

v0.4.x to v0.5.0 Migration

Breaking Change: Pre-built pools replaced with configuration objects

Before (v0.4.x):

After (v0.5.0):

Custom Ontomir Mempool Configuration

The mempool uses a PriorityNonceMempool for Ontomir transactions by default. You can customize the priority calculation:

Custom Block Gas Limit

Different chains may require different gas limits based on their capacity:

Event Bus Integration

For best results, connect the mempool to CometBFT's EventBus so it can react to finalized blocks:

This enables chain-head notifications so the mempool can promptly promote/evict transactions when blocks are committed.

Architecture Components

The EVM mempool consists of several key components:

ExperimentalEVMMempool

The main coordinator implementing Ontomir SDK's ExtMempool interface (mempool/mempool.go).

Key Methods:

  • Insert(ctx, tx): Routes transactions to appropriate pools

  • Select(ctx, filter): Returns unified iterator over all transactions

  • Remove(tx): Handles transaction removal with EVM-specific logic

  • InsertInvalidNonce(txBytes): Queues nonce-gapped EVM transactions locally

CheckTx Handler

Custom transaction validation that handles nonce gaps specially (mempool/check_tx.go).

Special Handling: On ErrNonceGap for EVM transactions:

TxPool

Direct port of Ethereum's transaction pool managing both pending and queued transactions (mempool/txpool/).

Key Features:

  • Uses vm.StateDB interface for Ontomir state compatibility

  • Implements BroadcastTxFn callback for transaction promotion

  • Ontomir-specific reset logic for instant finality

PriorityNonceMempool

Standard Ontomir SDK mempool for non-EVM transactions with fee-based prioritization.

Default Priority Calculation:

Transaction Type Routing

The mempool handles different transaction types appropriately:

Ethereum Transactions (MsgEthereumTx)

  • Tier 1 (Local): EVM TxPool handles nonce gaps and promotion

  • Tier 2 (Network): CometBFT broadcasts executable transactions

Ontomir Transactions (Bank, Staking, Gov, etc.)

  • Direct to Tier 2: Always go directly to CometBFT mempool

  • Standard Flow: Follow normal Ontomir SDK validation and broadcasting

  • Priority-Based: Use PriorityNonceMempool for fee-based ordering

Unified Transaction Selection

During block building, both transaction types compete fairly based on their effective tips:

Fee Comparison:

  • EVM: gas_tip_cap or min(gas_tip_cap, gas_fee_cap - base_fee)

  • Ontomir: (fee_amount / gas_limit) - base_fee

  • Selection: Higher effective tip gets selected first

Testing Your Integration

Verify Nonce Gap Handling

Test that transactions with nonce gaps are properly queued:

Test Transaction Replacement

Verify that higher-fee transactions replace lower-fee ones:

Verify Batch Deployments

Test typical deployment scripts (like Uniswap) that send many transactions at once:

Monitoring and Debugging

Use the txpool RPC methodsarrow-up-right 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

  • Mempool Concepts - Understanding mempool behavior and design

  • EVM Module Integration - Prerequisites for mempool integration

  • JSON-RPC Methodsarrow-up-right - Mempool query methods