@@ -2,8 +2,11 @@ package evmd
22
33import (
44 "context"
5+ "fmt"
6+ "slices"
57
6- "github.com/cosmos/evm/x/vm/types"
8+ vmtypes "github.com/cosmos/evm/x/vm/types"
9+ "github.com/ethereum/go-ethereum/common"
710
811 storetypes "cosmossdk.io/store/types"
912 upgradetypes "cosmossdk.io/x/upgrade/types"
@@ -13,17 +16,24 @@ import (
1316 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
1417)
1518
16- // UpgradeName defines the on-chain upgrade name for the sample EVMD upgrade
17- // from v0.5.0 to v0.6.0.
18- //
19- // NOTE: This upgrade defines a reference implementation of what an upgrade
20- // could look like when an application is migrating from EVMD version
21- // v0.4.0 to v0.5.x
22- const UpgradeName = "v0.5.0-to-v0.6.0"
19+ const (
20+ // LegacyUpgradeName is kept to preserve compatibility with already-published
21+ // upgrade proposal names from earlier deployments.
22+ LegacyUpgradeName = "v0.5.0-to-v0.6.0"
23+
24+ // UpgradeName defines the on-chain upgrade name for enabling missing EVM
25+ // preinstalls on an already-running network and optionally activating the
26+ // latest static precompile.
27+ UpgradeName = "v0.6.0-enable-missing-preinstalls"
28+
29+ // OptionalStaticPrecompileAddress is enabled during the upgrade if missing.
30+ OptionalStaticPrecompileAddress = vmtypes .TEEPrecompileAddress
31+ )
2332
2433func (app EVMD ) RegisterUpgradeHandlers () {
34+ // Legacy sample upgrade (kept intact for compatibility with existing plans).
2535 app .UpgradeKeeper .SetUpgradeHandler (
26- UpgradeName ,
36+ LegacyUpgradeName ,
2737 func (ctx context.Context , _ upgradetypes.Plan , fromVM module.VersionMap ) (module.VersionMap , error ) {
2838 sdkCtx := sdk .UnwrapSDKContext (ctx )
2939 sdkCtx .Logger ().Debug ("this is a debug level message to test that verbose logging mode has properly been enabled during a chain upgrade" )
@@ -53,16 +63,77 @@ func (app EVMD) RegisterUpgradeHandlers() {
5363 // (Required for NON-18 denom chains *only)
5464 // Update EVM params to add Extended denom options
5565 // Ensure that this corresponds to the EVM denom
56- // (tyically the bond denom)
66+ // (typically the bond denom)
5767 evmParams := app .EVMKeeper .GetParams (sdkCtx )
58- evmParams .ExtendedDenomOptions = & types.ExtendedDenomOptions {ExtendedDenom : "atest" }
59- err := app .EVMKeeper .SetParams (sdkCtx , evmParams )
60- if err != nil {
68+ evmParams .ExtendedDenomOptions = & vmtypes.ExtendedDenomOptions {ExtendedDenom : "atest" }
69+ if err := app .EVMKeeper .SetParams (sdkCtx , evmParams ); err != nil {
70+ return nil , err
71+ }
72+
73+ // Initialize EvmCoinInfo in the module store. Chains bootstrapped before
74+ // v0.5.0 binaries never stored this information (it lived only in process
75+ // globals), so migrating nodes would otherwise see an empty EvmCoinInfo on
76+ // upgrade.
77+ if err := app .EVMKeeper .InitEvmCoinInfo (sdkCtx ); err != nil {
6178 return nil , err
6279 }
63- // Initialize EvmCoinInfo in the module store. Chains bootstrapped before v0.5.0
64- // binaries never stored this information (it lived only in process globals),
65- // so migrating nodes would otherwise see an empty EvmCoinInfo on upgrade.
80+
81+ return app .ModuleManager .RunMigrations (ctx , app .Configurator (), fromVM )
82+ },
83+ )
84+
85+ // New upgrade to backfill preinstalls and optionally activate new static precompile.
86+ app .UpgradeKeeper .SetUpgradeHandler (
87+ UpgradeName ,
88+ func (ctx context.Context , _ upgradetypes.Plan , fromVM module.VersionMap ) (module.VersionMap , error ) {
89+ sdkCtx := sdk .UnwrapSDKContext (ctx )
90+
91+ // Optionally activate a new static precompile if it is available in
92+ // the binary and not yet active in chain state.
93+ evmParams := app .EVMKeeper .GetParams (sdkCtx )
94+ if ! slices .Contains (evmParams .ActiveStaticPrecompiles , OptionalStaticPrecompileAddress ) {
95+ if ! slices .Contains (vmtypes .AvailableStaticPrecompiles , OptionalStaticPrecompileAddress ) {
96+ return nil , fmt .Errorf ("cannot activate static precompile %s: address not available in binary" , OptionalStaticPrecompileAddress )
97+ }
98+ evmParams .ActiveStaticPrecompiles = append (evmParams .ActiveStaticPrecompiles , OptionalStaticPrecompileAddress )
99+ if err := app .EVMKeeper .SetParams (sdkCtx , evmParams ); err != nil {
100+ return nil , err
101+ }
102+ }
103+
104+ // Add only missing default preinstalls. If an address has no code hash
105+ // but already has an account, abort to avoid mutating unknown state.
106+ missingPreinstalls := make ([]vmtypes.Preinstall , 0 , len (vmtypes .DefaultPreinstalls ))
107+ for _ , preinstall := range vmtypes .DefaultPreinstalls {
108+ addr := common .HexToAddress (preinstall .Address )
109+ codeHash := app .EVMKeeper .GetCodeHash (sdkCtx , addr )
110+ if ! vmtypes .IsEmptyCodeHash (codeHash .Bytes ()) {
111+ continue
112+ }
113+
114+ accAddress := sdk .AccAddress (addr .Bytes ())
115+ if acc := app .AccountKeeper .GetAccount (sdkCtx , accAddress ); acc != nil {
116+ // Skip addresses that already have an account (e.g. a funded EOA)
117+ // rather than halting the chain
118+ sdkCtx .Logger ().Warn (
119+ "skipping preinstall: account exists with empty code hash" ,
120+ "address" , preinstall .Address ,
121+ )
122+ continue
123+ }
124+
125+ missingPreinstalls = append (missingPreinstalls , preinstall )
126+ }
127+
128+ if len (missingPreinstalls ) > 0 {
129+ if err := app .EVMKeeper .AddPreinstalls (sdkCtx , missingPreinstalls ); err != nil {
130+ return nil , err
131+ }
132+ }
133+
134+ // Ensure EvmCoinInfo is present in the module store. This is idempotent
135+ // and required because this upgrade path may run on chains that never
136+ // executed the LegacyUpgradeName handler (which also calls this).
66137 if err := app .EVMKeeper .InitEvmCoinInfo (sdkCtx ); err != nil {
67138 return nil , err
68139 }
@@ -75,7 +146,7 @@ func (app EVMD) RegisterUpgradeHandlers() {
75146 panic (err )
76147 }
77148
78- if upgradeInfo .Name == UpgradeName && ! app .UpgradeKeeper .IsSkipHeight (upgradeInfo .Height ) {
149+ if ( upgradeInfo .Name == LegacyUpgradeName || upgradeInfo . Name == UpgradeName ) && ! app .UpgradeKeeper .IsSkipHeight (upgradeInfo .Height ) {
79150 storeUpgrades := storetypes.StoreUpgrades {
80151 Added : []string {},
81152 }
0 commit comments