Skip to content

Commit

Permalink
feat: update token handling to improve security (#914)
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 Jan 16, 2025
1 parent 61bd6d0 commit c749ceb
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 8 deletions.
31 changes: 31 additions & 0 deletions app/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math/big"
"os"
"path/filepath"
"strings"
"testing"

"cosmossdk.io/collections"
Expand All @@ -20,6 +21,7 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
Expand Down Expand Up @@ -92,6 +94,9 @@ func Test_UpgradeTestnet(t *testing.T) {

// check bridge fee contract status
checkBridgeFeeContract(t, ctx, myApp)

checkMetadataValidate(t, ctx, myApp)
checkPundiAIFXERC20Token(t, ctx, myApp)
}

func buildApp(t *testing.T) *app.App {
Expand Down Expand Up @@ -174,6 +179,8 @@ func checkAppUpgrade(t *testing.T, ctx sdk.Context, myApp *app.App, bdd BeforeUp
checkPundixPurse(t, ctx, myApp)
checkTotalSupply(t, ctx, myApp)
checkLayer2OracleIsOnline(t, ctx, myApp.Layer2Keeper)
checkMetadataValidate(t, ctx, myApp)
checkPundiAIFXERC20Token(t, ctx, myApp)
}

func checkLayer2OracleIsOnline(t *testing.T, ctx sdk.Context, layer2Keeper crosschainkeeper.Keeper) {
Expand Down Expand Up @@ -565,3 +572,27 @@ func checkBridgeFeeContract(t *testing.T, ctx sdk.Context, myApp *app.App) {
require.Empty(t, oracles)
}
}

func checkMetadataValidate(t *testing.T, ctx sdk.Context, myApp *app.App) {
t.Helper()

myApp.BankKeeper.IterateAllDenomMetaData(ctx, func(metadata banktypes.Metadata) bool {
if len(metadata.DenomUnits) <= 1 {
return false
}
require.NoError(t, metadata.Validate())
require.NotEqual(t, metadata.Display, metadata.Base)
return false
})
}

func checkPundiAIFXERC20Token(t *testing.T, ctx sdk.Context, myApp *app.App) {
t.Helper()

has, err := myApp.Erc20Keeper.ERC20Token.Has(ctx, fxtypes.DefaultDenom)
require.NoError(t, err)
require.True(t, has)
has, err = myApp.Erc20Keeper.ERC20Token.Has(ctx, strings.ToUpper(fxtypes.FXDenom))
require.NoError(t, err)
require.False(t, has)
}
69 changes: 66 additions & 3 deletions app/upgrades/v8/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,22 @@ func upgradeTestnet(ctx sdk.Context, app *keepers.AppKeepers) error {
if err := migrateFeemarketGasPrice(ctx, app.FeeMarketKeeper); err != nil {
return err
}
if err := redeployTestnetContract(ctx, app.AccountKeeper, app.EvmKeeper, app.Erc20Keeper, app.EthKeeper); err != nil {
return err
}
if err := migrateCrosschainParams(ctx, app.CrosschainKeepers); err != nil {
return err
}

return redeployTestnetContract(ctx, app.AccountKeeper, app.EvmKeeper, app.Erc20Keeper, app.EthKeeper)
if err := migrateMetadataDisplay(ctx, app.BankKeeper); err != nil {
return err
}
if err := migrateErc20FXToPundiAI(ctx, app.Erc20Keeper); err != nil {
return err
}
return migrateMetadataFXToPundiAI(ctx, app.BankKeeper)
}

//nolint:gocyclo // mainnet
func upgradeMainnet(
ctx sdk.Context,
mm *module.Manager,
Expand Down Expand Up @@ -171,7 +180,15 @@ func upgradeMainnet(
if err = migrateFeemarketGasPrice(ctx, app.FeeMarketKeeper); err != nil {
return toVM, err
}

if err = migrateMetadataDisplay(ctx, app.BankKeeper); err != nil {
return toVM, err
}
if err = migrateErc20FXToPundiAI(ctx, app.Erc20Keeper); err != nil {
return toVM, err
}
if err = migrateMetadataFXToPundiAI(ctx, app.BankKeeper); err != nil {
return toVM, err
}
return toVM, nil
}

Expand Down Expand Up @@ -569,3 +586,49 @@ func migrateCrosschainParams(ctx sdk.Context, keepers keepers.CrosschainKeepers)
}
return nil
}

func migrateMetadataDisplay(ctx sdk.Context, bankKeeper bankkeeper.Keeper) error {
mds := bankKeeper.GetAllDenomMetaData(ctx)
for _, md := range mds {
if md.Display != md.Base || len(md.DenomUnits) <= 1 {
continue
}
for _, dus := range md.DenomUnits {
if dus.Denom != md.Base {
md.Display = dus.Denom
break
}
}
if err := md.Validate(); err != nil {
return err
}
bankKeeper.SetDenomMetaData(ctx, md)
}
return nil
}

func migrateErc20FXToPundiAI(ctx sdk.Context, keeper erc20keeper.Keeper) error {
fxDenom := strings.ToUpper(fxtypes.FXDenom)
erc20Token, err := keeper.GetERC20Token(ctx, fxDenom)
if err != nil {
return err
}
erc20Token.Denom = fxtypes.DefaultDenom
if err = keeper.ERC20Token.Set(ctx, erc20Token.Denom, erc20Token); err != nil {
return err
}
return keeper.ERC20Token.Remove(ctx, fxDenom)
}

func migrateMetadataFXToPundiAI(ctx sdk.Context, keeper bankkeeper.Keeper) error {
// add pundiai metadata
metadata := fxtypes.NewDefaultMetadata()
keeper.SetDenomMetaData(ctx, metadata)

// remove FX metadata
bk, ok := keeper.(bankkeeper.BaseKeeper)
if !ok {
return errors.New("bank keeper not implement bank.BaseKeeper")
}
return bk.BaseViewKeeper.DenomMetadata.Remove(ctx, strings.ToUpper(fxtypes.FXDenom))
}
2 changes: 1 addition & 1 deletion scripts/linter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -eo pipefail

patternLimits=(
"nolint:22"
"nolint:23"
"#nosec:5"
"CrossChain:4"
"cross chain:0"
Expand Down
3 changes: 2 additions & 1 deletion x/erc20/migrations/v8/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func (m Migrator) migrateParams(ctx sdk.Context, store storetypes.KVStore) error
}

func (m Migrator) migrateTokenPair(ctx sdk.Context, store storetypes.KVStore) error {
fxDenom := strings.ToUpper(fxtypes.FXDenom)
iterator := storetypes.KVStorePrefixIterator(store, KeyPrefixTokenPair)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
Expand All @@ -73,7 +74,7 @@ func (m Migrator) migrateTokenPair(ctx sdk.Context, store storetypes.KVStore) er
if !found {
return sdkerrors.ErrKeyNotFound.Wrapf("metadata not found: %s", tokenPair.GetDenom())
}
if md.Base == fxtypes.FXDenom || md.Base == strings.ToLower(md.Symbol) {
if md.Base == fxDenom || md.Base == strings.ToLower(md.Symbol) {
if err := m.keeper.ERC20Token.Set(ctx, md.Base, tokenPair); err != nil {
return err
}
Expand Down
8 changes: 5 additions & 3 deletions x/erc20/migrations/v8/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ import (
)

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

mds := m.bankKeeper.GetAllDenomMetaData(ctx)
for _, md := range mds {
// exclude FX and alias empty, except PUNDIX
if md.Base == fxtypes.FXDenom || (len(md.DenomUnits) == 0 || len(md.DenomUnits[0].Aliases) == 0) && md.Symbol != "PUNDIX" {
if md.Base == fxDenom || (len(md.DenomUnits) == 0 || len(md.DenomUnits[0].Aliases) == 0) && md.Symbol != "PUNDIX" {
continue
}

Expand Down Expand Up @@ -73,11 +74,12 @@ func (m Migrator) addIBCToken(ctx sdk.Context, base, alias string) error {
}

func (m Migrator) addBridgeToken(ctx sdk.Context, base, alias string) error {
fxDenom := strings.ToUpper(fxtypes.FXDenom)
if getExcludeBridgeToken(ctx, alias) {
return nil
}
for _, ck := range m.crosschainKeepers {
canAddFxBridgeToken := base == fxtypes.FXDenom && ck.ModuleName() == ethtypes.ModuleName
canAddFxBridgeToken := base == fxDenom && ck.ModuleName() == ethtypes.ModuleName

canAddBridgeToken := strings.HasPrefix(alias, ck.ModuleName())
excludeModule := ck.ModuleName() != arbitrumtypes.ModuleName && ck.ModuleName() != optimismtypes.ModuleName
Expand Down

0 comments on commit c749ceb

Please sign in to comment.