diff --git a/x/assets/types/genesis.go b/x/assets/types/genesis.go index a081eed61..415517439 100644 --- a/x/assets/types/genesis.go +++ b/x/assets/types/genesis.go @@ -113,9 +113,9 @@ func (gs GenesisState) Validate() error { for _, depositByStaker := range gs.Deposits { stakerID := depositByStaker.StakerID // validate the stakerID - var id uint64 + var stakerClientChainID uint64 var err error - if _, id, err = ValidateID(stakerID, true); err != nil { + if _, stakerClientChainID, err = ValidateID(stakerID, true); err != nil { return errorsmod.Wrapf( ErrInvalidGenesisData, "invalid stakerID: %s", @@ -123,11 +123,11 @@ func (gs GenesisState) Validate() error { ) } // check that the chain is registered - if _, ok := lzIDs[id]; !ok { + if _, ok := lzIDs[stakerClientChainID]; !ok { return errorsmod.Wrapf( ErrInvalidGenesisData, "unknown LayerZeroChainID for staker %s: %d", - stakerID, id, + stakerID, stakerClientChainID, ) } // check that it is not a duplicate @@ -153,6 +153,18 @@ func (gs GenesisState) Validate() error { stakerID, assetID, ) } + // #nosec G703 // if it's invalid, we will not reach here. + _, assetClientChainID, _ := ParseID(assetID) + if assetClientChainID != stakerClientChainID { + // we can reach here if there are multiple chains + // and it tries to deposit assets from one chain + // under a staker from another chain. + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "mismatched client chain IDs for staker %s and asset %s", + stakerID, assetID, + ) + } // check that it is not a duplicate if _, ok := tokensForStaker[assetID]; ok { return errorsmod.Wrapf( diff --git a/x/assets/types/genesis_test.go b/x/assets/types/genesis_test.go index 621112a33..eb7d3741a 100644 --- a/x/assets/types/genesis_test.go +++ b/x/assets/types/genesis_test.go @@ -1,7 +1,6 @@ package types_test import ( - "fmt" "strings" "testing" @@ -308,6 +307,52 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { gs.Deposits[0].Deposits[0].AssetID = assetID }, }, + { + name: "invalid genesis due to different chain ids for asset and staker", + genState: &types.GenesisState{ + Params: types.DefaultParams(), + ClientChains: []types.ClientChainInfo{ + ethClientChain, ethClientChain, + }, + Tokens: []types.StakingAssetInfo{ + stakingInfo, stakingInfo, + }, + Deposits: []types.DepositsByStaker{genesisDeposit, genesisDeposit}, + }, + expPass: false, + malleate: func(gs *types.GenesisState) { + // new chain with different layer zero chain id + gs.ClientChains[1].LayerZeroChainID += 1 + // new asset (old asset is a pointer so can't alter that) + tokenAddress := utiltx.GenerateAddress().String() + usdcClientChainAsset := types.AssetInfo{ + Name: "Circle USD", + Symbol: "USDC", + Address: tokenAddress, + Decimals: 18, + LayerZeroChainID: ethClientChain.LayerZeroChainID + 1, + MetaInfo: "Circle USD token", + TotalSupply: math.NewInt(500000000), + } + stakingInfo := types.StakingAssetInfo{ + AssetBasicInfo: &usdcClientChainAsset, + StakingTotalAmount: math.NewInt(0), + } + gs.Tokens[1] = stakingInfo + stakerID, _ := types.GetStakeIDAndAssetIDFromStr( + usdtClientChainAsset.LayerZeroChainID+1, + ethAddress.String(), usdtClientChainAsset.Address, + ) + // change stakerID to be that of the second chain + gs.Deposits[1].StakerID = stakerID + // but keep the assetID the same + }, + unmalleate: func(gs *types.GenesisState) { + gs.ClientChains[1].LayerZeroChainID -= 1 + gs.Tokens[1].AssetBasicInfo.LayerZeroChainID -= 1 + gs.Deposits[1].StakerID = stakerID + }, + }, { name: "invalid genesis due to duplicate asset id for staker", genState: &types.GenesisState{ @@ -485,6 +530,6 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { if tc.unmalleate != nil { tc.unmalleate(tc.genState) } - fmt.Println(tc.name, ",", err) + // fmt.Println(tc.name, ",", err) } }