This guide provides step-by-step instructions for integrating the EVM mempool into your Cosmos EVM chain. For conceptual information about mempool design and architecture, see the Mempool Concepts page.
The mempool must be initialized after the antehandler has been set in the app.
Add the following configuration in your NewApp constructor:
Show View EVM mempool initialization code
Copy
Ask AI
// Set the EVM priority nonce mempoolif evmtypes.GetChainConfig() != nil { mempoolConfig := &evmmempool.EVMMempoolConfig{ AnteHandler: app.GetAnteHandler(), BlockGasLimit: 100_000_000, } evmMempool := evmmempool.NewExperimentalEVMMempool( app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, mempoolConfig, ) app.EVMMempool = evmMempool // Replace BaseApp mempool app.SetMempool(evmMempool) // Set custom CheckTx handler for nonce gap support checkTxHandler := evmmempool.NewCheckTxHandler(evmMempool) app.SetCheckTxHandler(checkTxHandler) // Set custom PrepareProposal handler abciProposalHandler := baseapp.NewDefaultProposalHandler(evmMempool, app) abciProposalHandler.SetSignerExtractionAdapter( evmmempool.NewEthSignerExtractionAdapter( sdkmempool.NewDefaultSignerExtractionAdapter(), ), ) app.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler())}
Breaking Change from v0.4.x: The global mempool registry (SetGlobalEVMMempool) has been removed. Mempool is now passed directly to the JSON-RPC server during initialization.
If BlockGasLimit is 0, the mempool uses a fallback of 100_000_000 gas.
If CosmosPoolConfig 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)).
Custom transaction validation that handles nonce gaps specially (mempool/check_tx.go).Special Handling: On ErrNonceGap for EVM transactions:
Copy
Ask AI
if errors.Is(err, ErrNonceGap) { // Route to local queue instead of rejecting err := mempool.InsertInvalidNonce(request.Tx) // Must intercept error and return success to EVM client return interceptedSuccess}