From b8bc1a8c2a61290e679a6920eabf578d013fc296 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Fri, 12 Nov 2021 13:45:45 +0100 Subject: [PATCH] test: relay tests for TrySendTx/OnRecvPacket (#531) * adding various sdk.Msg type tests and cleaning up relay_test.go * cleaning up tests to make consistent * adding missing godoc for OnRecvPacket * adding ica test for transfertypes.MsgTranfer * updating hardcoded strings to use sdk.DefaultBondDenom * Update modules/apps/27-interchain-accounts/keeper/relay_test.go Co-authored-by: Sean King * removing staking test for insufficient funds Co-authored-by: Sean King --- .../27-interchain-accounts/keeper/relay.go | 1 + .../keeper/relay_test.go | 500 ++++++++++++++---- 2 files changed, 398 insertions(+), 103 deletions(-) diff --git a/modules/apps/27-interchain-accounts/keeper/relay.go b/modules/apps/27-interchain-accounts/keeper/relay.go index 681433e03ee..9b5eec6e2d8 100644 --- a/modules/apps/27-interchain-accounts/keeper/relay.go +++ b/modules/apps/27-interchain-accounts/keeper/relay.go @@ -125,6 +125,7 @@ func (k Keeper) executeMsg(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { return handler(ctx, msg) } +// OnRecvPacket handles a given interchain accounts packet on a destination host chain func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet) error { var data types.InterchainAccountPacketData diff --git a/modules/apps/27-interchain-accounts/keeper/relay_test.go b/modules/apps/27-interchain-accounts/keeper/relay_test.go index bcc1ebccf27..e7741a8903c 100644 --- a/modules/apps/27-interchain-accounts/keeper/relay_test.go +++ b/modules/apps/27-interchain-accounts/keeper/relay_test.go @@ -1,13 +1,18 @@ package keeper_test import ( - "fmt" + "time" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/ibc-go/v2/modules/apps/27-interchain-accounts/types" + transfertypes "github.com/cosmos/ibc-go/v2/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v2/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v2/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v2/modules/core/24-host" @@ -16,95 +21,127 @@ import ( func (suite *KeeperTestSuite) TestTrySendTx() { var ( - path *ibctesting.Path - icaPacketData types.InterchainAccountPacketData - portID string - chanCap *capabilitytypes.Capability + path *ibctesting.Path + packetData types.InterchainAccountPacketData + chanCap *capabilitytypes.Capability ) testCases := []struct { - name string + msg string malleate func() expPass bool }{ { - "success", func() { - }, true, + "success", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msg := &banktypes.MsgSend{ + FromAddress: interchainAccountAddr, + ToAddress: suite.chainB.SenderAccount.GetAddress().String(), + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + } + + data, err := types.SerializeCosmosTx(suite.chainB.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + packetData = types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + }, + true, }, { - "success with multiple sdk.Msg", func() { - amount, _ := sdk.ParseCoinsNormalized("100stake") - interchainAccountAddr, _ := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) - msg1 := &banktypes.MsgSend{FromAddress: interchainAccountAddr, ToAddress: suite.chainB.SenderAccount.GetAddress().String(), Amount: amount} - msg2 := &banktypes.MsgSend{FromAddress: interchainAccountAddr, ToAddress: suite.chainB.SenderAccount.GetAddress().String(), Amount: amount} - data, err := types.SerializeCosmosTx(suite.chainB.GetSimApp().AppCodec(), []sdk.Msg{msg1, msg2}) + "success with multiple sdk.Msg", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msgsBankSend := []sdk.Msg{ + &banktypes.MsgSend{ + FromAddress: interchainAccountAddr, + ToAddress: suite.chainB.SenderAccount.GetAddress().String(), + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + }, + &banktypes.MsgSend{ + FromAddress: interchainAccountAddr, + ToAddress: suite.chainB.SenderAccount.GetAddress().String(), + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + }, + } + + data, err := types.SerializeCosmosTx(suite.chainB.GetSimApp().AppCodec(), msgsBankSend) suite.Require().NoError(err) - icaPacketData.Data = data - }, true, + + packetData = types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + }, + true, }, { - "data is nil", func() { - icaPacketData.Data = nil - }, false, + "data is nil", + func() { + packetData = types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: nil, + } + }, + false, }, { - "active channel not found", func() { - portID = "incorrect portID" - }, false, + "active channel not found", + func() { + path.EndpointA.ChannelConfig.PortID = "invalid-port-id" + }, + false, }, { - "channel does not exist", func() { - suite.chainA.GetSimApp().ICAKeeper.SetActiveChannelID(suite.chainA.GetContext(), portID, "channel-100") - }, false, + "channel does not exist", + func() { + suite.chainA.GetSimApp().ICAKeeper.SetActiveChannelID(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, "channel-100") + }, + false, }, { - "SendPacket fails - channel closed", func() { + "sendPacket fails - channel closed", + func() { err := path.EndpointA.SetChannelClosed() suite.Require().NoError(err) - }, false, + }, + false, }, { - "invalid channel capability provided", func() { + "invalid channel capability provided", + func() { chanCap = nil - }, false, + }, + false, }, } for _, tc := range testCases { tc := tc - suite.Run(tc.name, func() { + suite.Run(tc.msg, func() { suite.SetupTest() // reset + path = NewICAPath(suite.chainA, suite.chainB) suite.coordinator.SetupConnections(path) err := suite.SetupICAPath(path, TestOwnerAddress) suite.Require().NoError(err) - // default setup - portID = path.EndpointA.ChannelConfig.PortID - - amount, _ := sdk.ParseCoinsNormalized("100stake") - interchainAccountAddr, _ := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) - - msg := &banktypes.MsgSend{FromAddress: interchainAccountAddr, ToAddress: suite.chainB.SenderAccount.GetAddress().String(), Amount: amount} - data, err := types.SerializeCosmosTx(suite.chainB.GetSimApp().AppCodec(), []sdk.Msg{msg}) - suite.Require().NoError(err) - - // default packet data, must be modified in malleate for test cases expected to fail - icaPacketData = types.InterchainAccountPacketData{ - Type: types.EXECUTE_TX, - Data: data, - Memo: "memo", - } - var ok bool - chanCap, ok = suite.chainA.GetSimApp().ScopedICAMockKeeper.GetCapability(path.EndpointA.Chain.GetContext(), host.ChannelCapabilityPath(portID, path.EndpointA.ChannelID)) + chanCap, ok = suite.chainA.GetSimApp().ScopedICAMockKeeper.GetCapability(path.EndpointA.Chain.GetContext(), host.ChannelCapabilityPath(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) suite.Require().True(ok) - tc.malleate() + tc.malleate() // malleate mutates test data - _, err = suite.chainA.GetSimApp().ICAKeeper.TrySendTx(suite.chainA.GetContext(), chanCap, portID, icaPacketData) + _, err = suite.chainA.GetSimApp().ICAKeeper.TrySendTx(suite.chainA.GetContext(), chanCap, path.EndpointA.ChannelConfig.PortID, packetData) if tc.expPass { suite.Require().NoError(err) @@ -118,9 +155,7 @@ func (suite *KeeperTestSuite) TestTrySendTx() { func (suite *KeeperTestSuite) TestOnRecvPacket() { var ( path *ibctesting.Path - msg sdk.Msg packetData []byte - sourcePort string ) testCases := []struct { @@ -129,105 +164,336 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { expPass bool }{ { - "Interchain account successfully executes banktypes.MsgSend", func() { - // build MsgSend - amount, _ := sdk.ParseCoinsNormalized("100stake") - interchainAccountAddr, _ := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) - msg = &banktypes.MsgSend{FromAddress: interchainAccountAddr, ToAddress: suite.chainB.SenderAccount.GetAddress().String(), Amount: amount} - // build packet data - data, err := types.SerializeCosmosTx(suite.chainA.Codec, []sdk.Msg{msg}) + "interchain account successfully executes banktypes.MsgSend", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msg := &banktypes.MsgSend{ + FromAddress: interchainAccountAddr, + ToAddress: suite.chainB.SenderAccount.GetAddress().String(), + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) suite.Require().NoError(err) icaPacketData := types.InterchainAccountPacketData{ Type: types.EXECUTE_TX, Data: data, } + packetData = icaPacketData.GetBytes() - }, true, + }, + true, }, { - "Cannot deserialize packet data messages", func() { - data := []byte("invalid packet data") + "interchain account successfully executes stakingtypes.MsgDelegate", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + validatorAddr := (sdk.ValAddress)(suite.chainB.Vals.Validators[0].Address) + msg := &stakingtypes.MsgDelegate{ + DelegatorAddress: interchainAccountAddr, + ValidatorAddress: validatorAddr.String(), + Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5000)), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) icaPacketData := types.InterchainAccountPacketData{ Type: types.EXECUTE_TX, Data: data, } + packetData = icaPacketData.GetBytes() - }, false, + }, + true, }, { - "Invalid packet type", func() { - // build packet data - data, err := types.SerializeCosmosTx(suite.chainA.Codec, []sdk.Msg{&banktypes.MsgSend{}}) + "interchain account successfully executes stakingtypes.MsgDelegate and stakingtypes.MsgUndelegate sequentially", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + validatorAddr := (sdk.ValAddress)(suite.chainB.Vals.Validators[0].Address) + msgDelegate := &stakingtypes.MsgDelegate{ + DelegatorAddress: interchainAccountAddr, + ValidatorAddress: validatorAddr.String(), + Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5000)), + } + + msgUndelegate := &stakingtypes.MsgUndelegate{ + DelegatorAddress: interchainAccountAddr, + ValidatorAddress: validatorAddr.String(), + Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5000)), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msgDelegate, msgUndelegate}) suite.Require().NoError(err) - // Type here is an ENUM - // Valid type is types.EXECUTE_TX icaPacketData := types.InterchainAccountPacketData{ - Type: 100, + Type: types.EXECUTE_TX, Data: data, } + packetData = icaPacketData.GetBytes() - }, false, + }, + true, }, { - "Cannot unmarshal interchain account packet data into types.InterchainAccountPacketData", func() { + "interchain account successfully executes govtypes.MsgSubmitProposal", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + testProposal := &govtypes.TextProposal{ + Title: "IBC Gov Proposal", + Description: "tokens for all!", + } + + any, err := codectypes.NewAnyWithValue(testProposal) + suite.Require().NoError(err) + + msg := &govtypes.MsgSubmitProposal{ + Content: any, + InitialDeposit: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5000))), + Proposer: interchainAccountAddr, + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + true, + }, + { + "interchain account successfully executes govtypes.MsgVote", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + // Populate the gov keeper in advance with an active proposal + testProposal := &govtypes.TextProposal{ + Title: "IBC Gov Proposal", + Description: "tokens for all!", + } + + proposal, err := govtypes.NewProposal(testProposal, govtypes.DefaultStartingProposalID, time.Now(), time.Now().Add(time.Hour)) + suite.Require().NoError(err) + + suite.chainB.GetSimApp().GovKeeper.SetProposal(suite.chainB.GetContext(), proposal) + suite.chainB.GetSimApp().GovKeeper.ActivateVotingPeriod(suite.chainB.GetContext(), proposal) + + msg := &govtypes.MsgVote{ + ProposalId: govtypes.DefaultStartingProposalID, + Voter: interchainAccountAddr, + Option: govtypes.OptionYes, + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + true, + }, + { + "interchain account successfully executes disttypes.MsgFundCommunityPool", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msg := &disttypes.MsgFundCommunityPool{ + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(5000))), + Depositor: interchainAccountAddr, + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + true, + }, + { + "interchain account successfully executes disttypes.MsgSetWithdrawAddress", + func() { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msg := &disttypes.MsgSetWithdrawAddress{ + DelegatorAddress: interchainAccountAddr, + WithdrawAddress: suite.chainB.SenderAccount.GetAddress().String(), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + true, + }, + { + "interchain account successfully executes transfertypes.MsgTransfer", + func() { + transferPath := ibctesting.NewPath(suite.chainB, suite.chainC) + transferPath.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort + transferPath.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort + + suite.coordinator.Setup(transferPath) + + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) + suite.Require().True(found) + + msg := &transfertypes.MsgTransfer{ + SourcePort: transferPath.EndpointA.ChannelConfig.PortID, + SourceChannel: transferPath.EndpointA.ChannelID, + Token: sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), + Sender: interchainAccountAddr, + Receiver: suite.chainA.SenderAccount.GetAddress().String(), + TimeoutHeight: clienttypes.NewHeight(0, 100), + TimeoutTimestamp: uint64(0), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + true, + }, + { + "cannot unmarshal interchain account packet data", + func() { packetData = []byte{} - }, false, + }, + false, + }, + { + "cannot deserialize interchain account packet data messages", + func() { + data := []byte("invalid packet data") + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + false, }, { - "Unauthorised: Interchain account not found for given source portID", func() { - sourcePort = "invalid-port-id" - }, false, + "invalid packet type - UNSPECIFIED", + func() { + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{&banktypes.MsgSend{}}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.UNSPECIFIED, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + false, + }, + { + "unauthorised: interchain account not found for controller port ID", + func() { + path.EndpointA.ChannelConfig.PortID = "invalid-port-id" + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{&banktypes.MsgSend{}}) + suite.Require().NoError(err) + + icaPacketData := types.InterchainAccountPacketData{ + Type: types.EXECUTE_TX, + Data: data, + } + + packetData = icaPacketData.GetBytes() + }, + false, }, { - "Unauthorised: Signer of message is not the interchain account associated with sourcePortID", func() { - // build MsgSend - amount, _ := sdk.ParseCoinsNormalized("100stake") - // Incorrect FromAddress - msg = &banktypes.MsgSend{FromAddress: suite.chainB.SenderAccount.GetAddress().String(), ToAddress: suite.chainB.SenderAccount.GetAddress().String(), Amount: amount} - // build packet data - data, err := types.SerializeCosmosTx(suite.chainA.Codec, []sdk.Msg{msg}) + "unauthorised: signer address is not the interchain account associated with the controller portID", + func() { + msg := &banktypes.MsgSend{ + FromAddress: suite.chainB.SenderAccount.GetAddress().String(), // unexpected signer + ToAddress: suite.chainB.SenderAccount.GetAddress().String(), + Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + } + + data, err := types.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []sdk.Msg{msg}) suite.Require().NoError(err) + icaPacketData := types.InterchainAccountPacketData{ Type: types.EXECUTE_TX, Data: data, } + packetData = icaPacketData.GetBytes() - }, false, + }, + false, }, } for _, tc := range testCases { tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.Run(tc.msg, func() { suite.SetupTest() // reset path = NewICAPath(suite.chainA, suite.chainB) suite.coordinator.SetupConnections(path) - err := suite.SetupICAPath(path, TestOwnerAddress) - suite.Require().NoError(err) - // send 100stake to interchain account wallet - amount, _ := sdk.ParseCoinsNormalized("100stake") - interchainAccountAddr, _ := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID) - bankMsg := &banktypes.MsgSend{FromAddress: suite.chainB.SenderAccount.GetAddress().String(), ToAddress: interchainAccountAddr, Amount: amount} - - _, err = suite.chainB.SendMsgs(bankMsg) + err := suite.SetupICAPath(path, TestOwnerAddress) suite.Require().NoError(err) - // valid source port - sourcePort = path.EndpointA.ChannelConfig.PortID + suite.fundICAWallet(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10000)))) - // malleate packetData for test cases - tc.malleate() + tc.malleate() // malleate mutates test data - seq := uint64(1) - packet := channeltypes.NewPacket(packetData, seq, sourcePort, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0) + packet := channeltypes.NewPacket( + packetData, + suite.chainA.SenderAccount.GetSequence(), + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, + path.EndpointB.ChannelID, + clienttypes.NewHeight(0, 100), + 0, + ) - // Pass it in here err = suite.chainB.GetSimApp().ICAKeeper.OnRecvPacket(suite.chainB.GetContext(), packet) if tc.expPass { @@ -245,18 +511,21 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { ) testCases := []struct { - name string + msg string malleate func() expPass bool }{ { - "success", func() {}, true, + "success", + func() {}, + true, }, } for _, tc := range testCases { - suite.Run(tc.name, func() { + suite.Run(tc.msg, func() { suite.SetupTest() // reset + path = NewICAPath(suite.chainA, suite.chainB) suite.coordinator.SetupConnections(path) @@ -265,7 +534,17 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { tc.malleate() // malleate mutates test data - packet := channeltypes.NewPacket([]byte{}, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 100), 0) + packet := channeltypes.NewPacket( + []byte{}, + 1, + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, + path.EndpointB.ChannelID, + clienttypes.NewHeight(0, 100), + 0, + ) + err = suite.chainA.GetSimApp().ICAKeeper.OnTimeoutPacket(suite.chainA.GetContext(), packet) activeChannelID, found := suite.chainA.GetSimApp().ICAKeeper.GetActiveChannelID(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) @@ -280,3 +559,18 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { }) } } + +func (suite *KeeperTestSuite) fundICAWallet(ctx sdk.Context, portID string, amount sdk.Coins) { + interchainAccountAddr, found := suite.chainB.GetSimApp().ICAKeeper.GetInterchainAccountAddress(ctx, portID) + suite.Require().True(found) + + msgBankSend := &banktypes.MsgSend{ + FromAddress: suite.chainB.SenderAccount.GetAddress().String(), + ToAddress: interchainAccountAddr, + Amount: amount, + } + + res, err := suite.chainB.SendMsgs(msgBankSend) + suite.Require().NotEmpty(res) + suite.Require().NoError(err) +}