From 5820b3d9f097adbb37943d2da306eb213df70d15 Mon Sep 17 00:00:00 2001 From: metalarm10 Date: Wed, 11 Mar 2026 13:06:40 +0300 Subject: [PATCH] fix missing DenomUnits update in v6 denom metadata migration --- app/app.go | 6 ++ .../v6_fix_denom_metadata/denom_metadata.go | 49 +++++++++++++++ .../denom_metadata_test.go | 60 +++++++++++++++++++ app/upgrade/v6_fix_denom_metadata/upgrade.go | 37 ++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 app/upgrade/v6_fix_denom_metadata/denom_metadata.go create mode 100644 app/upgrade/v6_fix_denom_metadata/denom_metadata_test.go create mode 100644 app/upgrade/v6_fix_denom_metadata/upgrade.go diff --git a/app/app.go b/app/app.go index 56ece019..6835691e 100644 --- a/app/app.go +++ b/app/app.go @@ -132,6 +132,7 @@ import ( "github.com/tokenize-x/tx-chain/v6/app/openapi" appupgrade "github.com/tokenize-x/tx-chain/v6/app/upgrade" appupgradev6 "github.com/tokenize-x/tx-chain/v6/app/upgrade/v6" + appupgradev6fixdenommetadata "github.com/tokenize-x/tx-chain/v6/app/upgrade/v6_fix_denom_metadata" "github.com/tokenize-x/tx-chain/v6/docs" "github.com/tokenize-x/tx-chain/v6/pkg/config" "github.com/tokenize-x/tx-chain/v6/pkg/config/constant" @@ -1203,6 +1204,11 @@ func New( app.AccountKeeper.AddressCodec(), app.StakingKeeper.ValidatorAddressCodec(), ), + appupgradev6fixdenommetadata.New( + app.ModuleManager, + app.configurator, + app.BankKeeper, + ), } upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() diff --git a/app/upgrade/v6_fix_denom_metadata/denom_metadata.go b/app/upgrade/v6_fix_denom_metadata/denom_metadata.go new file mode 100644 index 00000000..666ada99 --- /dev/null +++ b/app/upgrade/v6_fix_denom_metadata/denom_metadata.go @@ -0,0 +1,49 @@ +package v6fixdenommetadata + +import ( + "context" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/tokenize-x/tx-chain/v6/pkg/config/constant" + wbankkeeper "github.com/tokenize-x/tx-chain/v6/x/wbank/keeper" +) + +// MigrateDenomMetadata fixes the DenomUnits that were missed in the v6 migration. +func MigrateDenomMetadata(ctx context.Context, bankKeeper wbankkeeper.BaseKeeperWrapper) error { + var denom string + var prefix string + + sdkCtx := sdk.UnwrapSDKContext(ctx) + + switch sdkCtx.ChainID() { + case string(constant.ChainIDMain): + denom = constant.DenomMain + prefix = "" + case string(constant.ChainIDTest): + denom = constant.DenomTest + prefix = "test" + case string(constant.ChainIDDev): + denom = constant.DenomDev + prefix = "dev" + default: + return fmt.Errorf("unknown chain id: %s", sdkCtx.ChainID()) + } + + meta, found := bankKeeper.GetDenomMetaData(ctx, denom) + if !found { + return fmt.Errorf("denom metadata not found for %s", denom) + } + + displayDenom := prefix + "tx" + for i, unit := range meta.DenomUnits { + if unit.Exponent == 6 { + meta.DenomUnits[i].Denom = displayDenom + } + } + + bankKeeper.SetDenomMetaData(ctx, meta) + + return nil +} diff --git a/app/upgrade/v6_fix_denom_metadata/denom_metadata_test.go b/app/upgrade/v6_fix_denom_metadata/denom_metadata_test.go new file mode 100644 index 00000000..8462a79a --- /dev/null +++ b/app/upgrade/v6_fix_denom_metadata/denom_metadata_test.go @@ -0,0 +1,60 @@ +package v6fixdenommetadata_test + +import ( + "testing" + "time" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/require" + + v6fixdenommetadata "github.com/tokenize-x/tx-chain/v6/app/upgrade/v6_fix_denom_metadata" + "github.com/tokenize-x/tx-chain/v6/pkg/config/constant" + "github.com/tokenize-x/tx-chain/v6/testutil/simapp" +) + +func TestMigrateDenomMetadata(t *testing.T) { + requireT := require.New(t) + + testApp := simapp.New() + ctx := testApp.NewContext(false). + WithChainID(string(constant.ChainIDDev)). + WithBlockTime(time.Now()) + + // Reproduce the broken on-chain state left by v6: Display, Description, Symbol were + // rebranded to "tx" but DenomUnits was missed, leaving "devcore" at exponent 6. + testApp.BankKeeper.SetDenomMetaData(ctx, banktypes.Metadata{ + Description: "devtx coin", + DenomUnits: []*banktypes.DenomUnit{ + {Denom: constant.DenomDev, Exponent: 0}, + {Denom: constant.DenomDevDisplay, Exponent: 6}, // "devcore" - not updated by v6 + }, + Base: constant.DenomDev, + Display: "devtx", // updated by v6 + Name: constant.DenomDev, + Symbol: "udevtx", + }) + + // Verify the inconsistent state before fix + meta, found := testApp.BankKeeper.GetDenomMetaData(ctx, constant.DenomDev) + requireT.True(found) + requireT.Equal("devtx", meta.Display) + requireT.Equal("devcore", meta.DenomUnits[1].Denom) + + // Run the fix + err := v6fixdenommetadata.MigrateDenomMetadata(ctx, testApp.BankKeeper) + requireT.NoError(err) + + // Verify the fix + meta, found = testApp.BankKeeper.GetDenomMetaData(ctx, constant.DenomDev) + requireT.True(found) + requireT.Equal("devtx", meta.Display) + requireT.Equal("devtx", meta.DenomUnits[1].Denom) + requireT.Equal(uint32(6), meta.DenomUnits[1].Exponent) + + // Verify base unit unchanged + requireT.Equal(constant.DenomDev, meta.DenomUnits[0].Denom) + requireT.Equal(uint32(0), meta.DenomUnits[0].Exponent) + + // Verify the metadata passes validation + requireT.NoError(meta.Validate()) +} diff --git a/app/upgrade/v6_fix_denom_metadata/upgrade.go b/app/upgrade/v6_fix_denom_metadata/upgrade.go new file mode 100644 index 00000000..f329e504 --- /dev/null +++ b/app/upgrade/v6_fix_denom_metadata/upgrade.go @@ -0,0 +1,37 @@ +package v6fixdenommetadata + +import ( + "context" + + store "cosmossdk.io/store/types" + upgradetypes "cosmossdk.io/x/upgrade/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/tokenize-x/tx-chain/v6/app/upgrade" + wbankkeeper "github.com/tokenize-x/tx-chain/v6/x/wbank/keeper" +) + +// Name defines the upgrade name. +const Name = "v6_fix_denom_metadata" + +// New makes an upgrade handler for v6_fix_denom_metadata upgrade. +func New( + mm *module.Manager, + configurator module.Configurator, + bankKeeper wbankkeeper.BaseKeeperWrapper, +) upgrade.Upgrade { + return upgrade.Upgrade{ + Name: Name, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{}, + Deleted: []string{}, + }, + Upgrade: func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + if err := MigrateDenomMetadata(ctx, bankKeeper); err != nil { + return nil, err + } + + return mm.RunMigrations(ctx, configurator, vm) + }, + } +}