-
Notifications
You must be signed in to change notification settings - Fork 585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
E2E: Interchain Account failed bank transfer over incentivised channel #2049
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -389,3 +389,165 @@ func (s *InterchainAccountsTestSuite) TestMsgSubmitTx_SuccessfulBankSend_Incenti | |
}) | ||
}) | ||
} | ||
|
||
func (s *InterchainAccountsTestSuite) TestMsgSubmitTx_FailedBankSend_Incentivized() { | ||
t := s.T() | ||
ctx := context.TODO() | ||
|
||
// setup relayers and connection-0 between two chains | ||
// channel-0 is a transfer channel but it will not be used in this test case | ||
relayer, _ := s.SetupChainsRelayerAndChannel(ctx) | ||
chainA, chainB := s.GetChains() | ||
|
||
var ( | ||
chainADenom = chainA.Config().Denom | ||
interchainAcc = "" | ||
testFee = testvalues.DefaultFee(chainADenom) | ||
) | ||
|
||
t.Run("relayer wallets recovered", func(t *testing.T) { | ||
err := s.RecoverRelayerWallets(ctx, relayer) | ||
s.Require().NoError(err) | ||
}) | ||
|
||
chainARelayerWallet, chainBRelayerWallet, err := s.GetRelayerWallets(relayer) | ||
t.Run("relayer wallets fetched", func(t *testing.T) { | ||
s.Require().NoError(err) | ||
}) | ||
|
||
s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") | ||
|
||
chainARelayerUser, chainBRelayerUser := s.GetRelayerUsers(ctx) | ||
relayerAStartingBalance, err := s.GetChainANativeBalance(ctx, chainARelayerUser) | ||
s.Require().NoError(err) | ||
t.Logf("relayer A user starting with balance: %d", relayerAStartingBalance) | ||
|
||
controllerAccount := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) | ||
chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) | ||
|
||
t.Run("register interchain account", func(t *testing.T) { | ||
version := "" // allow app to handle the version as appropriate. | ||
msgRegisterAccount := intertxtypes.NewMsgRegisterAccount(controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID, version) | ||
err := s.RegisterInterchainAccount(ctx, chainA, controllerAccount, msgRegisterAccount) | ||
s.Require().NoError(err) | ||
}) | ||
|
||
t.Run("start relayer", func(t *testing.T) { | ||
s.StartRelayer(relayer) | ||
}) | ||
|
||
var channelOutput ibc.ChannelOutput | ||
t.Run("verify interchain account", func(t *testing.T) { | ||
var err error | ||
interchainAcc, err = s.QueryInterchainAccount(ctx, chainA, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), ibctesting.FirstConnectionID) | ||
s.Require().NoError(err) | ||
s.Require().NotZero(len(interchainAcc)) | ||
|
||
channels, err := relayer.GetChannels(ctx, s.GetRelayerExecReporter(), chainA.Config().ChainID) | ||
s.Require().NoError(err) | ||
s.Require().Equal(len(channels), 2) | ||
|
||
// interchain accounts channel at index: 0 | ||
channelOutput = channels[0] | ||
|
||
s.Require().NoError(test.WaitForBlocks(ctx, 2, chainA, chainB)) | ||
}) | ||
|
||
t.Run("execute interchain account bank send through controller", func(t *testing.T) { | ||
|
||
t.Run("register counterparty payee", func(t *testing.T) { | ||
resp, err := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelOutput.Counterparty.PortID, channelOutput.Counterparty.ChannelID, chainBRelayerWallet.Address, chainARelayerWallet.Address) | ||
s.Require().NoError(err) | ||
s.AssertValidTxResponse(resp) | ||
}) | ||
|
||
t.Run("verify counterparty payee", func(t *testing.T) { | ||
address, err := s.QueryCounterPartyPayee(ctx, chainB, chainBRelayerWallet.Address, channelOutput.Counterparty.ChannelID) | ||
s.Require().NoError(err) | ||
s.Require().Equal(chainARelayerWallet.Address, address) | ||
}) | ||
|
||
t.Run("no incentivized packets", func(t *testing.T) { | ||
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelOutput.PortID, channelOutput.ChannelID) | ||
s.Require().NoError(err) | ||
s.Require().Empty(packets) | ||
}) | ||
|
||
t.Run("stop relayer", func(t *testing.T) { | ||
err := relayer.StopRelayer(ctx, s.GetRelayerExecReporter()) | ||
s.Require().NoError(err) | ||
}) | ||
|
||
t.Run("broadcast incentivized MsgSubmitTx", func(t *testing.T) { | ||
msgPayPacketFee := &feetypes.MsgPayPacketFee{ | ||
Fee: testvalues.DefaultFee(chainADenom), | ||
SourcePortId: channelOutput.PortID, | ||
SourceChannelId: channelOutput.ChannelID, | ||
Signer: controllerAccount.Bech32Address(chainA.Config().Bech32Prefix), | ||
} | ||
|
||
msgSend := &banktypes.MsgSend{ | ||
FromAddress: interchainAcc, | ||
ToAddress: chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), | ||
Amount: sdk.NewCoins(testvalues.DefaultTransferAmount(chainB.Config().Denom)), | ||
} | ||
|
||
msgSubmitTx, err := intertxtypes.NewMsgSubmitTx(msgSend, ibctesting.FirstConnectionID, controllerAccount.Bech32Address(chainA.Config().Bech32Prefix)) | ||
s.Require().NoError(err) | ||
|
||
resp, err := s.BroadcastMessages(ctx, chainA, controllerAccount, msgPayPacketFee, msgSubmitTx) | ||
s.AssertValidTxResponse(resp) | ||
s.Require().NoError(err) | ||
|
||
s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB)) | ||
}) | ||
|
||
t.Run("there should be incentivized packets", func(t *testing.T) { | ||
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelOutput.PortID, channelOutput.ChannelID) | ||
s.Require().NoError(err) | ||
s.Require().Len(packets, 1) | ||
actualFee := packets[0].PacketFees[0].Fee | ||
|
||
s.Require().True(actualFee.RecvFee.IsEqual(testFee.RecvFee)) | ||
s.Require().True(actualFee.AckFee.IsEqual(testFee.AckFee)) | ||
s.Require().True(actualFee.TimeoutFee.IsEqual(testFee.TimeoutFee)) | ||
}) | ||
|
||
t.Run("start relayer", func(t *testing.T) { | ||
s.StartRelayer(relayer) | ||
}) | ||
|
||
t.Run("packets are relayed", func(t *testing.T) { | ||
packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelOutput.PortID, channelOutput.ChannelID) | ||
s.Require().NoError(err) | ||
s.Require().Empty(packets) | ||
}) | ||
|
||
t.Run("verify interchain account did not send tokens", func(t *testing.T) { | ||
balance, err := chainB.GetBalance(ctx, chainBAccount.Bech32Address(chainB.Config().Bech32Prefix), chainB.Config().Denom) | ||
s.Require().NoError(err) | ||
|
||
_, err = chainB.GetBalance(ctx, interchainAcc, chainB.Config().Denom) | ||
s.Require().NoError(err) | ||
|
||
expected := testvalues.StartingTokenAmount | ||
s.Require().Equal(expected, balance, "tokens should not have been sent as interchain account was not funded") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the interchain account is not funded, shouldn't the balance be zero? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is just because all of the accounts are initialized like this chainBAccount := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) It is not possible to initialize an account with a balance of |
||
}) | ||
|
||
t.Run("timeout fee is refunded", func(t *testing.T) { | ||
actualBalance, err := s.GetChainANativeBalance(ctx, controllerAccount) | ||
s.Require().NoError(err) | ||
|
||
expected := testvalues.StartingTokenAmount - testFee.AckFee.AmountOf(chainADenom).Int64() - testFee.RecvFee.AmountOf(chainADenom).Int64() | ||
s.Require().Equal(expected, actualBalance) | ||
}) | ||
|
||
t.Run("relayerA is paid ack and recv fee", func(t *testing.T) { | ||
actualBalance, err := s.GetChainANativeBalance(ctx, chainARelayerUser) | ||
s.Require().NoError(err) | ||
|
||
expected := relayerAStartingBalance + testFee.AckFee.AmountOf(chainADenom).Int64() + testFee.RecvFee.AmountOf(chainADenom).Int64() | ||
s.Require().Equal(expected, actualBalance) | ||
}) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you know that the ICA channel is at index 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good question, @damiannolan do you recall why it is at index 0 rather than 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally I would've expected it to be at index 1 (as the transfer channel is created first), but after trying that and having a failing test, I quickly switched it around and had no failures after.
It's not ideal and I haven't dug into it much more than taking a look at this function https://github.com/strangelove-ventures/ibctest/blob/main/relayer/rly/cosmos_relayer.go#L247
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just looking into it here, it looks like this is output of that variable
The order seems unexpected but the channel we care about is definitely first.