From c9fa17b8e9a22c247414205945847c487685154d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Thu, 25 Jun 2026 16:06:06 +0200 Subject: [PATCH 1/2] fix(v11): install missing EIP-2935 history-storage contract --- app/upgrades.go | 1 + app/upgrades/v11/keepers.go | 9 +++++++++ app/upgrades/v11/upgrades.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/app/upgrades.go b/app/upgrades.go index 5217635..d65bfaf 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -72,6 +72,7 @@ func (app *App) setupUpgradeHandlers() { app.ICAHostKeeper, app.StakingKeeper, app.TransferKeeper, + app.EvmKeeper, ), ) diff --git a/app/upgrades/v11/keepers.go b/app/upgrades/v11/keepers.go index 482b59a..1c899c2 100644 --- a/app/upgrades/v11/keepers.go +++ b/app/upgrades/v11/keepers.go @@ -5,7 +5,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + evmtypes "github.com/cosmos/evm/x/vm/types" icahosttypes "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/host/types" + "github.com/ethereum/go-ethereum/common" ) // ICAHostKeeper is the narrow interface required by the v11 upgrade @@ -26,3 +28,10 @@ type StakingKeeper interface { type TransferKeeper interface { UnescrowCoin(ctx sdk.Context, escrowAddress, receiver sdk.AccAddress, coin sdk.Coin) error } + +// EvmKeeper is the narrow interface required by the v11 upgrade +// handler. It matches a subset of evmkeeper.Keeper. +type EvmKeeper interface { + IsContract(ctx sdk.Context, addr common.Address) bool + AddPreinstalls(ctx sdk.Context, preinstalls []evmtypes.Preinstall) error +} diff --git a/app/upgrades/v11/upgrades.go b/app/upgrades/v11/upgrades.go index ab30147..000fe3a 100644 --- a/app/upgrades/v11/upgrades.go +++ b/app/upgrades/v11/upgrades.go @@ -3,14 +3,18 @@ package v11 import ( "context" "fmt" + "slices" "time" "cosmossdk.io/log" upgradetypes "cosmossdk.io/x/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + evmtypes "github.com/cosmos/evm/x/vm/types" icahosttypes "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/host/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + "github.com/ethereum/go-ethereum/common" + ethparams "github.com/ethereum/go-ethereum/params" ) func CreateUpgradeHandler( @@ -19,6 +23,7 @@ func CreateUpgradeHandler( icaHostKeeper ICAHostKeeper, stakingKeeper StakingKeeper, transferKeeper TransferKeeper, + evmKeeper EvmKeeper, ) upgradetypes.UpgradeHandler { return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { ctx := sdk.UnwrapSDKContext(c) @@ -50,11 +55,35 @@ func CreateUpgradeHandler( return nil, err } + logger.Info("Installing EIP-2935 history-storage contract...") + if err := installHistoryStorageContract(ctx, logger, evmKeeper); err != nil { + return nil, err + } + logger.Info("Finished v11 upgrade handler") return vm, nil } } +// installHistoryStorageContract installs the EIP-2935 history-storage contract if +// missing. +func installHistoryStorageContract(ctx sdk.Context, logger log.Logger, evmKeeper EvmKeeper) error { + if evmKeeper.IsContract(ctx, ethparams.HistoryStorageAddress) { + logger.Info("EIP-2935 history-storage contract already present, skipping") + return nil + } + + idxContractPreinstall := slices.IndexFunc(evmtypes.DefaultPreinstalls, func(p evmtypes.Preinstall) bool { + return common.HexToAddress(p.Address) == ethparams.HistoryStorageAddress + }) + if idxContractPreinstall < 0 { + return fmt.Errorf("EIP-2935 preinstall not found in DefaultPreinstalls") + } + + logger.Info("Installing EIP-2935 history-storage contract", "address", ethparams.HistoryStorageAddress.Hex()) + return evmKeeper.AddPreinstalls(ctx, []evmtypes.Preinstall{evmtypes.DefaultPreinstalls[idxContractPreinstall]}) +} + // withdrawElysEscrow releases the configured amount of XRP from the Elys channel // escrow to the recovery address configured for the running network. func withdrawElysEscrow(ctx sdk.Context, logger log.Logger, transferKeeper TransferKeeper) error { From 6ca74b972529f3c90694f1417c8c4af702184845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 26 Jun 2026 10:21:32 +0200 Subject: [PATCH 2/2] fix(v11): install all missing default preinstalls --- app/upgrades/v11/upgrades.go | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/app/upgrades/v11/upgrades.go b/app/upgrades/v11/upgrades.go index 000fe3a..ae21774 100644 --- a/app/upgrades/v11/upgrades.go +++ b/app/upgrades/v11/upgrades.go @@ -3,7 +3,6 @@ package v11 import ( "context" "fmt" - "slices" "time" "cosmossdk.io/log" @@ -14,7 +13,6 @@ import ( icahosttypes "github.com/cosmos/ibc-go/v10/modules/apps/27-interchain-accounts/host/types" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" "github.com/ethereum/go-ethereum/common" - ethparams "github.com/ethereum/go-ethereum/params" ) func CreateUpgradeHandler( @@ -55,8 +53,8 @@ func CreateUpgradeHandler( return nil, err } - logger.Info("Installing EIP-2935 history-storage contract...") - if err := installHistoryStorageContract(ctx, logger, evmKeeper); err != nil { + logger.Info("Installing missing default preinstalls...") + if err := installMissingPreinstalls(ctx, logger, evmKeeper); err != nil { return nil, err } @@ -65,23 +63,20 @@ func CreateUpgradeHandler( } } -// installHistoryStorageContract installs the EIP-2935 history-storage contract if -// missing. -func installHistoryStorageContract(ctx sdk.Context, logger log.Logger, evmKeeper EvmKeeper) error { - if evmKeeper.IsContract(ctx, ethparams.HistoryStorageAddress) { - logger.Info("EIP-2935 history-storage contract already present, skipping") - return nil +// installMissingPreinstalls deploys any default preinstall that is absent. +func installMissingPreinstalls(ctx sdk.Context, logger log.Logger, evmKeeper EvmKeeper) error { + var missingPreinstalls []evmtypes.Preinstall + for _, aDefaultPreinstall := range evmtypes.DefaultPreinstalls { + if evmKeeper.IsContract(ctx, common.HexToAddress(aDefaultPreinstall.Address)) { + continue + } + logger.Info("installing missing preinstall", "name", aDefaultPreinstall.Name, "address", aDefaultPreinstall.Address) + missingPreinstalls = append(missingPreinstalls, aDefaultPreinstall) } - - idxContractPreinstall := slices.IndexFunc(evmtypes.DefaultPreinstalls, func(p evmtypes.Preinstall) bool { - return common.HexToAddress(p.Address) == ethparams.HistoryStorageAddress - }) - if idxContractPreinstall < 0 { - return fmt.Errorf("EIP-2935 preinstall not found in DefaultPreinstalls") + if len(missingPreinstalls) == 0 { + return nil } - - logger.Info("Installing EIP-2935 history-storage contract", "address", ethparams.HistoryStorageAddress.Hex()) - return evmKeeper.AddPreinstalls(ctx, []evmtypes.Preinstall{evmtypes.DefaultPreinstalls[idxContractPreinstall]}) + return evmKeeper.AddPreinstalls(ctx, missingPreinstalls) } // withdrawElysEscrow releases the configured amount of XRP from the Elys channel