> ## Documentation Index
> Fetch the complete documentation index at: https://cosmos-docs-security-release.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration: v0.4.x to v0.5.0

## 0) Prep

* Create a branch: `git switch -c upgrade/evm-v0.5`.
* Ensure a clean build + tests green pre-upgrade.
* Snapshot your current params/genesis for comparison later.

***

## 1) Dependency bumps (go.mod)

* Bump `github.com/cosmos/evm` to v0.5.0 and run:

```bash theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
go mod tidy
```

***

## 2) Fix `"github.com/cosmos/evm/types" imports`

`v0.5.0` removes `github.com/cosmos/evm/types` and moves files to their folders, respective to function.
For a complete list of changes, refer to [this PR](https://github.com/cosmos/evm/pull/639). The
following list includes references within `evmd` that have been moved.

### Summary of import changes in `evmd`:

**Removed import:**

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
- cosmosevmtypes "github.com/cosmos/evm/types"
```

**Added imports:**

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
+ antetypes "github.com/cosmos/evm/ante/types"
+ evmaddress "github.com/cosmos/evm/encoding/address"
+ "github.com/cosmos/evm/utils"
```

### Detailed mapping of moved items:

* **`AttoPowerReduction`** → moved to `"github.com/cosmos/evm/utils"`
  ```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  - sdk.DefaultPowerReduction = cosmosevmtypes.AttoPowerReduction
  + sdk.DefaultPowerReduction = utils.AttoPowerReduction
  ```

* **`HasDynamicFeeExtensionOption`** → moved to `"github.com/cosmos/evm/ante/types"`
  ```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  - ExtensionOptionChecker: cosmosevmtypes.HasDynamicFeeExtensionOption,
  + ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption,
  ```

* **Address Codec functions** → new package `"github.com/cosmos/evm/encoding/address"`

  Use `evmaddress.NewEvmCodec()` for address codec initialization:

  ```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  app.AccountKeeper = authkeeper.NewAccountKeeper(
      appCodec,
      runtime.NewKVStoreService(keys[authtypes.StoreKey]),
      authtypes.ProtoBaseAccount,
      evmconfig.GetMaccPerms(),
      evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
      sdk.GetConfig().GetBech32AccountAddrPrefix(),
      authAddr,
  )
  ```

* **`Bip44CoinType`, `BIP44HDPath`** → moved to `"github.com/cosmos/evm/crypto/hd"`

* **`GenesisState`** → removed as a duplicate object can be found in the `evmd` folder and a testing version is in `"github.com/cosmos/evm/testutil"`

***

## 3) App wiring in `app.go`

### Mempool

#### Custom initializer

The mempool configuration can now be handled by a helper function. If you prefer to use the configuration from `app.toml` and CLI flags, you can refactor your mempool setup:

* **Before**: Manual configuration in app.go

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
mempoolConfig := &evmmempool.EVMMempoolConfig{
    AnteHandler:   app.GetAnteHandler(),
    BlockGasLimit: blockGasLimit,
    MinTip:        minTip,
}
evmMempool := evmmempool.NewExperimentalEVMMempool(
    app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper,
    app.txConfig, app.clientCtx, mempoolConfig,
)
```

* **After**: Using helper function (optional). See [https://github.com/cosmos/evm/blob/42e1141c9b00432020e69945e565f60f80ab501d/evmd/mempool.go](https://github.com/cosmos/evm/blob/42e1141c9b00432020e69945e565f60f80ab501d/evmd/mempool.go) for the reference implementation

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
if err := app.configureEVMMempool(appOpts, logger); err != nil {
    panic(fmt.Sprintf("failed to configure EVM mempool: %s", err.Error()))
}
```

The helper function reads configuration from `appOpts` or applies defaults if omitted. Note that `NewExperimentalEVMMempool` now takes an additional `cosmosPoolMaxTx` parameter, with a recommended default value being `4096` or `0` (uncapped).

#### Simple config migration

If `BlockGasLimit` is 0, it defaults to `100_000_000`. If `BroadCastTxFn` is not set, it's also set to a default value.

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
mempoolConfig := &evmmempool.EVMMempoolConfig{
    AnteHandler:   app.GetAnteHandler(),
    BlockGasLimit: 100_000_000, // or 0 to use default
}
evmMempool := evmmempool.NewExperimentalEVMMempool(
    app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, mempoolConfig
)
```

#### Advanced setups: migrate your customizations

PR [#496](https://github.com/cosmos/evm/pull/496) replaced pre-built pools with configs in `EVMMempoolConfig`:

* Replace pools with configs
  * Removed: `TxPool *txpool.TxPool`, `CosmosPool sdkmempool.ExtMempool`
  * Added: `LegacyPoolConfig *legacypool.Config`, `CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]`

If you built custom pools yourself:

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
 mempoolConfig := &evmmempool.EVMMempoolConfig{
-   TxPool:     customTxPool,
-   CosmosPool: customCosmosPool,
+   LegacyPoolConfig: &legacyCfg,  // or nil for defaults
+   CosmosPoolConfig: &cosmosCfg,  // or nil for defaults
   AnteHandler:      app.GetAnteHandler(),
   BroadCastTxFn:    myBroadcast, // optional
 }
```

Example custom configs:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// EVM legacy txpool tuning
legacyCfg := legacypool.DefaultConfig
legacyCfg.PriceLimit = 2
mempoolConfig.LegacyPoolConfig = &legacyCfg

// Cosmos priority mempool tuning
cosmosCfg := sdkmempool.PriorityNonceMempoolConfig[math.Int]{}
cosmosCfg.TxPriority = sdkmempool.TxPriority[math.Int]{
    GetTxPriority: func(goCtx context.Context, tx sdk.Tx) math.Int {
        // Custom priority function
    },
    Compare:  func(a, b math.Int) int { return a.BigInt().Cmp(b.BigInt()) },
    MinValue: math.ZeroInt(),
}
mempoolConfig.CosmosPoolConfig = &cosmosCfg

// Custom EVM broadcast (optional)
mempoolConfig.BroadCastTxFn = func(txs []*ethtypes.Transaction) error { return nil }
```

#### New Configuration Options

PR [#698](https://github.com/cosmos/evm/pull/698) adds new configuration options for the EVM mempool that can be set via `app.toml` or CLI flags. These options allow fine-tuning of the EVM legacy pool behavior.

##### Configuration via `app.toml`

The following mempool configuration options are now available in `app.toml` under the `[evm.mempool]` section:

```toml theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
[evm.mempool]
# PriceLimit is the minimum gas price to enforce for acceptance into the pool (in wei)
price-limit = 1

# PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce)
price-bump = 10

# AccountSlots is the number of executable transaction slots guaranteed per account
account-slots = 16

# GlobalSlots is the maximum number of executable transaction slots for all accounts
global-slots = 5120

# AccountQueue is the maximum number of non-executable transaction slots permitted per account
account-queue = 64

# GlobalQueue is the maximum number of non-executable transaction slots for all accounts
global-queue = 1024

# Lifetime is the maximum amount of time non-executable transaction are queued
lifetime = "3h0m0s"
```

##### Configuration via CLI Flags

These options can also be set via CLI flags:

* `--evm.mempool.price-limit` (default: 1)
* `--evm.mempool.price-bump` (default: 10)
* `--evm.mempool.account-slots` (default: 16)
* `--evm.mempool.global-slots` (default: 5120)
* `--evm.mempool.account-queue` (default: 64)
* `--evm.mempool.global-queue` (default: 1024)
* `--evm.mempool.lifetime` (default: 3h0m0s)

##### Cosmos Mempool Max Transactions

A new flag `--mempool.max-txs` allows limiting the maximum number of transactions in the Cosmos mempool. Set to 0 or -1 for unbounded (default: 0).

The function signature for `NewExperimentalEVMMempool` also changed to add a cosmosPoolMaxTx field:

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
func NewExperimentalEVMMempool(
	getCtxCallback func(height int64, prove bool) (sdk.Context, error),
	logger log.Logger,
	vmKeeper VMKeeperI,
	feeMarketKeeper FeeMarketKeeperI,
	txConfig client.TxConfig,
	clientCtx client.Context,
	config *EVMMempoolConfig,
+	cosmosPoolMaxTx int,
)
```

#### EVM Chain ID

The EVM chain ID is now retrieved directly from `appOpts` instead of being passed as a parameter. In `app.go`, the chain ID is obtained using:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID))
```

See `evmd/app.go:216` for the reference implementation.

The EVM Keeper now also takes in evmChainID as a parameter:

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
app.EVMKeeper = evmkeeper.NewKeeper(
		appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys,
		authtypes.NewModuleAddress(govtypes.ModuleName),
		app.AccountKeeper,
		app.PreciseBankKeeper,
		app.StakingKeeper,
		app.FeeMarketKeeper,
		&app.ConsensusParamsKeeper,
		&app.Erc20Keeper,
+		evmChainID,
		tracer,
	)
```

#### Function Signature Changes

In `app.go`, remove evmChainID and evmAppOptions from the NewApp signature.

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// NewExampleApp returns a reference to an initialized EVMD.
func NewExampleApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
-	evmChainID uint64,
-	evmAppOptions evmconfig.EVMOptionsFn,
	baseAppOptions ...func(*baseapp.BaseApp),
) *EVMD {
```

Afterwards, fix any reference to the function by removing the inputs.

Then, remove any reference of evmAppOptions being called:

`app.go`

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
-	if err := evmAppOptions(evmChainID); err != nil {
-		panic(err)
-	}
```

`root.go`

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
- noOpEvmAppOptions := func(_ uint64) error {
-		return nil
-	}
```

```diff theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
- if initClientCtx.ChainID != "" {
-		if err := config.EvmAppOptions(config.EVMChainID); err != nil {
-			panic(err)
-		}
-	}
```

`evmd_config.go`, `chain_id.go`, `config.go`, `constants.go` have been moved to
`github.com/cosmos/evm/config` and may be removed to your repo.

### Denom Configs

[#661](https://github.com/cosmos/evm/pull/661) removes the instantiation of chain configs via app.go
and moves them to state or genesis.
It is critical to remove any use of EvmAppOptions as calling the configurator will panic the chain
at runtime during startup.

### Default Precompiles

Default precompiles have been moved to `/evm/precompiles/types/defaults.go` and the function name was
changed to `DefaultStaticPrecompiles`. The function signature has also changed, and now takes pointers
as inputs for the `Erc20Keeper` and `TransferKeeper`. Finally, the `WithStaticPrecompiles` builder
function can now happen *alongside the keeper instantiation*, and not after. The new wiring is shown below:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
	app.EVMKeeper = evmkeeper.NewKeeper(
		appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys,
		authtypes.NewModuleAddress(govtypes.ModuleName),
		app.AccountKeeper,
		app.PreciseBankKeeper,
		app.StakingKeeper,
		app.FeeMarketKeeper,
		&app.ConsensusParamsKeeper,
		&app.Erc20Keeper,
		evmChainID,
		tracer,
	).WithStaticPrecompiles(
		precompiletypes.DefaultStaticPrecompiles(
			*app.StakingKeeper,
			app.DistrKeeper,
			app.PreciseBankKeeper,
			&app.Erc20Keeper, // UPDATED
			&app.TransferKeeper, // UPDATED
			app.IBCKeeper.ChannelKeeper,
			app.GovKeeper,
			app.SlashingKeeper,
			appCodec,
		),
	)
```

#### UpgradeHandler

As the configs have been moved to state and genesis, you must include an UpgradeHandler if your chain does
not satisfy the following conditions.

1. Your EVM Denom set in the `x/vm` params must have `DenomMetadata` registered for it in `x/bank`.
2. Your EVM Denom must have a display denom associated with it in `DenomMetadata`.
   1. The display denom for the EVM Denom must have an accurate decimal value (i.e. for `uatom`, `atom` must have a decimal value of 6.
3. Your chain is an 18-decimal chain.
4. Call `InitEvmCoinInfo` to initialize EVM coin metadata in the module store.

In your UpgradeHandler:

* **If your chain does not have DenomMetadata set for the EVM Denom, you must include it.**
* **If your chain's EVM denom is *not* 18 decimals, you must add ExtendedDenomOptions to your `x/vm` params.**
* **After setting metadata, initialize EVM coin info:**

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// After setting denom metadata
if err := app.EVMKeeper.InitEvmCoinInfo(ctx); err != nil {
    return nil, err
}
```

Please refer to the [upgrade example](https://github.com/cosmos/evm/blob/main/evmd/upgrades.go) for the complete implementation.

***

## 4) Build & quick tests

```bash theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
go build ./...
```

Smoke test on a single node:

* Send a few EVM txs; confirm promotion/broadcast (or your `BroadCastTxFn`).
* Send Cosmos txs; confirm ordering reflects your `CosmosPoolConfig` (if customized).
