From ce9657b60f951d26b995943b0372e5e8696bbfd7 Mon Sep 17 00:00:00 2001 From: Zhiqiang Zhang <745124335@qq.com> Date: Mon, 16 Aug 2021 09:28:17 +0800 Subject: [PATCH] Export coinswap pool (#220) * export genesis * update query api * fix bug * can not issue lpt token * fix test error * fix test error --- .../coinswap/client/rest/grpc_query_test.go | 12 +- modules/coinswap/genesis.go | 24 ---- modules/coinswap/keeper/genesis.go | 31 +++++ modules/coinswap/keeper/genesis_test.go | 34 +++++ modules/coinswap/keeper/grpc_query.go | 3 +- modules/coinswap/keeper/pool.go | 27 +++- modules/coinswap/keeper/querier.go | 3 +- modules/coinswap/keeper/querier_test.go | 2 +- modules/coinswap/module.go | 8 +- modules/coinswap/types/genesis.go | 50 ++++++- modules/coinswap/types/genesis.pb.go | 131 +++++++++++++++--- modules/coinswap/types/utils.go | 10 ++ modules/coinswap/types/validation.go | 2 +- modules/token/types/validation.go | 4 +- modules/token/types/validation_test.go | 4 +- proto/coinswap/genesis.proto | 8 +- 16 files changed, 280 insertions(+), 73 deletions(-) delete mode 100644 modules/coinswap/genesis.go create mode 100644 modules/coinswap/keeper/genesis.go create mode 100644 modules/coinswap/keeper/genesis_test.go diff --git a/modules/coinswap/client/rest/grpc_query_test.go b/modules/coinswap/client/rest/grpc_query_test.go index d5f6ef4f..90e2b95b 100644 --- a/modules/coinswap/client/rest/grpc_query_test.go +++ b/modules/coinswap/client/rest/grpc_query_test.go @@ -173,7 +173,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399985965", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("1000", coins.AmountOf(lptDenom).String()) - url := fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url := fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err := rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("1000", gjson.Get(string(resp), "result.standard.amount").String()) @@ -235,7 +235,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399983955", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("3000", coins.AmountOf(lptDenom).String()) - url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err = rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("3000", gjson.Get(string(resp), "result.standard.amount").String()) @@ -297,7 +297,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399984693", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("3000", coins.AmountOf(lptDenom).String()) - url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err = rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("2252", gjson.Get(string(resp), "result.standard.amount").String()) @@ -359,7 +359,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399983930", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("3000", coins.AmountOf(lptDenom).String()) - url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err = rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("3005", gjson.Get(string(resp), "result.standard.amount").String()) @@ -416,7 +416,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399985923", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("1000", coins.AmountOf(lptDenom).String()) - url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err = rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("1002", gjson.Get(string(resp), "result.standard.amount").String()) @@ -473,7 +473,7 @@ func (s *IntegrationTestSuite) TestCoinswap() { s.Require().Equal("399986915", coins.AmountOf(sdk.DefaultBondDenom).String()) s.Require().Equal("0", coins.AmountOf(lptDenom).String()) - url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, symbol) + url = fmt.Sprintf("%s/coinswap/liquidities/%s", baseURL, lptDenom) resp, err = rest.GetRequest(url) s.Require().NoError(err) s.Require().Equal("0", gjson.Get(string(resp), "result.standard.amount").String()) diff --git a/modules/coinswap/genesis.go b/modules/coinswap/genesis.go deleted file mode 100644 index 9c5727a9..00000000 --- a/modules/coinswap/genesis.go +++ /dev/null @@ -1,24 +0,0 @@ -package coinswap - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/irisnet/irismod/modules/coinswap/keeper" - "github.com/irisnet/irismod/modules/coinswap/types" -) - -// InitGenesis new coinswap genesis -func InitGenesis(ctx sdk.Context, k keeper.Keeper, data types.GenesisState) { - if err := types.ValidateGenesis(data); err != nil { - panic(fmt.Errorf("panic for ValidateGenesis,%v", err)) - } - k.SetParams(ctx, data.Params) - k.SetStandardDenom(ctx, data.StandardDenom) -} - -// ExportGenesis returns a GenesisState for a given context and keeper. -func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { - return types.NewGenesisState(keeper.GetParams(ctx), keeper.GetStandardDenom(ctx)) -} diff --git a/modules/coinswap/keeper/genesis.go b/modules/coinswap/keeper/genesis.go new file mode 100644 index 00000000..e54d87ca --- /dev/null +++ b/modules/coinswap/keeper/genesis.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/irisnet/irismod/modules/coinswap/types" +) + +// InitGenesis initializes the coinswap module's state from a given genesis state. +func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { + if err := types.ValidateGenesis(genState); err != nil { + panic(fmt.Errorf("panic for ValidateGenesis,%v", err)) + } + k.SetParams(ctx, genState.Params) + k.SetStandardDenom(ctx, genState.StandardDenom) + k.setSequence(ctx, genState.Sequence) + for _, pool := range genState.Pool { + k.setPool(ctx, &pool) + } +} + +// ExportGenesis returns the coinswap module's genesis state. +func (k Keeper) ExportGenesis(ctx sdk.Context) types.GenesisState { + return types.GenesisState{ + Params: k.GetParams(ctx), + StandardDenom: k.GetStandardDenom(ctx), + Pool: k.GetAllPools(ctx), + Sequence: k.getSequence(ctx), + } +} diff --git a/modules/coinswap/keeper/genesis_test.go b/modules/coinswap/keeper/genesis_test.go new file mode 100644 index 00000000..f90b772d --- /dev/null +++ b/modules/coinswap/keeper/genesis_test.go @@ -0,0 +1,34 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/irisnet/irismod/modules/coinswap/types" + "github.com/stretchr/testify/suite" +) + +func TestGenesisSuite(t *testing.T) { + suite.Run(t, new(TestSuite)) +} + +func (suite *TestSuite) TestInitGenesisAndExportGenesis() { + expGenesis := types.GenesisState{ + Params: types.Params{ + Fee: sdk.NewDecWithPrec(4, 3), + }, + StandardDenom: denomStandard, + Pool: []types.Pool{{ + Id: types.GetPoolId(denomETH), + StandardDenom: denomStandard, + CounterpartyDenom: denomETH, + EscrowAddress: types.GetReservePoolAddr("lpt-1").String(), + LptDenom: "lpt-1", + }}, + Sequence: 2, + } + suite.app.CoinswapKeeper.InitGenesis(suite.ctx, expGenesis) + actGenesis := suite.app.CoinswapKeeper.ExportGenesis(suite.ctx) + suite.Require().Equal(expGenesis, actGenesis) +} diff --git a/modules/coinswap/keeper/grpc_query.go b/modules/coinswap/keeper/grpc_query.go index 96fae706..f4bcf483 100644 --- a/modules/coinswap/keeper/grpc_query.go +++ b/modules/coinswap/keeper/grpc_query.go @@ -21,8 +21,7 @@ func (k Keeper) Liquidity(c context.Context, req *types.QueryLiquidityRequest) ( } ctx := sdk.UnwrapSDKContext(c) - poolId := types.GetPoolId(req.Denom) - pool, exists := k.GetPool(ctx, poolId) + pool, exists := k.GetPoolByLptDenom(ctx, req.Denom) if !exists { return nil, sdkerrors.Wrapf(types.ErrReservePoolNotExists, "liquidity pool token: %s", req.Denom) } diff --git a/modules/coinswap/keeper/pool.go b/modules/coinswap/keeper/pool.go index 5eaf39d1..5dda8a30 100644 --- a/modules/coinswap/keeper/pool.go +++ b/modules/coinswap/keeper/pool.go @@ -11,7 +11,7 @@ import ( // CreatePool create a liquidity that saves relevant information about popular pool tokens func (k Keeper) CreatePool(ctx sdk.Context, counterpartyDenom string) types.Pool { - sequence := k.getPoolSequence(ctx) + sequence := k.getSequence(ctx) lptDenom := types.GetLptDenom(sequence) pool := &types.Pool{ Id: types.GetPoolId(counterpartyDenom), @@ -20,7 +20,7 @@ func (k Keeper) CreatePool(ctx sdk.Context, counterpartyDenom string) types.Pool EscrowAddress: types.GetReservePoolAddr(lptDenom).String(), LptDenom: lptDenom, } - k.increasePoolSequence(ctx, sequence) + k.setSequence(ctx, sequence+1) k.setPool(ctx, pool) return *pool } @@ -38,6 +38,19 @@ func (k Keeper) GetPool(ctx sdk.Context, poolId string) (types.Pool, bool) { return *pool, true } +// GetAllPools return all the liquidity pools +func (k Keeper) GetAllPools(ctx sdk.Context) (pools []types.Pool) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte(types.KeyPool)) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var pool types.Pool + k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &pool) + pools = append(pools, pool) + } + return +} + // GetPoolByLptDenom return the liquidity pool by the specified anotherCoinDenom func (k Keeper) GetPoolByLptDenom(ctx sdk.Context, lptDenom string) (types.Pool, bool) { store := ctx.KVStore(k.storeKey) @@ -125,8 +138,8 @@ func (k Keeper) setPool(ctx sdk.Context, pool *types.Pool) { store.Set(types.GetLptDenomKey(pool.LptDenom), poolIdBz) } -// getPoolSequence gets the next pool sequence from the store. -func (k Keeper) getPoolSequence(ctx sdk.Context) uint64 { +// getSequence gets the next pool sequence from the store. +func (k Keeper) getSequence(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) bz := store.Get([]byte(types.KeyNextPoolSequence)) if bz == nil { @@ -135,9 +148,9 @@ func (k Keeper) getPoolSequence(ctx sdk.Context) uint64 { return sdk.BigEndianToUint64(bz) } -// increasePoolSequence sets the next pool sequence to the store. -func (k Keeper) increasePoolSequence(ctx sdk.Context, sequence uint64) { +// setSequence sets the next pool sequence to the store. +func (k Keeper) setSequence(ctx sdk.Context, sequence uint64) { store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence + 1) + bz := sdk.Uint64ToBigEndian(sequence) store.Set([]byte(types.KeyNextPoolSequence), bz) } diff --git a/modules/coinswap/keeper/querier.go b/modules/coinswap/keeper/querier.go index b5e526cb..56616c7a 100644 --- a/modules/coinswap/keeper/querier.go +++ b/modules/coinswap/keeper/querier.go @@ -31,8 +31,7 @@ func queryLiquidity(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuer return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - poolId := types.GetPoolId(params.Denom) - pool, exists := k.GetPool(ctx, poolId) + pool, exists := k.GetPoolByLptDenom(ctx, params.Denom) if !exists { return nil, sdkerrors.Wrapf(types.ErrReservePoolNotExists, "liquidity pool token: %s", params.Denom) } diff --git a/modules/coinswap/keeper/querier_test.go b/modules/coinswap/keeper/querier_test.go index a740497a..b19a6577 100644 --- a/modules/coinswap/keeper/querier_test.go +++ b/modules/coinswap/keeper/querier_test.go @@ -41,7 +41,7 @@ func (suite *TestSuite) TestNewQuerier() { // test queryLiquidity - bz, errRes := legacyAmino.MarshalJSON(types.QueryLiquidityParams{Denom: denomBTC}) + bz, errRes := legacyAmino.MarshalJSON(types.QueryLiquidityParams{Denom: lptCoin.Denom}) suite.NoError(errRes) req.Path = fmt.Sprintf("custom/%s/%s", types.QuerierRoute, types.QueryLiquidity) diff --git a/modules/coinswap/module.go b/modules/coinswap/module.go index 815eba01..43a52b9a 100644 --- a/modules/coinswap/module.go +++ b/modules/coinswap/module.go @@ -134,17 +134,15 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd // no validator updates. func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { var genesisState types.GenesisState - cdc.MustUnmarshalJSON(data, &genesisState) - - InitGenesis(ctx, am.keeper, genesisState) + am.keeper.InitGenesis(ctx, genesisState) return []abci.ValidatorUpdate{} } // ExportGenesis returns the exported genesis state as raw bytes for the coinswap module. func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { - gs := ExportGenesis(ctx, am.keeper) - return cdc.MustMarshalJSON(gs) + gs := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(&gs) } // BeginBlock performs a no-op. diff --git a/modules/coinswap/types/genesis.go b/modules/coinswap/types/genesis.go index 8ec808fc..ea444cb0 100644 --- a/modules/coinswap/types/genesis.go +++ b/modules/coinswap/types/genesis.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -14,7 +16,11 @@ func NewGenesisState(params Params, denom string) *GenesisState { // DefaultGenesisState creates a default GenesisState object func DefaultGenesisState() *GenesisState { - return NewGenesisState(DefaultParams(), sdk.DefaultBondDenom) + return &GenesisState{ + Params: DefaultParams(), + StandardDenom: sdk.DefaultBondDenom, + Sequence: 1, + } } // ValidateGenesis validates the given genesis state @@ -22,5 +28,47 @@ func ValidateGenesis(data GenesisState) error { if err := sdk.ValidateDenom(data.StandardDenom); err != nil { return err } + + var poolIds = make(map[string]bool, len(data.Pool)) + var lptDenoms = make(map[string]bool, len(data.Pool)) + var maxSequence = uint64(0) + for _, pool := range data.Pool { + if poolIds[pool.Id] { + return fmt.Errorf("duplicate pool: %s", pool.Id) + } + if lptDenoms[pool.LptDenom] { + return fmt.Errorf("duplicate lptDenom: %s", pool.LptDenom) + } + poolIds[pool.Id] = true + lptDenoms[pool.LptDenom] = true + + //validate the liquidity pool token denom + seq, err := ParseLptDenom(pool.LptDenom) + if err != nil { + return err + } + + if seq > maxSequence { + maxSequence = seq + } + + //validate the token denom + if err := sdk.ValidateDenom(pool.CounterpartyDenom); err != nil { + return err + } + + //validate the token denom + if err := sdk.ValidateDenom(pool.StandardDenom); err != nil { + return err + } + + //validate the address + if _, err := sdk.AccAddressFromBech32(pool.EscrowAddress); err != nil { + return err + } + } + if maxSequence+1 != data.Sequence { + return fmt.Errorf("invalid sequence: %d", data.Sequence) + } return data.Params.Validate() } diff --git a/modules/coinswap/types/genesis.pb.go b/modules/coinswap/types/genesis.pb.go index 13e1e729..b5e7f26f 100644 --- a/modules/coinswap/types/genesis.pb.go +++ b/modules/coinswap/types/genesis.pb.go @@ -27,6 +27,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GenesisState struct { Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` StandardDenom string `protobuf:"bytes,2,opt,name=standard_denom,json=standardDenom,proto3" json:"standard_denom,omitempty" yaml:"standard_denom"` + Pool []Pool `protobuf:"bytes,3,rep,name=pool,proto3" json:"pool"` + Sequence uint64 `protobuf:"varint,4,opt,name=sequence,proto3" json:"sequence,omitempty"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -76,6 +78,20 @@ func (m *GenesisState) GetStandardDenom() string { return "" } +func (m *GenesisState) GetPool() []Pool { + if m != nil { + return m.Pool + } + return nil +} + +func (m *GenesisState) GetSequence() uint64 { + if m != nil { + return m.Sequence + } + return 0 +} + func init() { proto.RegisterType((*GenesisState)(nil), "irismod.coinswap.GenesisState") } @@ -83,23 +99,26 @@ func init() { func init() { proto.RegisterFile("coinswap/genesis.proto", fileDescriptor_2ec819868131a4f8) } var fileDescriptor_2ec819868131a4f8 = []byte{ - // 244 bytes of a gzipped FileDescriptorProto + // 290 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0xce, 0xcf, 0xcc, 0x2b, 0x2e, 0x4f, 0x2c, 0xd0, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc8, 0x2c, 0xca, 0x2c, 0xce, 0xcd, 0x4f, 0xd1, 0x83, 0xc9, 0x4b, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf5, 0x41, 0x2c, 0x88, 0x3a, 0x29, 0x71, 0xb8, 0x7e, 0x18, - 0x03, 0x22, 0xa1, 0xd4, 0xc1, 0xc8, 0xc5, 0xe3, 0x0e, 0x31, 0x32, 0xb8, 0x24, 0xb1, 0x24, 0x55, - 0xc8, 0x8c, 0x8b, 0xad, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, - 0x48, 0x42, 0x0f, 0xdd, 0x0a, 0xbd, 0x00, 0xb0, 0xbc, 0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, - 0x50, 0xd5, 0x42, 0x0e, 0x5c, 0x7c, 0xc5, 0x25, 0x89, 0x79, 0x29, 0x89, 0x45, 0x29, 0xf1, 0x29, - 0xa9, 0x79, 0xf9, 0xb9, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x9c, 0x4e, 0x92, 0x9f, 0xee, 0xc9, 0x8b, - 0x56, 0x26, 0xe6, 0xe6, 0x58, 0x29, 0xa1, 0xca, 0x2b, 0x05, 0xf1, 0xc2, 0x04, 0x5c, 0x40, 0x7c, - 0x27, 0xef, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, - 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4c, 0xcf, 0x2c, - 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x07, 0xb9, 0x26, 0x2f, 0xb5, 0x44, 0x1f, 0xea, - 0x2a, 0xfd, 0xdc, 0xfc, 0x94, 0xd2, 0x9c, 0xd4, 0x62, 0xb8, 0xbf, 0xf4, 0x4b, 0x2a, 0x0b, 0x52, - 0x8b, 0x93, 0xd8, 0xc0, 0xde, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x31, 0xf3, 0xa5, - 0x39, 0x01, 0x00, 0x00, + 0x03, 0x22, 0xa1, 0x74, 0x8d, 0x91, 0x8b, 0xc7, 0x1d, 0x62, 0x64, 0x70, 0x49, 0x62, 0x49, 0xaa, + 0x90, 0x19, 0x17, 0x5b, 0x41, 0x62, 0x51, 0x62, 0x6e, 0xb1, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, + 0x91, 0x84, 0x1e, 0xba, 0x15, 0x7a, 0x01, 0x60, 0x79, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, + 0xa0, 0xaa, 0x85, 0x1c, 0xb8, 0xf8, 0x8a, 0x4b, 0x12, 0xf3, 0x52, 0x12, 0x8b, 0x52, 0xe2, 0x53, + 0x52, 0xf3, 0xf2, 0x73, 0x25, 0x98, 0x14, 0x18, 0x35, 0x38, 0x9d, 0x24, 0x3f, 0xdd, 0x93, 0x17, + 0xad, 0x4c, 0xcc, 0xcd, 0xb1, 0x52, 0x42, 0x95, 0x57, 0x0a, 0xe2, 0x85, 0x09, 0xb8, 0x80, 0xf8, + 0x42, 0x06, 0x5c, 0x2c, 0x05, 0xf9, 0xf9, 0x39, 0x12, 0xcc, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x62, + 0x58, 0xec, 0xcd, 0xcf, 0xcf, 0x81, 0xda, 0x0a, 0x56, 0x29, 0x24, 0xc5, 0xc5, 0x51, 0x9c, 0x5a, + 0x58, 0x9a, 0x9a, 0x97, 0x9c, 0x2a, 0xc1, 0xa2, 0xc0, 0xa8, 0xc1, 0x12, 0x04, 0xe7, 0x3b, 0x79, + 0x9f, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, + 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x61, 0x7a, 0x66, 0x49, 0x46, + 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x3e, 0xc8, 0x8e, 0xbc, 0xd4, 0x12, 0x7d, 0xa8, 0x5d, 0xfa, + 0xb9, 0xf9, 0x29, 0xa5, 0x39, 0xa9, 0xc5, 0xf0, 0x50, 0xd2, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, + 0x62, 0x03, 0x07, 0x96, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xf3, 0x27, 0xcd, 0x87, 0x01, + 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -122,6 +141,25 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Sequence != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Sequence)) + i-- + dAtA[i] = 0x20 + } + if len(m.Pool) > 0 { + for iNdEx := len(m.Pool) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Pool[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } if len(m.StandardDenom) > 0 { i -= len(m.StandardDenom) copy(dAtA[i:], m.StandardDenom) @@ -165,6 +203,15 @@ func (m *GenesisState) Size() (n int) { if l > 0 { n += 1 + l + sovGenesis(uint64(l)) } + if len(m.Pool) > 0 { + for _, e := range m.Pool { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.Sequence != 0 { + n += 1 + sovGenesis(uint64(m.Sequence)) + } return n } @@ -268,16 +315,66 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { } m.StandardDenom = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pool", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pool = append(m.Pool, Pool{}) + if err := m.Pool[len(m.Pool)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) + } + m.Sequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthGenesis } if (iNdEx + skippy) > l { diff --git a/modules/coinswap/types/utils.go b/modules/coinswap/types/utils.go index a7d7e322..2a315f19 100644 --- a/modules/coinswap/types/utils.go +++ b/modules/coinswap/types/utils.go @@ -2,6 +2,8 @@ package types import ( "fmt" + "strconv" + "strings" "github.com/tendermint/tendermint/crypto" @@ -27,3 +29,11 @@ func GetPoolId(counterpartyDenom string) string { func GetLptDenom(sequence uint64) string { return fmt.Sprintf(LptTokenFormat, sequence) } + +func ParseLptDenom(lptDenom string) (uint64, error) { + result := strings.Split(lptDenom, "-") + if len(result) != 2 { + return 0, fmt.Errorf("invalid lpt denom: %s", lptDenom) + } + return strconv.ParseUint(result[1], 10, 64) +} diff --git a/modules/coinswap/types/validation.go b/modules/coinswap/types/validation.go index 45a7a3d3..2e604af4 100644 --- a/modules/coinswap/types/validation.go +++ b/modules/coinswap/types/validation.go @@ -106,7 +106,7 @@ func ValidateMinStandardAmt(minStandardAmt sdk.Int) error { // ValidateLptDenom returns nil if the Liquidity pool token denom is valid func ValidateLptDenom(lptDenom string) error { - if !strings.HasPrefix(lptDenom, LptTokenPrefix) { + if _, err := ParseLptDenom(lptDenom); err != nil { return sdkerrors.Wrap(ErrInvalidDenom, lptDenom) } return nil diff --git a/modules/token/types/validation.go b/modules/token/types/validation.go index c9ef0deb..cd41a63b 100644 --- a/modules/token/types/validation.go +++ b/modules/token/types/validation.go @@ -32,12 +32,12 @@ const ( const ( ReservedPeg = "peg" ReservedIBC = "ibc" - ReservedSwap = "swap" + ReservedLpt = "lpt" ReservedHTLT = "htlt" ) var ( - keywords = strings.Join([]string{ReservedPeg, ReservedIBC, ReservedSwap, ReservedHTLT}, "|") + keywords = strings.Join([]string{ReservedPeg, ReservedIBC, ReservedLpt, ReservedHTLT}, "|") regexpKeywordsFmt = fmt.Sprintf("^(%s).*", keywords) regexpKeyword = regexp.MustCompile(regexpKeywordsFmt).MatchString diff --git a/modules/token/types/validation_test.go b/modules/token/types/validation_test.go index ff002ca3..3736ce0b 100644 --- a/modules/token/types/validation_test.go +++ b/modules/token/types/validation_test.go @@ -72,9 +72,9 @@ func TestValidateKeywords(t *testing.T) { {name: "denom is ibc", args: args{denom: "ibc"}, wantErr: true}, {name: "denom is IBC", args: args{denom: "Peg"}, wantErr: false}, {name: "denom begin with ibc", args: args{denom: "ibctoken"}, wantErr: true}, - {name: "denom is swap", args: args{denom: "swap"}, wantErr: true}, + {name: "denom is lpt", args: args{denom: "lpt"}, wantErr: true}, {name: "denom is SWAP", args: args{denom: "SWAP"}, wantErr: false}, - {name: "denom begin with swap", args: args{denom: "swaptoken"}, wantErr: true}, + {name: "denom begin with lpt", args: args{denom: "lpttoken"}, wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/proto/coinswap/genesis.proto b/proto/coinswap/genesis.proto index 3fae991a..90608bf1 100644 --- a/proto/coinswap/genesis.proto +++ b/proto/coinswap/genesis.proto @@ -8,7 +8,9 @@ option go_package = "github.com/irisnet/irismod/modules/coinswap/types"; // GenesisState defines the coinswap module's genesis state message GenesisState { - Params params = 1 [ (gogoproto.nullable) = false ]; - string standard_denom = 2 - [ (gogoproto.moretags) = "yaml:\"standard_denom\"" ]; + Params params = 1 [ (gogoproto.nullable) = false ]; + string standard_denom = 2 + [ (gogoproto.moretags) = "yaml:\"standard_denom\"" ]; + repeated irismod.coinswap.Pool pool = 3 [ (gogoproto.nullable) = false ]; + uint64 sequence = 4; }