From 214e4a3e83de6875f529eaedb54c30b2be6764de Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 27 Jul 2022 11:03:23 +0100 Subject: [PATCH] E2E Test: TestMsgPayPacketFeeSingleSenderTimesOut (#1751) --- e2e/fee_middleware_test.go | 122 ++++++++++++++++++++++++++++++++++++- e2e/testvalues/values.go | 8 +++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/e2e/fee_middleware_test.go b/e2e/fee_middleware_test.go index 4cc4ea14332..e6207f5d729 100644 --- a/e2e/fee_middleware_test.go +++ b/e2e/fee_middleware_test.go @@ -3,6 +3,7 @@ package e2e import ( "context" "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/strangelove-ventures/ibctest/broadcast" @@ -79,7 +80,7 @@ func (s *FeeMiddlewareTestSuite) QueryIncentivizedPacketsForChannel( return res.IncentivizedPackets, err } -func (s *FeeMiddlewareTestSuite) TestMsgPayPacketFeeAsyncSingleSender() { +func (s *FeeMiddlewareTestSuite) TestMsgPayPacketFee_AsyncSingleSender_Succeeds() { t := s.T() ctx := context.TODO() @@ -309,6 +310,125 @@ func (s *FeeMiddlewareTestSuite) TestMultiMsg_MsgPayPacketFeeSingleSender() { }) } +func (s *FeeMiddlewareTestSuite) TestMsgPayPacketFee_SingleSender_TimesOut() { + t := s.T() + ctx := context.TODO() + + relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, feeMiddlewareChannelOptions()) + chainA, chainB := s.GetChains() + + var ( + chainADenom = chainA.Config().Denom + testFee = testvalues.DefaultFee(chainADenom) + chainATx ibc.Tx + payPacketFeeTxResp sdk.TxResponse + ) + + chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + + t.Run("relayer wallets recovered", func(t *testing.T) { + s.Require().NoError(s.RecoverRelayerWallets(ctx, relayer)) + }) + + chainARelayerWallet, chainBRelayerWallet, err := s.GetRelayerWallets(relayer) + t.Run("relayer wallets fetched", func(t *testing.T) { + s.Require().NoError(err) + }) + + _, chainBRelayerUser := s.GetRelayerUsers(ctx) + + t.Run("register counter party payee", func(t *testing.T) { + resp, err := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, chainBRelayerWallet.Address, chainARelayerWallet.Address) + s.Require().NoError(err) + s.AssertValidTxResponse(resp) + }) + + t.Run("verify counter party payee", func(t *testing.T) { + address, err := s.QueryCounterPartyPayee(ctx, chainB, chainBRelayerWallet.Address, channelA.Counterparty.ChannelID) + s.Require().NoError(err) + s.Require().Equal(chainARelayerWallet.Address, address) + }) + + chainBWalletAmount := ibc.WalletAmount{ + Address: chainBWallet.Bech32Address(chainB.Config().Bech32Prefix), // destination address + Denom: chainA.Config().Denom, + Amount: testvalues.IBCTransferAmount, + } + + t.Run("Send IBC transfer", func(t *testing.T) { + chainATx, err = chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName, chainBWalletAmount, testvalues.ImmediatelyTimeout()) + s.Require().NoError(err) + s.Require().NoError(chainATx.Validate(), "source ibc transfer tx is invalid") + time.Sleep(time.Nanosecond * 1) // want it to timeout immediately + }) + + t.Run("tokens are escrowed", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount - chainBWalletAmount.Amount + s.Require().Equal(expected, actualBalance) + }) + + t.Run("pay packet fee", func(t *testing.T) { + + packetId := channeltypes.NewPacketId(channelA.PortID, channelA.ChannelID, 1) + packetFee := feetypes.NewPacketFee(testFee, chainAWallet.Bech32Address(chainA.Config().Bech32Prefix), nil) + + t.Run("no incentivized packets", func(t *testing.T) { + packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Empty(packets) + }) + + t.Run("should succeed", func(t *testing.T) { + payPacketFeeTxResp, err = s.PayPacketFeeAsync(ctx, chainA, chainAWallet, packetId, packetFee) + s.Require().NoError(err) + s.AssertValidTxResponse(payPacketFeeTxResp) + }) + + t.Run("there should be incentivized packets", func(t *testing.T) { + packets, err := s.QueryIncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.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("balance should be lowered by sum of recv ack and timeout", func(t *testing.T) { + // The balance should be lowered by the sum of the recv, ack and timeout fees. + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount - chainBWalletAmount.Amount - testFee.Total().AmountOf(chainADenom).Int64() + s.Require().Equal(expected, actualBalance) + }) + + }) + + 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, channelA.PortID, channelA.ChannelID) + s.Require().NoError(err) + s.Require().Empty(packets) + }) + + t.Run("recv and ack should be refunded", func(t *testing.T) { + actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) + s.Require().NoError(err) + + expected := testvalues.StartingTokenAmount - testFee.TimeoutFee.AmountOf(chainADenom).Int64() + s.Require().Equal(expected, actualBalance) + }) +} + // feeMiddlewareChannelOptions configures both of the chains to have fee middleware enabled. func feeMiddlewareChannelOptions() func(options *ibc.CreateChannelOptions) { return func(opts *ibc.CreateChannelOptions) { diff --git a/e2e/testvalues/values.go b/e2e/testvalues/values.go index 7b0822c9f1c..ce11c09bc98 100644 --- a/e2e/testvalues/values.go +++ b/e2e/testvalues/values.go @@ -2,6 +2,7 @@ package testvalues import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/strangelove-ventures/ibctest/ibc" feetypes "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types" ) @@ -11,6 +12,13 @@ const ( IBCTransferAmount int64 = 10_000 ) +// ImmediatelyTimeout returns an ibc.IBCTimeout which will cause an IBC transfer to timeout immediately. +func ImmediatelyTimeout() *ibc.IBCTimeout { + return &ibc.IBCTimeout{ + NanoSeconds: 1, + } +} + func DefaultFee(denom string) feetypes.Fee { return feetypes.Fee{ RecvFee: sdk.NewCoins(sdk.NewCoin(denom, sdk.NewInt(50))),