From 2fddce87de8768538f217edecce66275f45ce8e3 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Mon, 29 Jul 2024 14:37:10 +0900 Subject: [PATCH 1/7] fix: wrong denom check at RegisterCoin Check registered denom using `coinMetadata.Base` not `.Name` details: https://github.com/b-harvest/Canto/commit/d01eab04b98217290ec49f5277bb0acede1479ec --- x/erc20/keeper/proposals.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/erc20/keeper/proposals.go b/x/erc20/keeper/proposals.go index d072b1bc..b34162ef 100644 --- a/x/erc20/keeper/proposals.go +++ b/x/erc20/keeper/proposals.go @@ -33,7 +33,7 @@ func (k Keeper) RegisterCoin( } // Check if denomination is already registered - if k.IsDenomRegistered(ctx, coinMetadata.Name) { + if k.IsDenomRegistered(ctx, coinMetadata.Base) { return nil, sdkerrors.Wrapf( types.ErrTokenPairAlreadyExists, "coin denomination already registered: %s", coinMetadata.Name, ) From ea61c8960aa763828e73cf6074cb62d603463ee7 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Mon, 29 Jul 2024 14:52:03 +0900 Subject: [PATCH 2/7] refactor: remove ibc-related tests --- x/erc20/keeper/msg_server_test.go | 351 ------------------------------ x/erc20/keeper/proposals_test.go | 33 --- 2 files changed, 384 deletions(-) diff --git a/x/erc20/keeper/msg_server_test.go b/x/erc20/keeper/msg_server_test.go index a5c1ede1..5c9f268b 100644 --- a/x/erc20/keeper/msg_server_test.go +++ b/x/erc20/keeper/msg_server_test.go @@ -964,354 +964,3 @@ func (suite *KeeperTestSuite) TestWrongPairOwnerERC20NativeCoin() { }) } } - -func (suite *KeeperTestSuite) TestConvertCoinNativeIBCVoucher() { - testCases := []struct { - name string - mint int64 - burn int64 - malleate func(common.Address) - extra func() - expPass bool - selfdestructed bool - }{ - { - "ok - sufficient funds", - 100, - 10, - func(common.Address) {}, - func() {}, - true, - false, - }, - { - "ok - equal funds", - 10, - 10, - func(common.Address) {}, - func() {}, - true, - false, - }, - { - "ok - suicided contract", - 10, - 10, - func(erc20 common.Address) { - stateDb := suite.StateDB() - ok := stateDb.Suicide(erc20) - suite.Require().True(ok) - suite.Require().NoError(stateDb.Commit()) - }, - func() {}, - true, - true, - }, - { - "fail - insufficient funds", - 0, - 10, - func(common.Address) {}, - func() {}, - false, - false, - }, - { - "fail - minting disabled", - 100, - 10, - func(common.Address) { - params := types.DefaultParams() - params.EnableErc20 = false - suite.app.Erc20Keeper.SetParams(suite.ctx, params) - }, - func() {}, - false, - false, - }, - { - "fail - deleted module account - force fail", 100, 10, func(common.Address) {}, - func() { - acc := suite.app.AccountKeeper.GetAccount(suite.ctx, types.ModuleAddress.Bytes()) - suite.app.AccountKeeper.RemoveAccount(suite.ctx, acc) - }, false, false, - }, - { - "fail - force evm fail", 100, 10, func(common.Address) {}, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, false, false, - }, - { - "fail - force evm balance error", 100, 10, func(common.Address) {}, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - // first balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - // convert coin - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil).Once() - // second balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, fmt.Errorf("third")).Once() - // Extra call on test - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, false, false, - }, - { - "fail - force balance error", 100, 10, func(common.Address) {}, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Times(4) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, false, false, - }, - } - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.mintFeeCollector = true - suite.SetupTest() - metadata, pair := suite.setupRegisterIBCVoucher() - suite.Require().NotNil(metadata) - erc20 := pair.GetERC20Contract() - tc.malleate(erc20) - suite.Commit() - - ctx := sdk.WrapSDKContext(suite.ctx) - coins := sdk.NewCoins(sdk.NewCoin(ibcBase, sdk.NewInt(tc.mint))) - sender := sdk.AccAddress(suite.address.Bytes()) - msg := types.NewMsgConvertCoin( - sdk.NewCoin(ibcBase, sdk.NewInt(tc.burn)), - suite.address, - sender, - ) - - suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, coins) - suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, sender, coins) - - tc.extra() - res, err := suite.app.Erc20Keeper.ConvertCoin(ctx, msg) - expRes := &types.MsgConvertCoinResponse{} - suite.Commit() - balance := suite.BalanceOf(common.HexToAddress(pair.Erc20Address), suite.address) - cosmosBalance := suite.app.BankKeeper.GetBalance(suite.ctx, sender, metadata.Base) - - if tc.expPass { - suite.Require().NoError(err, tc.name) - - acc := suite.app.EvmKeeper.GetAccountWithoutBalance(suite.ctx, erc20) - if tc.selfdestructed { - suite.Require().Nil(acc, "expected contract to be destroyed") - } else { - suite.Require().NotNil(acc) - } - - if tc.selfdestructed || !acc.IsContract() { - id := suite.app.Erc20Keeper.GetTokenPairID(suite.ctx, erc20.String()) - _, found := suite.app.Erc20Keeper.GetTokenPair(suite.ctx, id) - suite.Require().False(found) - } else { - suite.Require().Equal(expRes, res) - suite.Require().Equal(cosmosBalance.Amount.Int64(), sdk.NewInt(tc.mint-tc.burn).Int64()) - suite.Require().Equal(balance.(*big.Int).Int64(), big.NewInt(tc.burn).Int64()) - } - } else { - suite.Require().Error(err, tc.name) - } - }) - } - suite.mintFeeCollector = false -} - -func (suite *KeeperTestSuite) TestConvertERC20NativeIBCVoucher() { - testCases := []struct { - name string - mint int64 - burn int64 - reconvert int64 - malleate func() - expPass bool - }{ - {"ok - sufficient funds", 100, 10, 5, func() {}, true}, - {"ok - equal funds", 10, 10, 10, func() {}, true}, - {"fail - insufficient funds", 10, 1, 5, func() {}, false}, - {"fail ", 10, 1, -5, func() {}, false}, - { - "fail - deleted module account - force fail", 100, 10, 5, - func() { - acc := suite.app.AccountKeeper.GetAccount(suite.ctx, types.ModuleAddress.Bytes()) - suite.app.AccountKeeper.RemoveAccount(suite.ctx, acc) - }, - false, - }, - { - "fail - force evm fail", 100, 10, 5, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("forced ApplyMessage error")) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, - false, - }, - { - "fail - force fail second balance", 100, 10, 5, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - // first balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - // convert coin - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil).Once() - // second balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, fmt.Errorf("third")).Once() - // Extra call on test - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, - false, - }, - { - "fail - force fail second balance", 100, 10, 5, - func() { - mockEVMKeeper := &MockEVMKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, suite.app.BankKeeper, mockEVMKeeper) - - existingAcc := &statedb.Account{Nonce: uint64(1), Balance: common.Big1} - balance := make([]uint8, 32) - mockEVMKeeper.On("EstimateGas", mock.Anything, mock.Anything).Return(&evmtypes.EstimateGasResponse{Gas: uint64(200)}, nil) - // first balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - // convert coin - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil).Once() - // second balance of - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{Ret: balance}, nil).Once() - // Extra call on test - mockEVMKeeper.On("ApplyMessage", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&evmtypes.MsgEthereumTxResponse{}, nil) - mockEVMKeeper.On("GetAccountWithoutBalance", mock.Anything, mock.Anything).Return(existingAcc, nil) - }, - false, - }, - { - "fail - force fail unescrow", 100, 10, 5, - func() { - mockBankKeeper := &MockBankKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, mockBankKeeper, suite.app.EvmKeeper) - - mockBankKeeper.On("SendCoinsFromModuleToAccount", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("failed to unescrow")) - mockBankKeeper.On("BlockedAddr", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(false) - mockBankKeeper.On("GetBalance", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(sdk.Coin{Denom: "coin", Amount: sdk.OneInt()}) - }, - false, - }, - { - "fail - force fail balance after transfer", 100, 10, 5, - func() { - mockBankKeeper := &MockBankKeeper{} - sp, found := suite.app.ParamsKeeper.GetSubspace(types.ModuleName) - suite.Require().True(found) - suite.app.Erc20Keeper = keeper.NewKeeper(suite.app.GetKey("erc20"), suite.app.AppCodec(), sp, suite.app.AccountKeeper, mockBankKeeper, suite.app.EvmKeeper) - - mockBankKeeper.On("SendCoinsFromModuleToAccount", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) - mockBankKeeper.On("BlockedAddr", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(false) - mockBankKeeper.On("GetBalance", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(sdk.Coin{Denom: ibcBase, Amount: sdk.OneInt()}) - }, - false, - }, - } - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.mintFeeCollector = true - suite.SetupTest() - metadata, pair := suite.setupRegisterIBCVoucher() - suite.Require().NotNil(metadata) - suite.Require().NotNil(pair) - - // Precondition: Convert Coin to ERC20 - coins := sdk.NewCoins(sdk.NewCoin(ibcBase, sdk.NewInt(tc.mint))) - sender := sdk.AccAddress(suite.address.Bytes()) - suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, coins) - suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, sender, coins) - msg := types.NewMsgConvertCoin( - sdk.NewCoin(ibcBase, sdk.NewInt(tc.burn)), - suite.address, - sender, - ) - - ctx := sdk.WrapSDKContext(suite.ctx) - _, err := suite.app.Erc20Keeper.ConvertCoin(ctx, msg) - suite.Require().NoError(err, tc.name) - suite.Commit() - balance := suite.BalanceOf(common.HexToAddress(pair.Erc20Address), suite.address) - cosmosBalance := suite.app.BankKeeper.GetBalance(suite.ctx, sender, metadata.Base) - suite.Require().Equal(cosmosBalance.Amount.Int64(), sdk.NewInt(tc.mint-tc.burn).Int64()) - suite.Require().Equal(balance, big.NewInt(tc.burn)) - - // Convert ERC20s back to Coins - ctx = sdk.WrapSDKContext(suite.ctx) - contractAddr := common.HexToAddress(pair.Erc20Address) - msgConvertERC20 := types.NewMsgConvertERC20( - sdk.NewInt(tc.reconvert), - sender, - contractAddr, - suite.address, - ) - - tc.malleate() - res, err := suite.app.Erc20Keeper.ConvertERC20(ctx, msgConvertERC20) - expRes := &types.MsgConvertERC20Response{} - suite.Commit() - balance = suite.BalanceOf(contractAddr, suite.address) - cosmosBalance = suite.app.BankKeeper.GetBalance(suite.ctx, sender, pair.Denom) - if tc.expPass { - suite.Require().NoError(err, tc.name) - suite.Require().Equal(expRes, res) - suite.Require().Equal(cosmosBalance.Amount.Int64(), sdk.NewInt(tc.mint-tc.burn+tc.reconvert).Int64()) - suite.Require().Equal(balance.(*big.Int).Int64(), big.NewInt(tc.burn-tc.reconvert).Int64()) - } else { - suite.Require().Error(err, tc.name) - } - }) - } - suite.mintFeeCollector = false -} diff --git a/x/erc20/keeper/proposals_test.go b/x/erc20/keeper/proposals_test.go index 35171eae..d64d8d3f 100644 --- a/x/erc20/keeper/proposals_test.go +++ b/x/erc20/keeper/proposals_test.go @@ -32,7 +32,6 @@ const ( cosmosDecimals = uint8(6) defaultExponent = uint32(18) zeroExponent = uint32(0) - ibcBase = "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2" ) func (suite *KeeperTestSuite) setupRegisterERC20Pair(contractType int) common.Address { @@ -83,34 +82,6 @@ func (suite *KeeperTestSuite) setupRegisterCoin() (banktypes.Metadata, *types.To return validMetadata, pair } -func (suite *KeeperTestSuite) setupRegisterIBCVoucher() (banktypes.Metadata, *types.TokenPair) { - suite.SetupTest() - - validMetadata := banktypes.Metadata{ - Description: "ATOM IBC voucher (channel 14)", - Base: ibcBase, - // NOTE: Denom units MUST be increasing - DenomUnits: []*banktypes.DenomUnit{ - { - Denom: ibcBase, - Exponent: 0, - }, - }, - Name: "ATOM channel-14", - Symbol: "ibcATOM-14", - Display: ibcBase, - } - - err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) - suite.Require().NoError(err) - - // pair := types.NewTokenPair(contractAddr, cosmosTokenBase, true, types.OWNER_MODULE) - pair, err := suite.app.Erc20Keeper.RegisterCoin(suite.ctx, validMetadata) - suite.Require().NoError(err) - suite.Commit() - return validMetadata, pair -} - func (suite KeeperTestSuite) TestRegisterCoin() { metadata := banktypes.Metadata{ Description: "description", @@ -384,10 +355,6 @@ func (suite KeeperTestSuite) TestRegisterERC20() { } } -func (suite *KeeperTestSuite) TestRegisterIBCVoucher() { - suite.setupRegisterIBCVoucher() -} - func (suite KeeperTestSuite) TestToggleConverision() { var ( contractAddr common.Address From ba501785e43322e41e3d5cfa39951908d93bff19 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Mon, 29 Jul 2024 14:57:06 +0900 Subject: [PATCH 3/7] chore: add registered denom test and refactoring --- x/erc20/keeper/proposals_test.go | 65 ++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/x/erc20/keeper/proposals_test.go b/x/erc20/keeper/proposals_test.go index d64d8d3f..478378aa 100644 --- a/x/erc20/keeper/proposals_test.go +++ b/x/erc20/keeper/proposals_test.go @@ -108,7 +108,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { expPass bool }{ { - "conversion is disabled globally", + "fail: conversion is disabled globally", func() { params := types.DefaultParams() params.EnableErc20 = false @@ -117,7 +117,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "denom already registered", + "fail: denom already registered", func() { regPair := types.NewTokenPair(tests.GenerateAddress(), metadata.Base, true, types.OWNER_MODULE) suite.app.Erc20Keeper.SetDenomMap(suite.ctx, regPair.Denom, regPair.GetID()) @@ -126,33 +126,17 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "token doesn't have supply", + "fail: token doesn't have supply", func() { }, false, }, { - "metadata different that stored", + "fail: metadata different that stored", func() { metadata.Base = cosmosTokenBase - validMetadata := banktypes.Metadata{ - Description: "description", - Base: cosmosTokenBase, - // NOTE: Denom units MUST be increasing - DenomUnits: []*banktypes.DenomUnit{ - { - Denom: cosmosTokenBase, - Exponent: 0, - }, - { - Denom: cosmosTokenDisplay, - Exponent: uint32(18), - }, - }, - Name: erc20Name, - Symbol: erc20Symbol, - Display: cosmosTokenDisplay, - } + validMetadata := metadata + validMetadata.Name = "different" err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(validMetadata.Base, 1)}) suite.Require().NoError(err) @@ -161,7 +145,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "evm denom registration - CANTO", + "fail: evm denom registration - CANTO", func() { metadata.Base = "CANTO" err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -170,7 +154,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "evm denom registration - CANTO", + "fail: evm denom registration - CANTO", func() { metadata.Base = "CANTO" err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -179,7 +163,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "evm denom registration - aCANTO", + "fail: evm denom registration - aCANTO", func() { metadata.Base = "aCANTO" err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -188,7 +172,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "evm denom registration - wCANTO", + "fail: evm denom registration - wCANTO", func() { metadata.Base = "wCANTO" err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -206,7 +190,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { true, }, { - "force fail evm", + "fail: force fail evm", func() { metadata.Base = cosmosTokenBase err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -222,7 +206,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { false, }, { - "force delete module account evm", + "fail: force delete module account evm", func() { metadata.Base = cosmosTokenBase err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) @@ -233,6 +217,29 @@ func (suite KeeperTestSuite) TestRegisterCoin() { }, false, }, + { + "fail: token pair already exists with same denom", + func() { + metadata.Base = cosmosTokenBase + err := suite.app.BankKeeper.MintCoins(suite.ctx, inflationtypes.ModuleName, sdk.Coins{sdk.NewInt64Coin(metadata.Base, 1)}) + suite.Require().NoError(err) + + tokenPair, err := suite.app.Erc20Keeper.RegisterCoin(suite.ctx, metadata) + suite.Require().NoError(err) + suite.Commit() + + // check token pair is stored + suite.Require().Equal(types.OWNER_MODULE, tokenPair.ContractOwner) + suite.Require().Equal(metadata.Base, tokenPair.Denom) + suite.Require().Equal(true, tokenPair.Enabled) + + // check denom erc20 are stored + id := tokenPair.GetID() + suite.Require().Equal(id, suite.app.Erc20Keeper.GetDenomMap(suite.ctx, tokenPair.Denom)) + suite.Require().Equal(id, suite.app.Erc20Keeper.GetERC20Map(suite.ctx, common.HexToAddress(tokenPair.Erc20Address))) + }, + false, + }, } for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.name), func() { @@ -247,7 +254,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { Erc20Address: "0x80b5a32E4F032B2a058b4F29EC95EEfEEB87aDcd", Denom: "acoin", Enabled: true, - ContractOwner: 1, + ContractOwner: types.OWNER_MODULE, } if tc.expPass { From e761795ca2a263ab063e40ffce4710a682d491e6 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Mon, 29 Jul 2024 18:37:48 +0900 Subject: [PATCH 4/7] chore: change func names better to reflect their purpose --- x/erc20/genesis.go | 4 ++-- x/erc20/keeper/evm_hooks.go | 2 +- x/erc20/keeper/evm_hooks_test.go | 4 ++-- x/erc20/keeper/grpc_query_test.go | 8 ++++---- x/erc20/keeper/mint_test.go | 20 +++++++++---------- x/erc20/keeper/proposals.go | 8 ++++---- x/erc20/keeper/proposals_test.go | 12 +++++------ x/erc20/keeper/token_pairs.go | 32 +++++++++++++++--------------- x/erc20/keeper/token_pairs_test.go | 12 +++++------ 9 files changed, 51 insertions(+), 51 deletions(-) diff --git a/x/erc20/genesis.go b/x/erc20/genesis.go index 785bb586..e97fd4c6 100644 --- a/x/erc20/genesis.go +++ b/x/erc20/genesis.go @@ -26,8 +26,8 @@ func InitGenesis( for _, pair := range data.TokenPairs { id := pair.GetID() k.SetTokenPair(ctx, pair) - k.SetDenomMap(ctx, pair.Denom, id) - k.SetERC20Map(ctx, pair.GetERC20Contract(), id) + k.SetTokenPairIdByDenom(ctx, pair.Denom, id) + k.SetTokenPairIdByERC20Addr(ctx, pair.GetERC20Contract(), id) } } diff --git a/x/erc20/keeper/evm_hooks.go b/x/erc20/keeper/evm_hooks.go index 47c08e63..365bf7ac 100644 --- a/x/erc20/keeper/evm_hooks.go +++ b/x/erc20/keeper/evm_hooks.go @@ -89,7 +89,7 @@ func (h Hooks) PostTxProcessing( // Check that the contract is a registered token pair contractAddr := log.Address - id := h.k.GetERC20Map(ctx, contractAddr) + id := h.k.GetTokenPairIdByERC20Addr(ctx, contractAddr) if len(id) == 0 { continue } diff --git a/x/erc20/keeper/evm_hooks_test.go b/x/erc20/keeper/evm_hooks_test.go index f721ab96..871bddba 100644 --- a/x/erc20/keeper/evm_hooks_test.go +++ b/x/erc20/keeper/evm_hooks_test.go @@ -92,8 +92,8 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisteredERC20() { suite.app.Erc20Keeper.DeleteTokenPair(suite.ctx, *pair) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, pair.GetERC20Contract(), pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, pair.GetERC20Contract(), pair.GetID()) // Mint 10 tokens to suite.address (owner) _ = suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(10)) suite.Commit() diff --git a/x/erc20/keeper/grpc_query_test.go b/x/erc20/keeper/grpc_query_test.go index 3043c3e4..c45b0c87 100644 --- a/x/erc20/keeper/grpc_query_test.go +++ b/x/erc20/keeper/grpc_query_test.go @@ -116,8 +116,8 @@ func (suite *KeeperTestSuite) TestTokenPair() { addr := tests.GenerateAddress() pair := types.NewTokenPair(addr, "coin", true, types.OWNER_MODULE) suite.app.Erc20Keeper.SetTokenPair(suite.ctx, pair) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, addr, pair.GetID()) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, addr, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) req = &types.QueryTokenPairRequest{ Token: pair.Erc20Address, @@ -131,8 +131,8 @@ func (suite *KeeperTestSuite) TestTokenPair() { func() { addr := tests.GenerateAddress() pair := types.NewTokenPair(addr, "coin", true, types.OWNER_MODULE) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, addr, pair.GetID()) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, addr, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) req = &types.QueryTokenPairRequest{ Token: pair.Erc20Address, diff --git a/x/erc20/keeper/mint_test.go b/x/erc20/keeper/mint_test.go index bc551efb..37b84e48 100644 --- a/x/erc20/keeper/mint_test.go +++ b/x/erc20/keeper/mint_test.go @@ -40,8 +40,8 @@ func (suite *KeeperTestSuite) TestMintingEnabled() { func() { expPair.Enabled = false suite.app.Erc20Keeper.SetTokenPair(suite.ctx, expPair) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, expPair.Denom, id) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, expPair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, expPair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, expPair.GetERC20Contract(), id) }, false, }, @@ -50,8 +50,8 @@ func (suite *KeeperTestSuite) TestMintingEnabled() { func() { expPair.Enabled = true suite.app.Erc20Keeper.SetTokenPair(suite.ctx, expPair) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, expPair.Denom, id) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, expPair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, expPair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, expPair.GetERC20Contract(), id) params := banktypes.DefaultParams() params.SendEnabled = []*banktypes.SendEnabled{ @@ -64,8 +64,8 @@ func (suite *KeeperTestSuite) TestMintingEnabled() { { "token not registered", func() { - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, expPair.Denom, id) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, expPair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, expPair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, expPair.GetERC20Contract(), id) }, false, }, @@ -73,8 +73,8 @@ func (suite *KeeperTestSuite) TestMintingEnabled() { "receiver address is blocked (module account)", func() { suite.app.Erc20Keeper.SetTokenPair(suite.ctx, expPair) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, expPair.Denom, id) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, expPair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, expPair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, expPair.GetERC20Contract(), id) acc := suite.app.AccountKeeper.GetModuleAccount(suite.ctx, types.ModuleName) receiver = acc.GetAddress() @@ -85,8 +85,8 @@ func (suite *KeeperTestSuite) TestMintingEnabled() { "ok", func() { suite.app.Erc20Keeper.SetTokenPair(suite.ctx, expPair) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, expPair.Denom, id) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, expPair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, expPair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, expPair.GetERC20Contract(), id) receiver = sdk.AccAddress(tests.GenerateAddress().Bytes()) }, diff --git a/x/erc20/keeper/proposals.go b/x/erc20/keeper/proposals.go index b34162ef..24e20f41 100644 --- a/x/erc20/keeper/proposals.go +++ b/x/erc20/keeper/proposals.go @@ -61,8 +61,8 @@ func (k Keeper) RegisterCoin( pair := types.NewTokenPair(addr, coinMetadata.Base, true, types.OWNER_MODULE) k.SetTokenPair(ctx, pair) - k.SetDenomMap(ctx, pair.Denom, pair.GetID()) - k.SetERC20Map(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) + k.SetTokenPairIdByDenom(ctx, pair.Denom, pair.GetID()) + k.SetTokenPairIdByERC20Addr(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) return &pair, nil } @@ -97,8 +97,8 @@ func (k Keeper) RegisterERC20( pair := types.NewTokenPair(contract, metadata.Name, true, types.OWNER_EXTERNAL) k.SetTokenPair(ctx, pair) - k.SetDenomMap(ctx, pair.Denom, pair.GetID()) - k.SetERC20Map(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) + k.SetTokenPairIdByDenom(ctx, pair.Denom, pair.GetID()) + k.SetTokenPairIdByERC20Addr(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) return &pair, nil } diff --git a/x/erc20/keeper/proposals_test.go b/x/erc20/keeper/proposals_test.go index 478378aa..a13904aa 100644 --- a/x/erc20/keeper/proposals_test.go +++ b/x/erc20/keeper/proposals_test.go @@ -120,7 +120,7 @@ func (suite KeeperTestSuite) TestRegisterCoin() { "fail: denom already registered", func() { regPair := types.NewTokenPair(tests.GenerateAddress(), metadata.Base, true, types.OWNER_MODULE) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, regPair.Denom, regPair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, regPair.Denom, regPair.GetID()) suite.Commit() }, false, @@ -235,8 +235,8 @@ func (suite KeeperTestSuite) TestRegisterCoin() { // check denom erc20 are stored id := tokenPair.GetID() - suite.Require().Equal(id, suite.app.Erc20Keeper.GetDenomMap(suite.ctx, tokenPair.Denom)) - suite.Require().Equal(id, suite.app.Erc20Keeper.GetERC20Map(suite.ctx, common.HexToAddress(tokenPair.Erc20Address))) + suite.Require().Equal(id, suite.app.Erc20Keeper.GetTokenPairIdByDenom(suite.ctx, tokenPair.Denom)) + suite.Require().Equal(id, suite.app.Erc20Keeper.GetTokenPairIdByERC20Addr(suite.ctx, common.HexToAddress(tokenPair.Erc20Address))) }, false, }, @@ -289,14 +289,14 @@ func (suite KeeperTestSuite) TestRegisterERC20() { { "token ERC20 already registered", func() { - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, pair.GetERC20Contract(), pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, pair.GetERC20Contract(), pair.GetID()) }, false, }, { "denom already registered", func() { - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) }, false, }, @@ -393,7 +393,7 @@ func (suite KeeperTestSuite) TestToggleConverision() { suite.Require().NoError(err) suite.Commit() pair = types.NewTokenPair(contractAddr, cosmosTokenBase, true, types.OWNER_MODULE) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) }, false, false, diff --git a/x/erc20/keeper/token_pairs.go b/x/erc20/keeper/token_pairs.go index 537db758..66601d63 100644 --- a/x/erc20/keeper/token_pairs.go +++ b/x/erc20/keeper/token_pairs.go @@ -30,9 +30,9 @@ func (k Keeper) GetTokenPairs(ctx sdk.Context) []types.TokenPair { func (k Keeper) GetTokenPairID(ctx sdk.Context, token string) []byte { if common.IsHexAddress(token) { addr := common.HexToAddress(token) - return k.GetERC20Map(ctx, addr) + return k.GetTokenPairIdByERC20Addr(ctx, addr) } - return k.GetDenomMap(ctx, token) + return k.GetTokenPairIdByDenom(ctx, token) } // GetTokenPair - get registered token pair from the identifier @@ -64,8 +64,8 @@ func (k Keeper) SetTokenPair(ctx sdk.Context, tokenPair types.TokenPair) { func (k Keeper) DeleteTokenPair(ctx sdk.Context, tokenPair types.TokenPair) { id := tokenPair.GetID() k.deleteTokenPair(ctx, id) - k.deleteERC20Map(ctx, tokenPair.GetERC20Contract()) - k.deleteDenomMap(ctx, tokenPair.Denom) + k.deleteTokenPairIdByERC20Addr(ctx, tokenPair.GetERC20Contract()) + k.deleteTokenPairIdByDenom(ctx, tokenPair.Denom) } // deleteTokenPair deletes the token pair for the given id @@ -74,38 +74,38 @@ func (k Keeper) deleteTokenPair(ctx sdk.Context, id []byte) { store.Delete(id) } -// GetERC20Map returns the token pair id for the given address -func (k Keeper) GetERC20Map(ctx sdk.Context, erc20 common.Address) []byte { +// GetTokenPairIdByERC20Addr returns the token pair id for the given address +func (k Keeper) GetTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address) []byte { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) return store.Get(erc20.Bytes()) } -// GetDenomMap returns the token pair id for the given denomination -func (k Keeper) GetDenomMap(ctx sdk.Context, denom string) []byte { +// GetTokenPairIdByDenom returns the token pair id for the given denomination +func (k Keeper) GetTokenPairIdByDenom(ctx sdk.Context, denom string) []byte { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByDenom) return store.Get([]byte(denom)) } -// SetERC20Map sets the token pair id for the given address -func (k Keeper) SetERC20Map(ctx sdk.Context, erc20 common.Address, id []byte) { +// SetTokenPairIdByERC20Addr sets the token pair id for the given address +func (k Keeper) SetTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address, id []byte) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) store.Set(erc20.Bytes(), id) } -// deleteERC20Map deletes the token pair id for the given address -func (k Keeper) deleteERC20Map(ctx sdk.Context, erc20 common.Address) { +// deleteTokenPairIdByERC20Addr deletes the token pair id for the given address +func (k Keeper) deleteTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) store.Delete(erc20.Bytes()) } -// SetDenomMap sets the token pair id for the denomination -func (k Keeper) SetDenomMap(ctx sdk.Context, denom string, id []byte) { +// SetTokenPairIdByDenom sets the token pair id for the denomination +func (k Keeper) SetTokenPairIdByDenom(ctx sdk.Context, denom string, id []byte) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByDenom) store.Set([]byte(denom), id) } -// deleteDenomMap deletes the token pair id for the given denom -func (k Keeper) deleteDenomMap(ctx sdk.Context, denom string) { +// deleteTokenPairIdByDenom deletes the token pair id for the given denom +func (k Keeper) deleteTokenPairIdByDenom(ctx sdk.Context, denom string) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByDenom) store.Delete([]byte(denom)) } diff --git a/x/erc20/keeper/token_pairs_test.go b/x/erc20/keeper/token_pairs_test.go index e1ef1fe0..3238fee2 100644 --- a/x/erc20/keeper/token_pairs_test.go +++ b/x/erc20/keeper/token_pairs_test.go @@ -104,8 +104,8 @@ func (suite *KeeperTestSuite) TestDeleteTokenPair() { pair := types.NewTokenPair(tests.GenerateAddress(), evmtypes.DefaultEVMDenom, true, types.OWNER_MODULE) id := pair.GetID() suite.app.Erc20Keeper.SetTokenPair(suite.ctx, pair) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, pair.GetERC20Contract(), id) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, id) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, pair.GetERC20Contract(), id) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, id) testCases := []struct { name string @@ -163,8 +163,8 @@ func (suite *KeeperTestSuite) TestIsERC20Registered() { addr := tests.GenerateAddress() pair := types.NewTokenPair(addr, "coin", true, types.OWNER_MODULE) suite.app.Erc20Keeper.SetTokenPair(suite.ctx, pair) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, addr, pair.GetID()) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, addr, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) testCases := []struct { name string @@ -200,8 +200,8 @@ func (suite *KeeperTestSuite) TestIsDenomRegistered() { addr := tests.GenerateAddress() pair := types.NewTokenPair(addr, "coin", true, types.OWNER_MODULE) suite.app.Erc20Keeper.SetTokenPair(suite.ctx, pair) - suite.app.Erc20Keeper.SetERC20Map(suite.ctx, addr, pair.GetID()) - suite.app.Erc20Keeper.SetDenomMap(suite.ctx, pair.Denom, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByERC20Addr(suite.ctx, addr, pair.GetID()) + suite.app.Erc20Keeper.SetTokenPairIdByDenom(suite.ctx, pair.Denom, pair.GetID()) testCases := []struct { name string From 440306a55a2b2e2eb6e79f8733ddf931f791d057 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Mon, 29 Jul 2024 19:43:28 +0900 Subject: [PATCH 5/7] feat(erc20): add indexes at genesis state to track active token pairs --- proto/canto/erc20/v1/erc20.proto | 16 + proto/canto/erc20/v1/genesis.proto | 8 + x/erc20/genesis.go | 24 +- x/erc20/genesis_test.go | 115 ++++-- x/erc20/keeper/token_pairs.go | 66 +++- x/erc20/simulation/decoder.go | 2 +- x/erc20/simulation/decoder_test.go | 2 +- x/erc20/types/erc20.pb.go | 582 +++++++++++++++++++++++++++-- x/erc20/types/genesis.go | 9 +- x/erc20/types/genesis.pb.go | 175 +++++++-- x/erc20/types/genesis_test.go | 2 +- x/erc20/types/keys.go | 8 +- x/inflation/types/inflation.pb.go | 6 +- 13 files changed, 916 insertions(+), 99 deletions(-) diff --git a/proto/canto/erc20/v1/erc20.proto b/proto/canto/erc20/v1/erc20.proto index ef5b96f5..343a71db 100644 --- a/proto/canto/erc20/v1/erc20.proto +++ b/proto/canto/erc20/v1/erc20.proto @@ -30,6 +30,22 @@ message TokenPair { Owner contract_owner = 4; } +// TokenPairDenomIndex is a mapping of a token pair's denom to its token pair +// ID. +message TokenPairDenomIndex { + option (gogoproto.equal) = true; + string denom = 1; + bytes token_pair_id = 2; +} + +// TokenPairERC20AddressIndex is a mapping of a token pair's ERC20 address to +// its token pair ID. +message TokenPairERC20AddressIndex { + option (gogoproto.equal) = true; + bytes erc20_address = 1; + bytes token_pair_id = 2; +} + // RegisterCoinProposal is a gov Content type to register a token pair for a // native Cosmos coin. message RegisterCoinProposal { diff --git a/proto/canto/erc20/v1/genesis.proto b/proto/canto/erc20/v1/genesis.proto index b96995b3..ef6b8b19 100644 --- a/proto/canto/erc20/v1/genesis.proto +++ b/proto/canto/erc20/v1/genesis.proto @@ -12,6 +12,14 @@ message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; // registered token pairs repeated TokenPair token_pairs = 2 [ (gogoproto.nullable) = false ]; + // list of mappings from Cosmos denoms to token pair IDs, used for indexing + // token pairs by their denom + repeated TokenPairDenomIndex denom_indexes = 3 + [ (gogoproto.nullable) = false ]; + // list of mappings from ERC20 addresses to token pair IDs, used for indexing + // token pairs by their ERC20 address + repeated TokenPairERC20AddressIndex erc20_address_indexes = 4 + [ (gogoproto.nullable) = false ]; } // Params defines the erc20 module params diff --git a/x/erc20/genesis.go b/x/erc20/genesis.go index e97fd4c6..234ad285 100644 --- a/x/erc20/genesis.go +++ b/x/erc20/genesis.go @@ -3,6 +3,7 @@ package erc20 import ( sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/ethereum/go-ethereum/common" "github.com/Canto-Network/Canto/v7/x/erc20/keeper" "github.com/Canto-Network/Canto/v7/x/erc20/types" @@ -23,18 +24,31 @@ func InitGenesis( panic("the erc20 module account has not been set") } + // set token pair once for _, pair := range data.TokenPairs { - id := pair.GetID() k.SetTokenPair(ctx, pair) - k.SetTokenPairIdByDenom(ctx, pair.Denom, id) - k.SetTokenPairIdByERC20Addr(ctx, pair.GetERC20Contract(), id) } + + // set indexes + // multiple contracts at the same denom can exist, + // but only one which is in indexes are valid. + for _, idx := range data.DenomIndexes { + id := idx.GetTokenPairId() + k.SetTokenPairIdByDenom(ctx, idx.Denom, id) + } + for _, idx := range data.Erc20AddressIndexes { + id := idx.GetTokenPairId() + k.SetTokenPairIdByERC20Addr(ctx, common.BytesToAddress(idx.Erc20Address), id) + } + } // ExportGenesis export module status func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { return &types.GenesisState{ - Params: k.GetParams(ctx), - TokenPairs: k.GetTokenPairs(ctx), + Params: k.GetParams(ctx), + TokenPairs: k.GetTokenPairs(ctx), + DenomIndexes: k.GetAllTokenPairDenomIndexes(ctx), + Erc20AddressIndexes: k.GetAllTokenPairERC20AddressIndexes(ctx), } } diff --git a/x/erc20/genesis_test.go b/x/erc20/genesis_test.go index 52f90a57..249ce7e8 100644 --- a/x/erc20/genesis_test.go +++ b/x/erc20/genesis_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/suite" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,6 +22,68 @@ import ( "github.com/Canto-Network/Canto/v7/x/erc20/types" ) +var ( + uqstars = "utestdenom" + // uqstars1 and uqstars2 have same denom + // uqstars1 is deployed first. + uqstars1 = types.TokenPair{ + Erc20Address: "0x2C68D1d6aB986Ff4640b51e1F14C716a076E44C4", + Denom: uqstars, + Enabled: true, + ContractOwner: types.OWNER_MODULE, + } + // uqstars2 is deployed later than uqstars1. + uqstars2 = types.TokenPair{ + Erc20Address: "0xD32eB974468ed767338533842D2D4Cc90B9BAb46", + Denom: uqstars, + Enabled: true, + ContractOwner: types.OWNER_MODULE, + } + customERC20 = types.TokenPair{ + Erc20Address: "0xC5e00D3b04563950941f7137B5AfA3a534F0D6d6", + Denom: "custom", + Enabled: true, + ContractOwner: types.OWNER_EXTERNAL, + } + + tokenPairs = []types.TokenPair{ + uqstars2, + // even if we put uqstars1 later, it should be disabled because + // uqstars2 is the deployed later than uqstars1 + uqstars1, + customERC20, + } + // denomIdxs should be ordered by denom ascending to compare with GetAllTokenPairDenomIndexes + denomIdxs = []types.TokenPairDenomIndex{ + { + Denom: customERC20.Denom, + TokenPairId: customERC20.GetID(), + }, + { + Denom: uqstars, + // denomIdx must have the latest token pair id assigned + // if there are multiple token pairs with the same denom + TokenPairId: uqstars2.GetID(), + }, + } + // erc20AddrIdxs should be ordered by erc20address ascending to compare with GetAllTokenPairERC20AddressIndexes + erc20AddrIdxs = []types.TokenPairERC20AddressIndex{ + { + Erc20Address: common.HexToAddress(uqstars1.Erc20Address).Bytes(), + TokenPairId: uqstars2.GetID(), + }, + { + Erc20Address: customERC20.GetERC20Contract().Bytes(), + TokenPairId: customERC20.GetID(), + }, + + { + Erc20Address: common.HexToAddress(uqstars2.Erc20Address).Bytes(), + TokenPairId: uqstars2.GetID(), + }, + } +) + type GenesisTestSuite struct { suite.Suite ctx sdk.Context @@ -39,7 +102,7 @@ func (suite *GenesisTestSuite) SetupTest() { suite.app = app.Setup(false, feemarkettypes.DefaultGenesisState()) suite.ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{ Height: 1, - ChainID: "canto_9000-1", + ChainID: "test-chainid", Time: time.Now().UTC(), ProposerAddress: consAddress.Bytes(), @@ -82,14 +145,10 @@ func (suite *GenesisTestSuite) TestERC20InitGenesis() { "custom genesis", types.NewGenesisState( types.DefaultParams(), - []types.TokenPair{ - { - Erc20Address: "0x5dCA2483280D9727c80b5518faC4556617fb19ZZ", - Denom: "coin", - Enabled: true, - ContractOwner: types.OWNER_MODULE, - }, - }), + tokenPairs, + denomIdxs, + erc20AddrIdxs, + ), }, } @@ -99,13 +158,23 @@ func (suite *GenesisTestSuite) TestERC20InitGenesis() { erc20.InitGenesis(suite.ctx, suite.app.Erc20Keeper, suite.app.AccountKeeper, tc.genesisState) }) params := suite.app.Erc20Keeper.GetParams(suite.ctx) + suite.Require().Equal(tc.genesisState.Params, params) tokenPairs := suite.app.Erc20Keeper.GetTokenPairs(suite.ctx) suite.Require().Equal(tc.genesisState.Params, params) if len(tokenPairs) > 0 { - suite.Require().Equal(tc.genesisState.TokenPairs, tokenPairs) + // The `tokenPairs` may not be sorted by tokenpair.id. For testing purposes, only check if the elements match. + suite.Require().ElementsMatch(tc.genesisState.TokenPairs, tokenPairs) + suite.Equal(denomIdxs, suite.app.Erc20Keeper.GetAllTokenPairDenomIndexes(suite.ctx)) + suite.Equal(erc20AddrIdxs, suite.app.Erc20Keeper.GetAllTokenPairERC20AddressIndexes(suite.ctx)) + suite.Equal( + uqstars2.GetID(), suite.app.Erc20Keeper.GetTokenPairIdByDenom(suite.ctx, uqstars), + "denom index must have latest token pair id", + ) } else { suite.Require().Len(tc.genesisState.TokenPairs, 0) + suite.Len(tc.genesisState.TokenPairs, 0) + suite.Len(suite.app.Erc20Keeper.GetAllTokenPairDenomIndexes(suite.ctx), 0) } } } @@ -127,14 +196,10 @@ func (suite *GenesisTestSuite) TestErc20ExportGenesis() { "custom genesis", types.NewGenesisState( types.DefaultParams(), - []types.TokenPair{ - { - Erc20Address: "0x5dCA2483280D9727c80b5518faC4556617fb19ZZ", - Denom: "coin", - Enabled: true, - ContractOwner: types.OWNER_MODULE, - }, - }), + tokenPairs, + denomIdxs, + erc20AddrIdxs, + ), }, } @@ -147,11 +212,19 @@ func (suite *GenesisTestSuite) TestErc20ExportGenesis() { tokenPairs := suite.app.Erc20Keeper.GetTokenPairs(suite.ctx) if len(tokenPairs) > 0 { - suite.Require().Equal(genesisExported.TokenPairs, tokenPairs) + // The `tokenPairs` may not be sorted by tokenpair.id. For testing purposes, only check if the elements match. + suite.Require().ElementsMatch(tc.genesisState.TokenPairs, tokenPairs) + suite.Equal(denomIdxs, suite.app.Erc20Keeper.GetAllTokenPairDenomIndexes(suite.ctx)) + suite.Equal(erc20AddrIdxs, suite.app.Erc20Keeper.GetAllTokenPairERC20AddressIndexes(suite.ctx)) + suite.Equal( + uqstars2.GetID(), suite.app.Erc20Keeper.GetTokenPairIdByDenom(suite.ctx, uqstars), + "denom index must have latest token pair id", + ) } else { - suite.Require().Len(genesisExported.TokenPairs, 0) + suite.Len(tc.genesisState.TokenPairs, 0) + suite.Len(suite.app.Erc20Keeper.GetAllTokenPairDenomIndexes(suite.ctx), 0) + suite.Len(suite.app.Erc20Keeper.GetAllTokenPairERC20AddressIndexes(suite.ctx), 0) } }) - // } } } diff --git a/x/erc20/keeper/token_pairs.go b/x/erc20/keeper/token_pairs.go index 66601d63..89c23a38 100644 --- a/x/erc20/keeper/token_pairs.go +++ b/x/erc20/keeper/token_pairs.go @@ -76,7 +76,7 @@ func (k Keeper) deleteTokenPair(ctx sdk.Context, id []byte) { // GetTokenPairIdByERC20Addr returns the token pair id for the given address func (k Keeper) GetTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address) []byte { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20Address) return store.Get(erc20.Bytes()) } @@ -88,13 +88,13 @@ func (k Keeper) GetTokenPairIdByDenom(ctx sdk.Context, denom string) []byte { // SetTokenPairIdByERC20Addr sets the token pair id for the given address func (k Keeper) SetTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address, id []byte) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20Address) store.Set(erc20.Bytes(), id) } // deleteTokenPairIdByERC20Addr deletes the token pair id for the given address func (k Keeper) deleteTokenPairIdByERC20Addr(ctx sdk.Context, erc20 common.Address) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20Address) store.Delete(erc20.Bytes()) } @@ -118,7 +118,7 @@ func (k Keeper) IsTokenPairRegistered(ctx sdk.Context, id []byte) bool { // IsERC20Registered check if registered ERC20 token is registered func (k Keeper) IsERC20Registered(ctx sdk.Context, erc20 common.Address) bool { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20Address) return store.Has(erc20.Bytes()) } @@ -127,3 +127,61 @@ func (k Keeper) IsDenomRegistered(ctx sdk.Context, denom string) bool { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByDenom) return store.Has([]byte(denom)) } + +// GetAllTokenPairDenomIndexes returns all token pair denom indexes +func (k Keeper) GetAllTokenPairDenomIndexes(ctx sdk.Context) []types.TokenPairDenomIndex { + var idxs []types.TokenPairDenomIndex + k.IterateTokenPairDenomIndex(ctx, func(denom string, id []byte) (stop bool) { + idx := types.TokenPairDenomIndex{ + Denom: denom, + TokenPairId: id, + } + idxs = append(idxs, idx) + return false + }) + return idxs +} + +// IterateTokenPairDenomIndex iterates over all token pair denom indexes +func (k Keeper) IterateTokenPairDenomIndex(ctx sdk.Context, cb func(denom string, id []byte) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByDenom) + iter := store.Iterator(nil, nil) + defer iter.Close() + + for ; iter.Valid(); iter.Next() { + denom := string(iter.Key()) + id := iter.Value() + if cb(denom, id) { + break + } + } +} + +// GetAllTokenPairERC20AddressIndexes returns all token pair ERC20 address indexes +func (k Keeper) GetAllTokenPairERC20AddressIndexes(ctx sdk.Context) []types.TokenPairERC20AddressIndex { + var idxs []types.TokenPairERC20AddressIndex + k.IterateTokenPairERC20AddressIndex(ctx, func(erc20Addr common.Address, id []byte) (stop bool) { + idx := types.TokenPairERC20AddressIndex{ + Erc20Address: erc20Addr.Bytes(), + TokenPairId: id, + } + idxs = append(idxs, idx) + return false + }) + return idxs +} + +// IterateTokenPairERC20AddressIndex iterates over all token pair ERC20 address indexes +func (k Keeper) IterateTokenPairERC20AddressIndex(ctx sdk.Context, cb func(erc20Addr common.Address, id []byte) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixTokenPairByERC20Address) + iter := store.Iterator(nil, nil) + defer iter.Close() + + for ; iter.Valid(); iter.Next() { + erc20Addr := common.BytesToAddress(iter.Key()) + id := iter.Value() + if cb(erc20Addr, id) { + break + } + } +} diff --git a/x/erc20/simulation/decoder.go b/x/erc20/simulation/decoder.go index ff9d530c..c650a1d5 100644 --- a/x/erc20/simulation/decoder.go +++ b/x/erc20/simulation/decoder.go @@ -21,7 +21,7 @@ func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { cdc.MustUnmarshal(kvB.Value, &tpB) return fmt.Sprintf("%v\n%v", tpA, tpB) - case bytes.Equal(kvA.Key[:1], types.KeyPrefixTokenPairByERC20): + case bytes.Equal(kvA.Key[:1], types.KeyPrefixTokenPairByERC20Address): var tpA, tpB types.TokenPair cdc.MustUnmarshal(kvA.Value, &tpA) cdc.MustUnmarshal(kvB.Value, &tpB) diff --git a/x/erc20/simulation/decoder_test.go b/x/erc20/simulation/decoder_test.go index f2d1bcf1..9d6502a2 100644 --- a/x/erc20/simulation/decoder_test.go +++ b/x/erc20/simulation/decoder_test.go @@ -23,7 +23,7 @@ func TestERC20Store(t *testing.T) { kvPairs := kv.Pairs{ Pairs: []kv.Pair{ {Key: types.KeyPrefixTokenPair, Value: cdc.Marshaler.MustMarshal(&tokenPair)}, - {Key: types.KeyPrefixTokenPairByERC20, Value: cdc.Marshaler.MustMarshal(&tokenPair)}, + {Key: types.KeyPrefixTokenPairByERC20Address, Value: cdc.Marshaler.MustMarshal(&tokenPair)}, {Key: types.KeyPrefixTokenPairByDenom, Value: cdc.Marshaler.MustMarshal(&tokenPair)}, {Key: []byte{0x99}, Value: []byte{0x99}}, }, diff --git a/x/erc20/types/erc20.pb.go b/x/erc20/types/erc20.pb.go index 249b1b16..781cbfab 100644 --- a/x/erc20/types/erc20.pb.go +++ b/x/erc20/types/erc20.pb.go @@ -4,6 +4,7 @@ package types import ( + bytes "bytes" fmt "fmt" types "github.com/cosmos/cosmos-sdk/x/bank/types" _ "github.com/gogo/protobuf/gogoproto" @@ -130,6 +131,114 @@ func (m *TokenPair) GetContractOwner() Owner { return OWNER_UNSPECIFIED } +// TokenPairDenomIndex is a mapping of a token pair's denom to its token pair +// ID. +type TokenPairDenomIndex struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + TokenPairId []byte `protobuf:"bytes,2,opt,name=token_pair_id,json=tokenPairId,proto3" json:"token_pair_id,omitempty"` +} + +func (m *TokenPairDenomIndex) Reset() { *m = TokenPairDenomIndex{} } +func (m *TokenPairDenomIndex) String() string { return proto.CompactTextString(m) } +func (*TokenPairDenomIndex) ProtoMessage() {} +func (*TokenPairDenomIndex) Descriptor() ([]byte, []int) { + return fileDescriptor_5c364669f6882b8b, []int{1} +} +func (m *TokenPairDenomIndex) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TokenPairDenomIndex) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TokenPairDenomIndex.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TokenPairDenomIndex) XXX_Merge(src proto.Message) { + xxx_messageInfo_TokenPairDenomIndex.Merge(m, src) +} +func (m *TokenPairDenomIndex) XXX_Size() int { + return m.Size() +} +func (m *TokenPairDenomIndex) XXX_DiscardUnknown() { + xxx_messageInfo_TokenPairDenomIndex.DiscardUnknown(m) +} + +var xxx_messageInfo_TokenPairDenomIndex proto.InternalMessageInfo + +func (m *TokenPairDenomIndex) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +func (m *TokenPairDenomIndex) GetTokenPairId() []byte { + if m != nil { + return m.TokenPairId + } + return nil +} + +// TokenPairERC20AddressIndex is a mapping of a token pair's ERC20 address to +// its token pair ID. +type TokenPairERC20AddressIndex struct { + Erc20Address []byte `protobuf:"bytes,1,opt,name=erc20_address,json=erc20Address,proto3" json:"erc20_address,omitempty"` + TokenPairId []byte `protobuf:"bytes,2,opt,name=token_pair_id,json=tokenPairId,proto3" json:"token_pair_id,omitempty"` +} + +func (m *TokenPairERC20AddressIndex) Reset() { *m = TokenPairERC20AddressIndex{} } +func (m *TokenPairERC20AddressIndex) String() string { return proto.CompactTextString(m) } +func (*TokenPairERC20AddressIndex) ProtoMessage() {} +func (*TokenPairERC20AddressIndex) Descriptor() ([]byte, []int) { + return fileDescriptor_5c364669f6882b8b, []int{2} +} +func (m *TokenPairERC20AddressIndex) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TokenPairERC20AddressIndex) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TokenPairERC20AddressIndex.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TokenPairERC20AddressIndex) XXX_Merge(src proto.Message) { + xxx_messageInfo_TokenPairERC20AddressIndex.Merge(m, src) +} +func (m *TokenPairERC20AddressIndex) XXX_Size() int { + return m.Size() +} +func (m *TokenPairERC20AddressIndex) XXX_DiscardUnknown() { + xxx_messageInfo_TokenPairERC20AddressIndex.DiscardUnknown(m) +} + +var xxx_messageInfo_TokenPairERC20AddressIndex proto.InternalMessageInfo + +func (m *TokenPairERC20AddressIndex) GetErc20Address() []byte { + if m != nil { + return m.Erc20Address + } + return nil +} + +func (m *TokenPairERC20AddressIndex) GetTokenPairId() []byte { + if m != nil { + return m.TokenPairId + } + return nil +} + // RegisterCoinProposal is a gov Content type to register a token pair for a // native Cosmos coin. type RegisterCoinProposal struct { @@ -145,7 +254,7 @@ func (m *RegisterCoinProposal) Reset() { *m = RegisterCoinProposal{} } func (m *RegisterCoinProposal) String() string { return proto.CompactTextString(m) } func (*RegisterCoinProposal) ProtoMessage() {} func (*RegisterCoinProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_5c364669f6882b8b, []int{1} + return fileDescriptor_5c364669f6882b8b, []int{3} } func (m *RegisterCoinProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -210,7 +319,7 @@ func (m *RegisterERC20Proposal) Reset() { *m = RegisterERC20Proposal{} } func (m *RegisterERC20Proposal) String() string { return proto.CompactTextString(m) } func (*RegisterERC20Proposal) ProtoMessage() {} func (*RegisterERC20Proposal) Descriptor() ([]byte, []int) { - return fileDescriptor_5c364669f6882b8b, []int{2} + return fileDescriptor_5c364669f6882b8b, []int{4} } func (m *RegisterERC20Proposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -276,7 +385,7 @@ func (m *ToggleTokenConversionProposal) Reset() { *m = ToggleTokenConver func (m *ToggleTokenConversionProposal) String() string { return proto.CompactTextString(m) } func (*ToggleTokenConversionProposal) ProtoMessage() {} func (*ToggleTokenConversionProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_5c364669f6882b8b, []int{3} + return fileDescriptor_5c364669f6882b8b, []int{5} } func (m *ToggleTokenConversionProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -329,6 +438,8 @@ func (m *ToggleTokenConversionProposal) GetToken() string { func init() { proto.RegisterEnum("canto.erc20.v1.Owner", Owner_name, Owner_value) proto.RegisterType((*TokenPair)(nil), "canto.erc20.v1.TokenPair") + proto.RegisterType((*TokenPairDenomIndex)(nil), "canto.erc20.v1.TokenPairDenomIndex") + proto.RegisterType((*TokenPairERC20AddressIndex)(nil), "canto.erc20.v1.TokenPairERC20AddressIndex") proto.RegisterType((*RegisterCoinProposal)(nil), "canto.erc20.v1.RegisterCoinProposal") proto.RegisterType((*RegisterERC20Proposal)(nil), "canto.erc20.v1.RegisterERC20Proposal") proto.RegisterType((*ToggleTokenConversionProposal)(nil), "canto.erc20.v1.ToggleTokenConversionProposal") @@ -337,39 +448,42 @@ func init() { func init() { proto.RegisterFile("canto/erc20/v1/erc20.proto", fileDescriptor_5c364669f6882b8b) } var fileDescriptor_5c364669f6882b8b = []byte{ - // 499 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x41, 0x6b, 0x13, 0x41, - 0x14, 0xc7, 0x77, 0xda, 0x54, 0xdb, 0x69, 0x1b, 0xe2, 0xd0, 0x40, 0x08, 0x74, 0x1b, 0xe2, 0x25, - 0x08, 0xee, 0x36, 0xf1, 0x20, 0x88, 0x20, 0xed, 0x76, 0x85, 0x48, 0x9b, 0x84, 0x75, 0x8b, 0xe2, - 0x25, 0xcc, 0xee, 0x0e, 0xeb, 0x92, 0x64, 0x5e, 0x98, 0x19, 0xb7, 0xf6, 0x1b, 0x78, 0xf4, 0xe2, - 0x5d, 0xd0, 0x0f, 0xd3, 0x63, 0x8f, 0x9e, 0x44, 0x92, 0x8b, 0x1f, 0x43, 0x76, 0x66, 0x23, 0xe9, - 0x4d, 0xf0, 0x36, 0xff, 0xff, 0x7b, 0x3b, 0xf3, 0xdb, 0xf7, 0x9f, 0xc1, 0xcd, 0x98, 0x72, 0x05, - 0x2e, 0x13, 0x71, 0xef, 0xd8, 0xcd, 0xbb, 0x66, 0xe1, 0xcc, 0x05, 0x28, 0x20, 0x55, 0x5d, 0x73, - 0x8c, 0x95, 0x77, 0x9b, 0x07, 0x29, 0xa4, 0xa0, 0x4b, 0x6e, 0xb1, 0x32, 0x5d, 0x4d, 0x3b, 0x06, - 0x39, 0x03, 0xe9, 0x46, 0x94, 0x4f, 0xdc, 0xbc, 0x1b, 0x31, 0x45, 0xbb, 0x5a, 0x98, 0x7a, 0xfb, - 0x3b, 0xc2, 0x3b, 0x21, 0x4c, 0x18, 0x1f, 0xd1, 0x4c, 0x90, 0x87, 0x78, 0x5f, 0xef, 0x37, 0xa6, - 0x49, 0x22, 0x98, 0x94, 0x0d, 0xd4, 0x42, 0x9d, 0x9d, 0x60, 0x4f, 0x9b, 0x27, 0xc6, 0x23, 0x07, - 0x78, 0x2b, 0x61, 0x1c, 0x66, 0x8d, 0x0d, 0x5d, 0x34, 0x82, 0x34, 0xf0, 0x7d, 0xc6, 0x69, 0x34, - 0x65, 0x49, 0x63, 0xb3, 0x85, 0x3a, 0xdb, 0xc1, 0x4a, 0x92, 0xe7, 0xb8, 0x1a, 0x03, 0x57, 0x82, - 0xc6, 0x6a, 0x0c, 0x57, 0x9c, 0x89, 0x46, 0xa5, 0x85, 0x3a, 0xd5, 0x5e, 0xdd, 0xb9, 0xfb, 0x07, - 0xce, 0xb0, 0x28, 0x06, 0xfb, 0xab, 0x66, 0x2d, 0x9f, 0x55, 0x7e, 0x7f, 0x3d, 0x42, 0xed, 0x2f, - 0x08, 0x1f, 0x04, 0x2c, 0xcd, 0xa4, 0x62, 0xc2, 0x83, 0x8c, 0x8f, 0x04, 0xcc, 0x41, 0xd2, 0x69, - 0x01, 0xa3, 0x32, 0x35, 0x65, 0x25, 0xa9, 0x11, 0xa4, 0x85, 0x77, 0x13, 0x26, 0x63, 0x91, 0xcd, - 0x55, 0x06, 0xbc, 0x04, 0x5d, 0xb7, 0xc8, 0x0b, 0xbc, 0x3d, 0x63, 0x8a, 0x26, 0x54, 0x51, 0xcd, - 0xbb, 0xdb, 0x3b, 0x74, 0xcc, 0xa8, 0x1c, 0x3d, 0x9d, 0x72, 0x54, 0xce, 0x45, 0xd9, 0x74, 0x5a, - 0xb9, 0xf9, 0x79, 0x64, 0x05, 0x7f, 0x3f, 0xd2, 0x5c, 0x56, 0xfb, 0x1a, 0xd7, 0x57, 0x58, 0x7e, - 0xe0, 0xf5, 0x8e, 0xff, 0x9b, 0xab, 0x8d, 0xcd, 0xb0, 0x57, 0x01, 0x6c, 0xae, 0x05, 0x50, 0x7a, - 0xe5, 0xd1, 0x12, 0x1f, 0x86, 0x90, 0xa6, 0x53, 0xa6, 0xe3, 0xf3, 0x80, 0xe7, 0x4c, 0xc8, 0x0c, - 0xee, 0x8c, 0x26, 0x5c, 0x47, 0x08, 0xff, 0x11, 0xa1, 0x40, 0x2f, 0xb6, 0x2c, 0xcf, 0x36, 0xc2, - 0xe4, 0xf0, 0xe8, 0x15, 0xde, 0xd2, 0xb1, 0x90, 0x3a, 0x7e, 0x30, 0x7c, 0x33, 0xf0, 0x83, 0xf1, - 0xe5, 0xe0, 0xf5, 0xc8, 0xf7, 0xfa, 0x2f, 0xfb, 0xfe, 0x59, 0xcd, 0x22, 0x35, 0xbc, 0x67, 0xec, - 0x8b, 0xe1, 0xd9, 0xe5, 0xb9, 0x5f, 0x43, 0x84, 0xe0, 0xaa, 0x71, 0xfc, 0xb7, 0xa1, 0x1f, 0x0c, - 0x4e, 0xce, 0x6b, 0x1b, 0xcd, 0xca, 0xa7, 0x6f, 0xb6, 0x75, 0xda, 0xbf, 0x59, 0xd8, 0xe8, 0x76, - 0x61, 0xa3, 0x5f, 0x0b, 0x1b, 0x7d, 0x5e, 0xda, 0xd6, 0xed, 0xd2, 0xb6, 0x7e, 0x2c, 0x6d, 0xeb, - 0x9d, 0x9b, 0x66, 0xea, 0xfd, 0x87, 0xc8, 0x89, 0x61, 0xe6, 0x7a, 0xc5, 0x1d, 0x79, 0x3c, 0x60, - 0xea, 0x0a, 0xc4, 0xc4, 0x28, 0x37, 0x7f, 0xea, 0x7e, 0x2c, 0x1f, 0x85, 0xba, 0x9e, 0x33, 0x19, - 0xdd, 0xd3, 0x97, 0xf9, 0xc9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x1e, 0x95, 0xcd, 0x30, - 0x03, 0x00, 0x00, + // 556 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0xcf, 0x6b, 0x13, 0x41, + 0x14, 0xde, 0x69, 0x53, 0x6d, 0x27, 0x3f, 0x88, 0x63, 0x02, 0x21, 0xd0, 0x6d, 0x88, 0x97, 0x20, + 0xb8, 0x6b, 0xe2, 0x41, 0x10, 0x41, 0xda, 0x64, 0x85, 0x48, 0x9b, 0x84, 0x35, 0x41, 0xf1, 0x12, + 0x26, 0xbb, 0xc3, 0xba, 0x24, 0x99, 0x17, 0x66, 0xc7, 0xb4, 0xfd, 0x0f, 0x3c, 0x7a, 0xf1, 0x2e, + 0xe8, 0x1f, 0xd3, 0x63, 0x8f, 0x9e, 0x44, 0x92, 0x8b, 0x7f, 0x86, 0xec, 0xcc, 0x6e, 0x4c, 0xc5, + 0x43, 0xc1, 0xdb, 0x7e, 0xdf, 0x7b, 0xfb, 0xde, 0xf7, 0xbe, 0xf7, 0x06, 0x57, 0x3d, 0xca, 0x25, + 0xd8, 0x4c, 0x78, 0xad, 0xc7, 0xf6, 0xb2, 0xa9, 0x3f, 0xac, 0x85, 0x00, 0x09, 0xa4, 0xa0, 0x62, + 0x96, 0xa6, 0x96, 0xcd, 0x6a, 0x29, 0x80, 0x00, 0x54, 0xc8, 0x8e, 0xbf, 0x74, 0x56, 0xd5, 0xf4, + 0x20, 0x9a, 0x43, 0x64, 0x4f, 0x28, 0x9f, 0xda, 0xcb, 0xe6, 0x84, 0x49, 0xda, 0x54, 0x40, 0xc7, + 0xeb, 0xdf, 0x10, 0x3e, 0x18, 0xc2, 0x94, 0xf1, 0x01, 0x0d, 0x05, 0x79, 0x80, 0xf3, 0xaa, 0xde, + 0x98, 0xfa, 0xbe, 0x60, 0x51, 0x54, 0x41, 0x35, 0xd4, 0x38, 0x70, 0x73, 0x8a, 0x3c, 0xd6, 0x1c, + 0x29, 0xe1, 0x3d, 0x9f, 0x71, 0x98, 0x57, 0x76, 0x54, 0x50, 0x03, 0x52, 0xc1, 0x77, 0x19, 0xa7, + 0x93, 0x19, 0xf3, 0x2b, 0xbb, 0x35, 0xd4, 0xd8, 0x77, 0x53, 0x48, 0x9e, 0xe3, 0x82, 0x07, 0x5c, + 0x0a, 0xea, 0xc9, 0x31, 0x9c, 0x73, 0x26, 0x2a, 0x99, 0x1a, 0x6a, 0x14, 0x5a, 0x65, 0xeb, 0xe6, + 0x04, 0x56, 0x3f, 0x0e, 0xba, 0xf9, 0x34, 0x59, 0xc1, 0x67, 0x99, 0x5f, 0x5f, 0x8e, 0x50, 0x7d, + 0x84, 0xef, 0x6f, 0x54, 0x76, 0xe2, 0x7e, 0x5d, 0xee, 0xb3, 0x8b, 0x3f, 0x52, 0xd0, 0xb6, 0x94, + 0x3a, 0xce, 0xcb, 0x38, 0x79, 0xbc, 0xa0, 0xa1, 0x18, 0x87, 0xbe, 0x12, 0x9a, 0x73, 0xb3, 0x32, + 0xad, 0xd0, 0xf5, 0x93, 0xb2, 0x53, 0x5c, 0xdd, 0x94, 0x75, 0xdc, 0xf6, 0x66, 0x46, 0x5d, 0xfd, + 0x9f, 0x6e, 0xe4, 0xfe, 0x72, 0xe3, 0xf6, 0xcd, 0x3e, 0x23, 0x5c, 0x72, 0x59, 0x10, 0x46, 0x92, + 0x89, 0x36, 0x84, 0x7c, 0x20, 0x60, 0x01, 0x11, 0x9d, 0xc5, 0x53, 0xc8, 0x50, 0xce, 0x58, 0x3a, + 0x85, 0x02, 0xa4, 0x86, 0xb3, 0x3e, 0x8b, 0x3c, 0x11, 0x2e, 0x64, 0x08, 0x3c, 0x31, 0x7b, 0x9b, + 0x22, 0x2f, 0xf0, 0xfe, 0x9c, 0x49, 0xea, 0x53, 0x49, 0x95, 0xe7, 0xd9, 0xd6, 0xa1, 0xa5, 0xd7, + 0x6d, 0xa9, 0x0d, 0x27, 0xeb, 0xb6, 0xce, 0x92, 0xa4, 0x93, 0xcc, 0xd5, 0x8f, 0x23, 0xc3, 0xdd, + 0xfc, 0xa4, 0x74, 0x19, 0xf5, 0x4b, 0x5c, 0x4e, 0x65, 0x29, 0x0f, 0xfe, 0x5b, 0x57, 0x1d, 0x6b, + 0x8b, 0x52, 0xdb, 0x76, 0xb7, 0x8e, 0x28, 0xe1, 0x92, 0xd6, 0x11, 0x3e, 0x1c, 0x42, 0x10, 0xcc, + 0x98, 0xda, 0x42, 0x1b, 0xf8, 0x92, 0x89, 0x28, 0x84, 0x1b, 0xd6, 0x0c, 0xb7, 0x25, 0x0c, 0x6f, + 0x29, 0x21, 0x96, 0x1e, 0x97, 0x4c, 0x7a, 0x6b, 0xa0, 0xf7, 0xf0, 0xf0, 0x15, 0xde, 0x53, 0xa7, + 0x45, 0xca, 0xf8, 0x5e, 0xff, 0x4d, 0xcf, 0x71, 0xc7, 0xa3, 0xde, 0xeb, 0x81, 0xd3, 0xee, 0xbe, + 0xec, 0x3a, 0x9d, 0xa2, 0x41, 0x8a, 0x38, 0xa7, 0xe9, 0xb3, 0x7e, 0x67, 0x74, 0xea, 0x14, 0x11, + 0x21, 0xb8, 0xa0, 0x19, 0xe7, 0xed, 0xd0, 0x71, 0x7b, 0xc7, 0xa7, 0xc5, 0x9d, 0x6a, 0xe6, 0xe3, + 0x57, 0xd3, 0x38, 0xe9, 0x5e, 0xad, 0x4c, 0x74, 0xbd, 0x32, 0xd1, 0xcf, 0x95, 0x89, 0x3e, 0xad, + 0x4d, 0xe3, 0x7a, 0x6d, 0x1a, 0xdf, 0xd7, 0xa6, 0xf1, 0xce, 0x0e, 0x42, 0xf9, 0xfe, 0xc3, 0xc4, + 0xf2, 0x60, 0x6e, 0xb7, 0xe3, 0x3b, 0x7f, 0xd4, 0x63, 0xf2, 0x1c, 0xc4, 0x54, 0x23, 0x7b, 0xf9, + 0xd4, 0xbe, 0x48, 0x1e, 0xb6, 0xbc, 0x5c, 0xb0, 0x68, 0x72, 0x47, 0x3d, 0xc8, 0x27, 0xbf, 0x03, + 0x00, 0x00, 0xff, 0xff, 0x91, 0x9a, 0x09, 0x15, 0xf4, 0x03, 0x00, 0x00, } func (this *TokenPair) Equal(that interface{}) bool { @@ -405,6 +519,60 @@ func (this *TokenPair) Equal(that interface{}) bool { } return true } +func (this *TokenPairDenomIndex) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*TokenPairDenomIndex) + if !ok { + that2, ok := that.(TokenPairDenomIndex) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Denom != that1.Denom { + return false + } + if !bytes.Equal(this.TokenPairId, that1.TokenPairId) { + return false + } + return true +} +func (this *TokenPairERC20AddressIndex) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*TokenPairERC20AddressIndex) + if !ok { + that2, ok := that.(TokenPairERC20AddressIndex) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Erc20Address, that1.Erc20Address) { + return false + } + if !bytes.Equal(this.TokenPairId, that1.TokenPairId) { + return false + } + return true +} func (this *ToggleTokenConversionProposal) Equal(that interface{}) bool { if that == nil { return this == nil @@ -487,6 +655,80 @@ func (m *TokenPair) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TokenPairDenomIndex) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TokenPairDenomIndex) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TokenPairDenomIndex) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TokenPairId) > 0 { + i -= len(m.TokenPairId) + copy(dAtA[i:], m.TokenPairId) + i = encodeVarintErc20(dAtA, i, uint64(len(m.TokenPairId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintErc20(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TokenPairERC20AddressIndex) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TokenPairERC20AddressIndex) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TokenPairERC20AddressIndex) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TokenPairId) > 0 { + i -= len(m.TokenPairId) + copy(dAtA[i:], m.TokenPairId) + i = encodeVarintErc20(dAtA, i, uint64(len(m.TokenPairId))) + i-- + dAtA[i] = 0x12 + } + if len(m.Erc20Address) > 0 { + i -= len(m.Erc20Address) + copy(dAtA[i:], m.Erc20Address) + i = encodeVarintErc20(dAtA, i, uint64(len(m.Erc20Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *RegisterCoinProposal) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -656,6 +898,40 @@ func (m *TokenPair) Size() (n int) { return n } +func (m *TokenPairDenomIndex) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovErc20(uint64(l)) + } + l = len(m.TokenPairId) + if l > 0 { + n += 1 + l + sovErc20(uint64(l)) + } + return n +} + +func (m *TokenPairERC20AddressIndex) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Erc20Address) + if l > 0 { + n += 1 + l + sovErc20(uint64(l)) + } + l = len(m.TokenPairId) + if l > 0 { + n += 1 + l + sovErc20(uint64(l)) + } + return n +} + func (m *RegisterCoinProposal) Size() (n int) { if m == nil { return 0 @@ -876,6 +1152,240 @@ func (m *TokenPair) Unmarshal(dAtA []byte) error { } return nil } +func (m *TokenPairDenomIndex) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TokenPairDenomIndex: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TokenPairDenomIndex: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthErc20 + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthErc20 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenPairId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthErc20 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthErc20 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenPairId = append(m.TokenPairId[:0], dAtA[iNdEx:postIndex]...) + if m.TokenPairId == nil { + m.TokenPairId = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipErc20(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthErc20 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TokenPairERC20AddressIndex) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TokenPairERC20AddressIndex: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TokenPairERC20AddressIndex: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthErc20 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthErc20 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Erc20Address = append(m.Erc20Address[:0], dAtA[iNdEx:postIndex]...) + if m.Erc20Address == nil { + m.Erc20Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TokenPairId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowErc20 + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthErc20 + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthErc20 + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TokenPairId = append(m.TokenPairId[:0], dAtA[iNdEx:postIndex]...) + if m.TokenPairId == nil { + m.TokenPairId = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipErc20(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthErc20 + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RegisterCoinProposal) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/erc20/types/genesis.go b/x/erc20/types/genesis.go index dab7227c..25ffcb3a 100644 --- a/x/erc20/types/genesis.go +++ b/x/erc20/types/genesis.go @@ -3,10 +3,13 @@ package types import "fmt" // NewGenesisState creates a new genesis state. -func NewGenesisState(params Params, pairs []TokenPair) GenesisState { +func NewGenesisState(params Params, pairs []TokenPair, denomIndexes []TokenPairDenomIndex, erc20AddrIndexes []TokenPairERC20AddressIndex, +) GenesisState { return GenesisState{ - Params: params, - TokenPairs: pairs, + Params: params, + TokenPairs: pairs, + DenomIndexes: denomIndexes, + Erc20AddressIndexes: erc20AddrIndexes, } } diff --git a/x/erc20/types/genesis.pb.go b/x/erc20/types/genesis.pb.go index 4c684ef9..fadb3478 100644 --- a/x/erc20/types/genesis.pb.go +++ b/x/erc20/types/genesis.pb.go @@ -29,6 +29,12 @@ type GenesisState struct { Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` // registered token pairs TokenPairs []TokenPair `protobuf:"bytes,2,rep,name=token_pairs,json=tokenPairs,proto3" json:"token_pairs"` + // list of mappings from Cosmos denoms to token pair IDs, used for indexing + // token pairs by their denom + DenomIndexes []TokenPairDenomIndex `protobuf:"bytes,3,rep,name=denom_indexes,json=denomIndexes,proto3" json:"denom_indexes"` + // list of mappings from ERC20 addresses to token pair IDs, used for indexing + // token pairs by their ERC20 address + Erc20AddressIndexes []TokenPairERC20AddressIndex `protobuf:"bytes,4,rep,name=erc20_address_indexes,json=erc20AddressIndexes,proto3" json:"erc20_address_indexes"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -78,6 +84,20 @@ func (m *GenesisState) GetTokenPairs() []TokenPair { return nil } +func (m *GenesisState) GetDenomIndexes() []TokenPairDenomIndex { + if m != nil { + return m.DenomIndexes + } + return nil +} + +func (m *GenesisState) GetErc20AddressIndexes() []TokenPairERC20AddressIndex { + if m != nil { + return m.Erc20AddressIndexes + } + return nil +} + // Params defines the erc20 module params type Params struct { // parameter to enable the conversion of Cosmos coins <--> ERC20 tokens. @@ -143,27 +163,32 @@ func init() { func init() { proto.RegisterFile("canto/erc20/v1/genesis.proto", fileDescriptor_6af5bf0eee46eaa1) } var fileDescriptor_6af5bf0eee46eaa1 = []byte{ - // 311 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0x4e, 0xcc, 0x2b, - 0xc9, 0xd7, 0x4f, 0x2d, 0x4a, 0x36, 0x32, 0xd0, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, - 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x03, 0xcb, 0xea, 0x81, 0x65, 0xf5, - 0xca, 0x0c, 0xa5, 0xa4, 0xd0, 0x54, 0x43, 0x24, 0xc0, 0x6a, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, - 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x22, 0xaa, 0xd4, 0xc6, 0xc8, 0xc5, 0xe3, 0x0e, 0x31, 0x33, 0xb8, - 0x24, 0xb1, 0x24, 0x55, 0xc8, 0x84, 0x8b, 0xad, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, 0x82, 0x51, - 0x81, 0x51, 0x83, 0xdb, 0x48, 0x4c, 0x0f, 0xd5, 0x0e, 0xbd, 0x00, 0xb0, 0xac, 0x13, 0xcb, 0x89, - 0x7b, 0xf2, 0x0c, 0x41, 0x50, 0xb5, 0x42, 0x0e, 0x5c, 0xdc, 0x25, 0xf9, 0xd9, 0xa9, 0x79, 0xf1, - 0x05, 0x89, 0x99, 0x45, 0xc5, 0x12, 0x4c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x92, 0xe8, 0x5a, 0x43, - 0x40, 0x4a, 0x02, 0x12, 0x33, 0x8b, 0xa0, 0xba, 0xb9, 0x4a, 0x60, 0x02, 0xc5, 0x4a, 0x69, 0x5c, - 0x6c, 0x10, 0x93, 0x85, 0x14, 0xb9, 0x78, 0x52, 0xf3, 0x12, 0x93, 0x72, 0x52, 0xe3, 0xc1, 0x1a, - 0xc1, 0xee, 0xe0, 0x08, 0xe2, 0x86, 0x88, 0xb9, 0x82, 0x84, 0x84, 0x2c, 0xb9, 0xf8, 0x61, 0x4a, - 0xca, 0x72, 0xe3, 0x33, 0xf2, 0xf3, 0xb3, 0x25, 0x98, 0x40, 0xaa, 0x9c, 0x04, 0x1f, 0xdd, 0x93, - 0xe7, 0x75, 0x85, 0xa8, 0x0c, 0xf3, 0xf5, 0xc8, 0xcf, 0xcf, 0x0e, 0xe2, 0x85, 0x6a, 0x2c, 0xcb, - 0x05, 0x71, 0x9d, 0x3c, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, - 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x3f, - 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xdf, 0x19, 0xe4, 0x70, 0x5d, 0xbf, - 0xd4, 0x92, 0xf2, 0xfc, 0xa2, 0x6c, 0x08, 0x4f, 0xbf, 0xcc, 0x5c, 0xbf, 0x02, 0x1a, 0xb4, 0x25, - 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0xe0, 0x20, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x42, - 0x2b, 0x40, 0x6d, 0xa4, 0x01, 0x00, 0x00, + // 386 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcd, 0x6e, 0xda, 0x40, + 0x14, 0x85, 0x6d, 0x40, 0xa8, 0x1a, 0x43, 0xab, 0xba, 0x3f, 0x72, 0x51, 0x65, 0x28, 0xdd, 0xa0, + 0x4a, 0xf5, 0x80, 0x5b, 0xa9, 0xea, 0xae, 0x85, 0xa2, 0x86, 0x45, 0x10, 0x72, 0xa2, 0x2c, 0xb2, + 0xb1, 0x06, 0x3c, 0x31, 0x96, 0x63, 0x8f, 0xe5, 0x99, 0x38, 0xe4, 0x2d, 0xf2, 0x40, 0x79, 0x00, + 0x96, 0x2c, 0xb3, 0x42, 0x91, 0x79, 0x91, 0x68, 0x66, 0x0c, 0x22, 0x48, 0xec, 0xee, 0x3d, 0xe7, + 0x3b, 0xc7, 0xf2, 0xb5, 0xc1, 0xe7, 0x19, 0x8a, 0x19, 0x81, 0x38, 0x9d, 0xd9, 0x5d, 0x98, 0xf5, + 0xa0, 0x8f, 0x63, 0x4c, 0x03, 0x6a, 0x25, 0x29, 0x61, 0x44, 0x7f, 0x2d, 0x5c, 0x4b, 0xb8, 0x56, + 0xd6, 0x6b, 0x34, 0x0e, 0x68, 0x69, 0x08, 0xb6, 0xf1, 0xde, 0x27, 0x3e, 0x11, 0x23, 0xe4, 0x93, + 0x54, 0xdb, 0x0f, 0x25, 0x50, 0xfb, 0x2f, 0x3b, 0xcf, 0x18, 0x62, 0x58, 0xff, 0x09, 0xaa, 0x09, + 0x4a, 0x51, 0x44, 0x0d, 0xb5, 0xa5, 0x76, 0x34, 0xfb, 0xa3, 0xf5, 0xf2, 0x19, 0xd6, 0x44, 0xb8, + 0xfd, 0xca, 0x72, 0xdd, 0x54, 0x9c, 0x82, 0xd5, 0xff, 0x00, 0x8d, 0x91, 0x10, 0xc7, 0x6e, 0x82, + 0x82, 0x94, 0x1a, 0xa5, 0x56, 0xb9, 0xa3, 0xd9, 0x9f, 0x0e, 0xa3, 0xe7, 0x1c, 0x99, 0xa0, 0x20, + 0x2d, 0xd2, 0x80, 0x6d, 0x05, 0xaa, 0x8f, 0x41, 0xdd, 0xc3, 0x31, 0x89, 0xdc, 0x20, 0xf6, 0xf0, + 0x02, 0x53, 0xa3, 0x2c, 0x3a, 0xbe, 0x1e, 0xed, 0xf8, 0xc7, 0xe9, 0x11, 0x87, 0x8b, 0xb6, 0x9a, + 0xb7, 0x53, 0x30, 0xd5, 0x3d, 0xf0, 0x41, 0x64, 0x5c, 0xe4, 0x79, 0x29, 0xa6, 0x74, 0xd7, 0x5b, + 0x11, 0xbd, 0xdf, 0x8e, 0xf6, 0x0e, 0x9d, 0x81, 0xdd, 0xfd, 0x2b, 0x43, 0xfb, 0xf5, 0xef, 0x04, + 0xba, 0x6f, 0x60, 0xda, 0xbe, 0x02, 0x55, 0x79, 0x0f, 0xfd, 0x0b, 0xa8, 0xe1, 0x18, 0x4d, 0xaf, + 0xb1, 0x2b, 0x38, 0x71, 0xbd, 0x57, 0x8e, 0x26, 0xb5, 0x21, 0x97, 0xf4, 0xdf, 0xe0, 0xcd, 0x16, + 0xc9, 0x22, 0x77, 0x4e, 0x48, 0x68, 0x94, 0x38, 0xd5, 0x7f, 0x9b, 0xaf, 0x9b, 0xf5, 0xa1, 0x24, + 0x2f, 0x4e, 0x4f, 0x08, 0x09, 0x9d, 0x7a, 0x11, 0xcc, 0x22, 0xbe, 0xf6, 0x47, 0xcb, 0xdc, 0x54, + 0x57, 0xb9, 0xa9, 0x3e, 0xe5, 0xa6, 0x7a, 0xbf, 0x31, 0x95, 0xd5, 0xc6, 0x54, 0x1e, 0x37, 0xa6, + 0x72, 0x09, 0xfd, 0x80, 0xcd, 0x6f, 0xa6, 0xd6, 0x8c, 0x44, 0x70, 0xc0, 0x5f, 0xe9, 0xfb, 0x18, + 0xb3, 0x5b, 0x92, 0x86, 0x72, 0x83, 0xd9, 0x2f, 0xb8, 0x28, 0x7e, 0x08, 0x76, 0x97, 0x60, 0x3a, + 0xad, 0x8a, 0x0f, 0xff, 0xe3, 0x39, 0x00, 0x00, 0xff, 0xff, 0x8b, 0xf1, 0x2b, 0xd2, 0x5a, 0x02, + 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -186,6 +211,34 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Erc20AddressIndexes) > 0 { + for iNdEx := len(m.Erc20AddressIndexes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Erc20AddressIndexes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.DenomIndexes) > 0 { + for iNdEx := len(m.DenomIndexes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DenomIndexes[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.TokenPairs) > 0 { for iNdEx := len(m.TokenPairs) - 1; iNdEx >= 0; iNdEx-- { { @@ -281,6 +334,18 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.DenomIndexes) > 0 { + for _, e := range m.DenomIndexes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Erc20AddressIndexes) > 0 { + for _, e := range m.Erc20AddressIndexes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -401,6 +466,74 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenomIndexes", 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.DenomIndexes = append(m.DenomIndexes, TokenPairDenomIndex{}) + if err := m.DenomIndexes[len(m.DenomIndexes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Erc20AddressIndexes", 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.Erc20AddressIndexes = append(m.Erc20AddressIndexes, TokenPairERC20AddressIndex{}) + if err := m.Erc20AddressIndexes[len(m.Erc20AddressIndexes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/erc20/types/genesis_test.go b/x/erc20/types/genesis_test.go index a3997232..1e505669 100644 --- a/x/erc20/types/genesis_test.go +++ b/x/erc20/types/genesis_test.go @@ -18,7 +18,7 @@ func TestGenesisTestSuite(t *testing.T) { } func (suite *GenesisTestSuite) TestValidateGenesis() { - newGen := NewGenesisState(DefaultParams(), []TokenPair{}) + newGen := NewGenesisState(DefaultParams(), []TokenPair{}, []TokenPairDenomIndex{}, []TokenPairERC20AddressIndex{}) testCases := []struct { name string diff --git a/x/erc20/types/keys.go b/x/erc20/types/keys.go index 65c4346a..8b141e28 100644 --- a/x/erc20/types/keys.go +++ b/x/erc20/types/keys.go @@ -27,13 +27,13 @@ func init() { // prefix bytes for the EVM persistent store const ( prefixTokenPair = iota + 1 - prefixTokenPairByERC20 + prefixTokenPairByERC20Address prefixTokenPairByDenom ) // KVStore key prefixes var ( - KeyPrefixTokenPair = []byte{prefixTokenPair} - KeyPrefixTokenPairByERC20 = []byte{prefixTokenPairByERC20} - KeyPrefixTokenPairByDenom = []byte{prefixTokenPairByDenom} + KeyPrefixTokenPair = []byte{prefixTokenPair} + KeyPrefixTokenPairByERC20Address = []byte{prefixTokenPairByERC20Address} + KeyPrefixTokenPairByDenom = []byte{prefixTokenPairByDenom} ) diff --git a/x/inflation/types/inflation.pb.go b/x/inflation/types/inflation.pb.go index 5431ba58..7c07d331 100644 --- a/x/inflation/types/inflation.pb.go +++ b/x/inflation/types/inflation.pb.go @@ -39,8 +39,10 @@ type InflationDistribution struct { // is // // to be allocated to the incentives module address // string usage_incentives = 2 [ - // (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - // (gogoproto.nullable) = false + // + // (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + // (gogoproto.nullable) = false + // // ]; // community_pool defines the proportion of the minted minted_denom that is to // be allocated to the community pool From a9bba117949fc6f7f8aed73b43154bc256004341 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Tue, 30 Jul 2024 10:51:18 +0900 Subject: [PATCH 6/7] chore: fix comments --- x/erc20/genesis.go | 4 ++-- x/erc20/genesis_test.go | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x/erc20/genesis.go b/x/erc20/genesis.go index 234ad285..63078de6 100644 --- a/x/erc20/genesis.go +++ b/x/erc20/genesis.go @@ -30,8 +30,8 @@ func InitGenesis( } // set indexes - // multiple contracts at the same denom can exist, - // but only one which is in indexes are valid. + // multiple token pairs should not be registered with the same denom, + // but if this happens, only the one in the index is valid. for _, idx := range data.DenomIndexes { id := idx.GetTokenPairId() k.SetTokenPairIdByDenom(ctx, idx.Denom, id) diff --git a/x/erc20/genesis_test.go b/x/erc20/genesis_test.go index 249ce7e8..41659e6c 100644 --- a/x/erc20/genesis_test.go +++ b/x/erc20/genesis_test.go @@ -24,6 +24,8 @@ import ( var ( uqstars = "utestdenom" + // The following test codes are to prove that multiple token pairs should not be registered + // with the same denom, but if this happens, only the one in the index is valid. // uqstars1 and uqstars2 have same denom // uqstars1 is deployed first. uqstars1 = types.TokenPair{ From 54cde68d8ddbcfae53571178db578722fb5a9544 Mon Sep 17 00:00:00 2001 From: "jason.song" Date: Tue, 30 Jul 2024 11:09:45 +0900 Subject: [PATCH 7/7] fix: revert chainId --- x/erc20/genesis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/erc20/genesis_test.go b/x/erc20/genesis_test.go index 41659e6c..bde91e22 100644 --- a/x/erc20/genesis_test.go +++ b/x/erc20/genesis_test.go @@ -104,7 +104,7 @@ func (suite *GenesisTestSuite) SetupTest() { suite.app = app.Setup(false, feemarkettypes.DefaultGenesisState()) suite.ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{ Height: 1, - ChainID: "test-chainid", + ChainID: "canto_9000-1", Time: time.Now().UTC(), ProposerAddress: consAddress.Bytes(),