From 95da49b2af4ab789f9937e1fe3dbdbbdaf5fe53f Mon Sep 17 00:00:00 2001 From: Philip Su Date: Mon, 12 Jun 2023 22:32:19 -0700 Subject: [PATCH] [WIP] Add display,name,symbol to tokenfactory denom creation (#861) Add display,name,symbol to tokenfactory denom creation --- .../dex_module/place_order_test.yaml | 2 +- .../create_tokenfactory_test.yaml | 20 ++++++++++++ x/tokenfactory/keeper/createdenom.go | 4 +++ x/tokenfactory/keeper/createdenom_test.go | 7 +++++ x/tokenfactory/keeper/keeper_test.go | 7 +++-- x/tokenfactory/keeper/migrations.go | 31 +++++++++++++++++++ x/tokenfactory/keeper/migrations_test.go | 19 ++++++++++++ x/tokenfactory/module.go | 3 +- x/tokenfactory/types/expected_keepers.go | 1 + 9 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 integration_test/tokenfactory_module/create_tokenfactory_test.yaml diff --git a/integration_test/dex_module/place_order_test.yaml b/integration_test/dex_module/place_order_test.yaml index 97934cfad8..3c35ac1eb9 100644 --- a/integration_test/dex_module/place_order_test.yaml +++ b/integration_test/dex_module/place_order_test.yaml @@ -1,6 +1,6 @@ - name: Test placing a new order and query the placed order inputs: - # Get contract address, this requires contrat already deployed + # Get contract address, this requires contract already deployed - cmd: tail -1 integration_test/contracts/mars-addr.txt env: CONTRACT_ADDR # Prepare parameter diff --git a/integration_test/tokenfactory_module/create_tokenfactory_test.yaml b/integration_test/tokenfactory_module/create_tokenfactory_test.yaml new file mode 100644 index 0000000000..f91d0fbf11 --- /dev/null +++ b/integration_test/tokenfactory_module/create_tokenfactory_test.yaml @@ -0,0 +1,20 @@ +- name: Test creating a denom + inputs: + # Get admin + - cmd: printf "12345678\n" | seid keys list --output json | jq ".[] | select (.name==\"admin\")" | jq -r .address + env: ADMIN_ADDR + # Create denom + - cmd: printf "12345678\n" | seid tx tokenfactory create-denom test --from admin --fees 2000usei -y + # Query various fields about denom + - cmd: seid q bank denom-metadata --output json | jq .metadatas | jq ".[] | select (.base==\"factory/${ADMIN_ADDR}/test\")" | jq -r .base + env: BASE + - cmd: seid q bank denom-metadata --output json | jq .metadatas | jq ".[] | select (.base==\"factory/${ADMIN_ADDR}/test\")" | jq -r .name + env: NAME + - cmd: seid q bank denom-metadata --output json | jq .metadatas | jq ".[] | select (.base==\"factory/${ADMIN_ADDR}/test\")" | jq -r .symbol + env: SYMBOL + - cmd: seid q bank denom-metadata --output json | jq .metadatas | jq ".[] | select (.base==\"factory/${ADMIN_ADDR}/test\")" | jq -r .display + env: DISPLAY + verifiers: + # All fields should be populated and match the base name + - type: eval + expr: NAME == BASE and SYMBOL == BASE and DISPLAY == BASE diff --git a/x/tokenfactory/keeper/createdenom.go b/x/tokenfactory/keeper/createdenom.go index 466dbe296f..5fe2d82e67 100644 --- a/x/tokenfactory/keeper/createdenom.go +++ b/x/tokenfactory/keeper/createdenom.go @@ -29,6 +29,10 @@ func (k Keeper) createDenomAfterValidation(ctx sdk.Context, creatorAddr string, Exponent: 0, }}, Base: denom, + // The following is necessary for x/bank denom validation + Display: denom, + Name: denom, + Symbol: denom, } k.bankKeeper.SetDenomMetaData(ctx, denomMetaData) diff --git a/x/tokenfactory/keeper/createdenom_test.go b/x/tokenfactory/keeper/createdenom_test.go index 96c54bb3d7..21d5b4372f 100644 --- a/x/tokenfactory/keeper/createdenom_test.go +++ b/x/tokenfactory/keeper/createdenom_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "fmt" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -96,7 +97,13 @@ func (suite *KeeperTestSuite) TestCreateDenom() { suite.Require().NoError(err) suite.Require().Equal(suite.TestAccs[0].String(), queryRes.AuthorityMetadata.Admin) + // Make sure that the denom is valid from the perspective of x/bank + bankQueryRes, err := suite.bankQueryClient.DenomMetadata(suite.Ctx.Context(), &banktypes.QueryDenomMetadataRequest{ + Denom: res.GetNewTokenDenom(), + }) + suite.Require().NoError(err) + suite.Require().NoError(bankQueryRes.Metadata.Validate()) } else { suite.Require().Error(err) } diff --git a/x/tokenfactory/keeper/keeper_test.go b/x/tokenfactory/keeper/keeper_test.go index f81c91b64d..05e6bf620b 100644 --- a/x/tokenfactory/keeper/keeper_test.go +++ b/x/tokenfactory/keeper/keeper_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,8 +16,9 @@ import ( type KeeperTestSuite struct { apptesting.KeeperTestHelper - queryClient types.QueryClient - msgServer types.MsgServer + queryClient types.QueryClient + bankQueryClient banktypes.QueryClient + msgServer types.MsgServer // defaultDenom is on the suite, as it depends on the creator test address. defaultDenom string } @@ -31,6 +33,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.SetupTokenFactory() suite.queryClient = types.NewQueryClient(suite.QueryHelper) + suite.bankQueryClient = banktypes.NewQueryClient(suite.QueryHelper) suite.msgServer = keeper.NewMsgServerImpl(suite.App.TokenFactoryKeeper) } diff --git a/x/tokenfactory/keeper/migrations.go b/x/tokenfactory/keeper/migrations.go index 6bfa0f32d4..b4ef3de98b 100644 --- a/x/tokenfactory/keeper/migrations.go +++ b/x/tokenfactory/keeper/migrations.go @@ -1,8 +1,11 @@ package keeper import ( + "fmt" "strings" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/sei-protocol/sei-chain/x/tokenfactory/types" ) @@ -37,3 +40,31 @@ func (m Migrator) Migrate2to3(ctx sdk.Context) error { } return nil } + +func (m Migrator) Migrate3to4(ctx sdk.Context) error { + // Set denom metadata for all denoms + m.keeper.bankKeeper.IterateTotalSupply(ctx, func(coin sdk.Coin) bool { + fmt.Printf("Migration denom: %s\n", coin.Denom) + if denomMetadata, err := m.keeper.bankKeeper.GetDenomMetaData(ctx, coin.Denom); !err { + panic(fmt.Errorf("denom %s does not exist", coin.Denom)) + } else { + m.SetMetadata(&denomMetadata) + m.keeper.bankKeeper.SetDenomMetaData(ctx, denomMetadata) + } + return true + }) + return nil +} + +func (m Migrator) SetMetadata(denomMetadata *banktypes.Metadata) { + if len(denomMetadata.Base) == 0 { + panic(fmt.Errorf("no base exists for denom %v", denomMetadata)) + } + if len(denomMetadata.Display) == 0 { + denomMetadata.Display = denomMetadata.Base + denomMetadata.Name = denomMetadata.Base + denomMetadata.Symbol = denomMetadata.Base + } else { + fmt.Printf("Denom %s already has denom set", denomMetadata.Base) + } +} diff --git a/x/tokenfactory/keeper/migrations_test.go b/x/tokenfactory/keeper/migrations_test.go index 43a97accf7..4f75273ad1 100644 --- a/x/tokenfactory/keeper/migrations_test.go +++ b/x/tokenfactory/keeper/migrations_test.go @@ -1,6 +1,7 @@ package keeper import ( + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "strings" "testing" @@ -66,3 +67,21 @@ func TestMigrate2to3(t *testing.T) { paramsSubspace.GetParamSet(ctx, ¶ms) require.Equal(t, types.Params{}, params) } + +func TestMigrate3To4(t *testing.T) { + // Test migration with all metadata denom + metadata := banktypes.Metadata{Description: sdk.DefaultBondDenom, Base: sdk.DefaultBondDenom, Display: sdk.DefaultBondDenom, Name: sdk.DefaultBondDenom, Symbol: sdk.DefaultBondDenom} + keeper := NewKeeper(nil, nil, typesparams.Subspace{}, nil, nil, nil) + m := NewMigrator(keeper) + m.SetMetadata(&metadata) + require.Equal(t, sdk.DefaultBondDenom, metadata.Display) + require.Equal(t, sdk.DefaultBondDenom, metadata.Name) + require.Equal(t, sdk.DefaultBondDenom, metadata.Symbol) + // Test migration with missing fields + testDenom := "test_denom" + metadata = banktypes.Metadata{Base: testDenom} + m.SetMetadata(&metadata) + require.Equal(t, testDenom, metadata.Display) + require.Equal(t, testDenom, metadata.Name) + require.Equal(t, testDenom, metadata.Symbol) +} diff --git a/x/tokenfactory/module.go b/x/tokenfactory/module.go index bef7b6ff17..29c99ad701 100644 --- a/x/tokenfactory/module.go +++ b/x/tokenfactory/module.go @@ -148,6 +148,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { m := keeper.NewMigrator(am.keeper) _ = cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { return nil }) _ = cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3) + _ = cfg.RegisterMigration(types.ModuleName, 3, m.Migrate3to4) } // RegisterInvariants registers the x/tokenfactory module's invariants. @@ -172,7 +173,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 4 } // BeginBlock executes all ABCI BeginBlock logic respective to the tokenfactory module. func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/tokenfactory/types/expected_keepers.go b/x/tokenfactory/types/expected_keepers.go index 96b3012952..045c857b3e 100644 --- a/x/tokenfactory/types/expected_keepers.go +++ b/x/tokenfactory/types/expected_keepers.go @@ -12,6 +12,7 @@ type BankKeeper interface { SetDenomMetaData(ctx sdk.Context, denomMetaData banktypes.Metadata) HasSupply(ctx sdk.Context, denom string) bool + IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error