Skip to main content

0) Prep

  • Create a branch: git switch -c upgrade/evm-v0.6.
  • 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.6.0 and run:

2) App Wiring Changes

IBC Transfer Module

v0.6.0 removes the custom IBC transfer keeper override and now uses the official IBC-Go transfer keeper directly. This means that ERC20 conversions via Cosmos IBC transfer transactions are not possible. These are now only handled in the ICS20 precompile, and any ERC20 transfer must be initiated through there. Changes required in app.go:
  1. Update imports - Replace custom transfer imports with official IBC-Go imports:
  1. Update TransferKeeper initialization - Remove ERC20 keeper parameter:
  1. Update module registration - Use official transfer module:
  1. Update ICS20 precompile wiring - Pass ERC20 keeper to ICS20 precompile:
The ICS20 precompile now takes the ERC20 keeper as a parameter (instead of the transfer keeper receiving it). This allows the precompile to handle ERC20 conversions directly.

3) Breaking API Changes

StateDB Requirements

v0.6.0 introduces significant changes to event tracking and state management. All EVM execution functions now require an explicit stateDB parameter and a callFromPrecompile flag to properly handle event management and state transitions. NOTE: The only function calls affected are CallEVM, CallEVMWithData, ApplyMessage, and ApplyMessageWithConfig. These are typically used in common precompiles and logic that calls back into the EVM from the SDK. If your project does not use these functions, then no steps need to be taken for the upgrade.

Advanced Changes

The following functions have updated signatures:
CallEVM
Before (v0.5.x):
After (v0.6.0):
CallEVMWithData
Before (v0.5.x):
After (v0.6.0):
ApplyMessage
Before (v0.5.x):
After (v0.6.0):
ApplyMessageWithConfig
Before (v0.5.x):
After (v0.6.0):

Migration Steps

For Non-Precompile Contexts

If you’re calling EVM functions from outside a precompile (e.g., from a module keeper, message server, or query handler):
  1. Create a new stateDB before calling EVM functions
  2. Pass false for the callFromPrecompile parameter
Example:

For Precompile Contexts

If you’re calling EVM functions from within a precompile:
  1. Reuse the existing stateDB from your precompile context (do not create a new one)
  2. Pass true for the callFromPrecompile parameter
  3. The existing stateDB is typically available as a parameter in your precompile function
Example:

Important Notes

  • Never pass nil for stateDB: This will return ErrNilStateDB error
  • Commit behavior in precompiles: When commit=true and callFromPrecompile=true, the state changes are flushed to the cache context rather than fully committed. This prevents collapsing the cache stack in nested call scenarios.

EVMKeeper Interface Changes

If you implement or mock the EVMKeeper interface, update your implementation:

4) ERC20 Keeper Interface Changes

The ERC20Keeper interface has new methods:
If you implement this interface, add these methods to your implementation.

5) Error Handling

A new error type has been added:
This error is returned when nil is passed as the stateDB parameter to EVM functions.

6) Build & Tests

Testing Checklist

After migration, verify:
  • All EVM calls pass a valid stateDB
  • Non-precompile calls use callFromPrecompile=false
  • Precompile calls reuse existing stateDB and use callFromPrecompile=true
  • Event emission works correctly in both success and revert scenarios
  • State changes are properly committed or reverted

Common Migration Examples

Example 1: Module Keeper Query

Example 2: Message Server Transaction

Example 3: Precompile Internal Call