Skip to content

Commit

Permalink
refactor: migrate bridge token data and update metadata alias (#749)
Browse files Browse the repository at this point in the history
Co-authored-by: nulnut <[email protected]>
  • Loading branch information
zakir-code and nulnut authored Oct 17, 2024
1 parent bff5bda commit 694f87b
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 5 deletions.
7 changes: 7 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ type CrossChainKeepers struct {
Layer2Keeper crosschainkeeper.Keeper
}

func (c CrossChainKeepers) ToSlice() []crosschainkeeper.Keeper {
return []crosschainkeeper.Keeper{
c.BscKeeper, c.PolygonKeeper, c.AvalancheKeeper, c.EthKeeper,
c.TronKeeper, c.ArbitrumKeeper, c.OptimismKeeper, c.Layer2Keeper,
}
}

type AppKeepers struct {
// keys to access the substores
keys map[string]*storetypes.KVStoreKey
Expand Down
2 changes: 1 addition & 1 deletion app/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func appModules(
layer2.NewAppModule(app.Layer2Keeper),
fxevm.NewAppModule(app.EvmKeeper, app.AccountKeeper, app.GetSubspace(evmtypes.ModuleName)),
feemarket.NewAppModule(app.FeeMarketKeeper, app.GetSubspace(feemarkettypes.ModuleName)),
erc20.NewAppModule(app.Erc20Keeper),
erc20.NewAppModule(app.GetKey(erc20types.StoreKey), appCodec, app.Erc20Keeper, app.BankKeeper, app.CrossChainKeepers.ToSlice()),
migrate.NewAppModule(app.MigrateKeeper),
ibctransfer.NewAppModule(app.IBCTransferKeeper),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
Expand Down
1 change: 1 addition & 0 deletions app/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func newContext(t *testing.T, myApp *app.App, chainId string, deliveState bool)
} else {
ctx = myApp.GetContextForCheckTx(nil).WithBlockHeader(header)
}
ctx = ctx.WithChainID(chainId)
ctx = ctx.WithHeaderInfo(coreheader.Info{
Height: header.Height,
Time: header.Time,
Expand Down
25 changes: 25 additions & 0 deletions app/upgrades/v8/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package v8
import (
"context"
"encoding/hex"
"strings"

storetypes "cosmossdk.io/store/types"
upgradetypes "cosmossdk.io/x/upgrade/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

"github.com/functionx/fx-core/v8/app/keepers"
fxtypes "github.com/functionx/fx-core/v8/types"
crosschainkeeper "github.com/functionx/fx-core/v8/x/crosschain/keeper"
"github.com/functionx/fx-core/v8/x/gov/keeper"
fxgovv8 "github.com/functionx/fx-core/v8/x/gov/migrations/v8"
Expand All @@ -38,6 +41,8 @@ func CreateUpgradeHandler(mm *module.Manager, configurator module.Configurator,
return fromVM, err
}

updateMetadata(cacheCtx, app.BankKeeper)

commit()
cacheCtx.Logger().Info("upgrade complete", "module", "upgrade")
return toVM, nil
Expand Down Expand Up @@ -75,3 +80,23 @@ func removeStoreKeys(ctx sdk.Context, storeKey *storetypes.KVStoreKey, keys [][]
deleteFn(key)
}
}

func updateMetadata(ctx sdk.Context, bankKeeper bankkeeper.Keeper) {
mds := bankKeeper.GetAllDenomMetaData(ctx)
for _, md := range mds {
if md.Base == fxtypes.DefaultDenom || len(md.DenomUnits) == 0 || len(md.DenomUnits[0].Aliases) == 0 {
continue
}
// remove alias
md.DenomUnits[0].Aliases = []string{}

// update pundix/purse base denom
newBase := strings.ToLower(md.Symbol)
if md.Base != newBase {
md.Base = newBase
md.DenomUnits[0].Denom = newBase
}

bankKeeper.SetDenomMetaData(ctx, md)
}
}
20 changes: 20 additions & 0 deletions x/crosschain/keeper/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/functionx/fx-core/v8/x/crosschain/types"
)

// Deprecated: do not use, remove in v8
func (k Keeper) LegacyGetDenomBridgeToken(ctx sdk.Context, denom string) (*types.BridgeToken, bool) {
store := ctx.KVStore(k.storeKey)
data := store.Get(types.GetTokenToDenomKey(denom))
if len(data) == 0 {
return nil, false
}
return &types.BridgeToken{
Denom: denom,
Token: string(data),
}, true
}
21 changes: 21 additions & 0 deletions x/erc20/migrations/v8/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package v8

import (
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/functionx/fx-core/v8/x/erc20/types"
)

func LegacyIsNativeERC20(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, denom string) bool {
store := ctx.KVStore(storeKey)
id := store.Get(append(types.KeyPrefixTokenPairByDenom, []byte(denom)...))
bz := store.Get(append(types.KeyPrefixTokenPair, id...))
if len(bz) == 0 {
return false
}
var tokenPair types.ERC20Token
cdc.MustUnmarshal(bz, &tokenPair)
return tokenPair.IsNativeERC20()
}
97 changes: 97 additions & 0 deletions x/erc20/migrations/v8/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package v8

import (
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"

fxtypes "github.com/functionx/fx-core/v8/types"
arbitrumtypes "github.com/functionx/fx-core/v8/x/arbitrum/types"
ethtypes "github.com/functionx/fx-core/v8/x/eth/types"
optimismtypes "github.com/functionx/fx-core/v8/x/optimism/types"
)

func (m Migrator) MigrateToken(ctx sdk.Context) error {
// add FX bridge token
if err := m.addToken(ctx, fxtypes.DefaultDenom, ""); err != nil {
return err
}

mds := m.bankKeeper.GetAllDenomMetaData(ctx)
for _, md := range mds {
if len(md.DenomUnits) == 0 || len(md.DenomUnits[0].Aliases) == 0 {
continue
}
baseDenom := strings.ToLower(md.Symbol)
// add other bridge/ibc token
for _, alias := range md.DenomUnits[0].Aliases {
if err := m.addToken(ctx, baseDenom, alias); err != nil {
return err
}
}
// add pundix/purse token
if md.Base == baseDenom {
continue
}
if err := m.addToken(ctx, baseDenom, md.Base); err != nil {
return err
}
}
return nil
}

func (m Migrator) addToken(
ctx sdk.Context,
base, alias string,
) error {
if strings.HasPrefix(alias, ibctransfertypes.DenomPrefix+"/") {
return m.addIBCToken(ctx, base, alias)
}
return m.addBridgeToken(ctx, base, alias)
}

func (m Migrator) addIBCToken(ctx sdk.Context, base, alias string) error {
channel, found := getIBCDenomTrace(ctx, alias)
if !found {
return sdkerrors.ErrInvalidCoins.Wrapf("ibc denom hash not found: %s %s", base, alias)
}
ctx.Logger().Info("add ibc token", "base-denom", base, "alias", alias, "channel", channel)
return m.keeper.AddIBCToken(ctx, base, channel, alias)
}

func (m Migrator) addBridgeToken(
ctx sdk.Context,
base, alias string,
) error {
if getExcludeBridgeToken(ctx, alias) {
return nil
}
for _, ck := range m.crossChainKeepers {
canAddFxBridgeToken := base == fxtypes.DefaultDenom && ck.ModuleName() == ethtypes.ModuleName
canAddBridgeToken := strings.HasPrefix(alias, ck.ModuleName())
excludeModule := ck.ModuleName() != arbitrumtypes.ModuleName && ck.ModuleName() != optimismtypes.ModuleName
if ctx.ChainID() == fxtypes.MainnetChainId {
canAddBridgeToken = canAddBridgeToken && excludeModule
}
if !canAddFxBridgeToken && !canAddBridgeToken {
continue
}

if alias == "" { // FX token
alias = base
}
legacyBridgeToken, found := ck.LegacyGetDenomBridgeToken(ctx, alias)
if !found {
return sdkerrors.ErrKeyNotFound.Wrapf("module %s bridge token: %s", ck.ModuleName(), alias)
}
ctx.Logger().Info("add bridge token", "base-denom", base, "alias", alias, "module", ck.ModuleName(), "contract", legacyBridgeToken.Token)
isNativeErc20 := LegacyIsNativeERC20(ctx, m.storeKey, m.cdc, base)
if err := m.keeper.AddBridgeToken(ctx, base, ck.ModuleName(), legacyBridgeToken.Token, isNativeErc20); err != nil {
return err
}
break
}
return nil
}
34 changes: 34 additions & 0 deletions x/erc20/migrations/v8/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package v8

import (
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"

crosschainkeeper "github.com/functionx/fx-core/v8/x/crosschain/keeper"
"github.com/functionx/fx-core/v8/x/erc20/keeper"
)

type Migrator struct {
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
keeper keeper.Keeper
bankKeeper bankkeeper.Keeper
crossChainKeepers []crosschainkeeper.Keeper
}

func NewMigrator(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, keeper keeper.Keeper, bk bankkeeper.Keeper, cks []crosschainkeeper.Keeper) Migrator {
return Migrator{
storeKey: storeKey,
cdc: cdc,
keeper: keeper,
bankKeeper: bk,
crossChainKeepers: cks,
}
}

// Migrate3to4 migrates from version 3 to 4.
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
return m.MigrateToken(ctx)
}
81 changes: 81 additions & 0 deletions x/erc20/migrations/v8/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package v8

import (
sdk "github.com/cosmos/cosmos-sdk/types"

fxtypes "github.com/functionx/fx-core/v8/types"
)

var (
testnetIBCDenomTrace = map[string]string{
// cosmoshub
"ibc/C892C98C728A916DFD74A8A6036DF0B6C9B590C813C4CA1E94402D20F7771174": "channel-90", // uatom

// osmosis
"ibc/DA227B314073473C4008CDFAE7D6629F5182891AA9A34403BF9CB0F2E380D274": "channel-119", // uosmo
"ibc/8B7A6637DC5F0921CB24D2F3A051E9797CA50EF728E72872219F0E85A1BFDDD9": "channel-119", // atom/osmo
"ibc/530063F78415D637217C28ACE7CC7A9ADCC7DD4E7D5A20CE5E143744BE33E685": "channel-119", // stosmo/tosmo
"ibc/A6D5D1C0A6BBA47E6BBC6C6CBEF531045599345A6CD4FC8B6447909C8D900B33": "channel-119", // tatom/tosmo
"ibc/C2D7826927DD7FF3EA2F9D3A93889EA09667429847C23007D3583DCEB98CD0BF": "channel-119", // usdc/tosmo
"ibc/8C8FA24B0CE2E2BE006A1D6CE7D14DD64C463D7887992832C8AE9EF4CEA6FC13": "channel-119", // wbtc/tosmo
"ibc/3DCFA7233C0E27C07223980CB233EB3D87F64FE4D5DBB88DBC744E0088AF7927": "channel-119", // weth/tosmo
}
mainnetIBCDenomTrace = map[string]string{
// cosmoshub
"ibc/A670D9568B3E399316EEDE40C1181B7AA4BD0695F0B37513CE9B95B977DFC12E": "channel-10", // uatom
"ibc/19FE4199D5E206A756AA8656D6CCECA3A50AECB081CC73126060D592BD93A15B": "channel-10", // uosmo(from cosmoshub)
"ibc/04734B17EDC1F68BA599D8387A8BB0266684F46D42F4D5C7667BF370D21D9B8E": "channel-10", // aevmos
"ibc/4E7EFFD6C691F22FEA1C3B72DB3C275AF595A48C769CBB79289BDBD109A1F39A": "channel-10", // inj
"ibc/B61B71A43BA8D837D866B6417CF65B391A9177B3C3391527BF88A1174C55D939": "channel-10", // uaxl
"ibc/DE7DEEC0A8B377C9C3292884B80BDF264BEE97EF2F85DABE2E46B00A2E15C29A": "channel-10", // ukava
"ibc/8136D7DCECF799F835497A02725092811BA22810F88A1D0678600E13CEB249BE": "channel-10", // uscrt
"ibc/5A730E758B54FDEFAC2696BC6A24342192DF8F3D2B0B947C6D26AF53E9E943CA": "channel-10", // ustrd

// osmosis
"ibc/D7B22A85AB15F44A3152EBF7F2D37B6061F66FAF637E42C287FC649F1F5CA348": "channel-19", // uosmo
"ibc/95B9D47D7890C9F3E9104DD1DA74D3CCD4890E453FE0F0A711E782CE77B13455": "channel-19", // ulvn(from osmosis)
"ibc/BE612CFB5445AD2F56FAE496C0848FA381F967970A4CA586B1F90123AA62C4D4": "channel-19", // atom/osmo
"ibc/1B68E41D8D074F645388189E46C0F480111936F136C06E57FF559AB052D5BF78": "channel-19", // akt/atom
"ibc/145B926094C7649D85679D577FE8D3FD713C8586346518BF838712D4498A37E3": "channel-19", // akt/osmo
"ibc/49ABFFC9B2823450EDF1D4548B5B6314B473E497CF454726575458E7FDF3C52B": "channel-19", // atom/qatom
"ibc/373E4EFF2671B14802D9B3AB3EAF0345FBED921949654EB115C5072DFEB93AB0": "channel-19", // atom/statom
"ibc/AC80A1534F33EBA754A4EFC4E6AC3672850CCD0CDE9666B635984FB41BE91DA1": "channel-19", // atom/stkatom
"ibc/16770A91B7849DAFC413E7094E2CD66A8E908DB8550D7AD7F9B2115F7E00AC33": "channel-19", // axl/osmo
"ibc/A283012C5CA64DE2B8C6B4979B9A99E5144AA30F707D0FE16ED3ADD0F0BEDB42": "channel-19", // cro/osmo
"ibc/E30827509649DBDA201E98E14EDD52116124D2BCFAF70BBA5E7CA2615E086A2C": "channel-19", // dai/osmo
"ibc/30033E46154DB10107B18AE42AFFEBD1FAF4C36AF0142F1156B0ECC1796227FE": "channel-19", // eth/osmo
"ibc/86C7F2DD93F556650BF0992A2F61CBBA42600BD7FFD3F98CCE74C9A1994EB565": "channel-19", // evmos/osmo
"ibc/97B0CC9611DFE37744BA8EE27B32DE9509FED9ECDFCE59434E0B549BAD67D83E": "channel-19", // inj/osmo
"ibc/E126BB8628A2259291A668E2C666C97D60D06C59717BD2E34290A6DEF8AA8D19": "channel-19", // juno/osmo
"ibc/1CC704EB23F1B0EAA9634F088E2F476937E3B4519782B996B63F096E69DBAF5B": "channel-19", // scrt/osmo
"ibc/DFF778E0F743B1FE66D6018051AB5395F7CB470B19673149F1422B9DE68CD62C": "channel-19", // stars/osmo
"ibc/69058D0A3D0E3E63DC4AA39571007277A16F968290084BD80AFFFA2831B4AD10": "channel-19", // stosmo/osmo
"ibc/FDF9794382805B73B7182E1155E9A74EAA0CB37CFEC547B66335E21CC55829C2": "channel-19", // strd/osmo
"ibc/D54952FCA1DAE3919B89F2D809A0400C372D5919480BA2FDC9FF4217384DA7CE": "channel-19", // usdc/nls
"ibc/8C412C753AF39C7A050A250FE4DD3B4975AE6B714F3D922E94E0DFA5F81EBEA0": "channel-19", // usdc/osmo
"ibc/A655D0A048B0FD73458D9E6F020ABBBC3DD39F2D3AEACD2DCD1B0EC26B5EC425": "channel-19", // wbtc/osmo

// chihuahua
"ibc/210FA8AD411B627A0EFAEF4580B0D61C707C2C9E138AAF5AA087B4864B1E3599": "channel-22", // uhuahua
}

testnetExcludeBridgeToken = map[string]bool{
"layer20xb1efb300876f993Dc6826f09E66FEaa1bc3A735F": true, // DEGEN
}
)

func getIBCDenomTrace(ctx sdk.Context, denom string) (trace string, ok bool) {
if ctx.ChainID() == fxtypes.TestnetChainId {
trace, ok = testnetIBCDenomTrace[denom]
} else {
trace, ok = mainnetIBCDenomTrace[denom]
}
return
}

func getExcludeBridgeToken(ctx sdk.Context, denom string) bool {
if ctx.ChainID() == fxtypes.TestnetChainId {
return testnetExcludeBridgeToken[denom]
}
return false
}
25 changes: 21 additions & 4 deletions x/erc20/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ import (
"fmt"

"cosmossdk.io/core/appmodule"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
"github.com/grpc-ecosystem/grpc-gateway/runtime"

crosschainkeeper "github.com/functionx/fx-core/v8/x/crosschain/keeper"
"github.com/functionx/fx-core/v8/x/erc20/keeper"
v8 "github.com/functionx/fx-core/v8/x/erc20/migrations/v8"
"github.com/functionx/fx-core/v8/x/erc20/types"
)

Expand Down Expand Up @@ -73,14 +77,22 @@ func (AppModuleBasic) RegisterInterfaces(interfaceRegistry codectypes.InterfaceR
// AppModule implements the AppModule interface for the capability module.
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper
storeKey storetypes.StoreKey
cdc codec.BinaryCodec
keeper keeper.Keeper
bankKeeper bankkeeper.Keeper
crossChainKeepers []crosschainkeeper.Keeper
}

// NewAppModule creates a new AppModule Object
func NewAppModule(keeper keeper.Keeper) AppModule {
func NewAppModule(storeKey storetypes.StoreKey, cdc codec.BinaryCodec, keeper keeper.Keeper, bk bankkeeper.Keeper, cks []crosschainkeeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
AppModuleBasic: AppModuleBasic{},
storeKey: storeKey,
cdc: cdc,
keeper: keeper,
bankKeeper: bk,
crossChainKeepers: cks,
}
}

Expand All @@ -98,6 +110,11 @@ func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServer(am.keeper))

m := v8.NewMigrator(am.storeKey, am.cdc, am.keeper, am.bankKeeper, am.crossChainKeepers)
if err := cfg.RegisterMigration(types.ModuleName, 3, m.Migrate3to4); err != nil {
panic(fmt.Sprintf("failed to migrate x/erc20 from version 3 to 4: %v", err))
}
}

// InitGenesis performs the capability module's genesis initialization It returns
Expand Down

0 comments on commit 694f87b

Please sign in to comment.