github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/29-fee/keeper/msg_server_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  
     6  	ibcmock "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/mock"
     7  
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/29-fee/types"
    10  	transfertypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types"
    11  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    12  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    13  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    14  )
    15  
    16  func (suite *KeeperTestSuite) TestRegisterPayee() {
    17  	var msg *types.MsgRegisterPayee
    18  
    19  	testCases := []struct {
    20  		name     string
    21  		expPass  bool
    22  		malleate func()
    23  	}{
    24  		{
    25  			"success",
    26  			true,
    27  			func() {},
    28  		},
    29  		{
    30  			"channel does not exist",
    31  			false,
    32  			func() {
    33  				msg.ChannelId = "channel-100"
    34  			},
    35  		},
    36  		{
    37  			"channel is not fee enabled",
    38  			false,
    39  			func() {
    40  				suite.chainA.GetSimApp().IBCFeeKeeper.DeleteFeeEnabled(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)
    41  			},
    42  		},
    43  		{
    44  			"given payee is not an sdk address",
    45  			false,
    46  			func() {
    47  				msg.Payee = "invalid-addr"
    48  			},
    49  		},
    50  		{
    51  			"payee is a blocked address",
    52  			false,
    53  			func() {
    54  				msg.Payee = suite.chainA.GetSimApp().SupplyKeeper.GetModuleAddress(transfertypes.ModuleName).String()
    55  			},
    56  		},
    57  	}
    58  
    59  	for _, tc := range testCases {
    60  		suite.SetupTest()
    61  		suite.coordinator.Setup(suite.path)
    62  
    63  		msg = types.NewMsgRegisterPayee(
    64  			suite.path.EndpointA.ChannelConfig.PortID,
    65  			suite.path.EndpointA.ChannelID,
    66  			suite.chainA.SenderAccounts()[0].SenderAccount.GetAddress().String(),
    67  			suite.chainA.SenderAccounts()[1].SenderAccount.GetAddress().String(),
    68  		)
    69  
    70  		tc.malleate()
    71  
    72  		res, err := suite.chainA.GetSimApp().IBCFeeKeeper.RegisterPayee(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
    73  
    74  		if tc.expPass {
    75  			suite.Require().NoError(err)
    76  			suite.Require().NotNil(res)
    77  
    78  			payeeAddr, found := suite.chainA.GetSimApp().IBCFeeKeeper.GetPayeeAddress(
    79  				suite.chainA.GetContext(),
    80  				suite.chainA.SenderAccounts()[0].SenderAccount.GetAddress().String(),
    81  				suite.path.EndpointA.ChannelID,
    82  			)
    83  
    84  			suite.Require().True(found)
    85  			suite.Require().Equal(suite.chainA.SenderAccounts()[1].SenderAccount.GetAddress().String(), payeeAddr)
    86  		} else {
    87  			suite.Require().Error(err)
    88  		}
    89  	}
    90  }
    91  
    92  func (suite *KeeperTestSuite) TestRegisterCounterpartyPayee() {
    93  	var (
    94  		msg                  *types.MsgRegisterCounterpartyPayee
    95  		expCounterpartyPayee string
    96  	)
    97  
    98  	testCases := []struct {
    99  		name     string
   100  		expPass  bool
   101  		malleate func()
   102  	}{
   103  		{
   104  			"success",
   105  			true,
   106  			func() {},
   107  		},
   108  		{
   109  			"counterparty payee is an arbitrary string",
   110  			true,
   111  			func() {
   112  				msg.CounterpartyPayee = "arbitrary-string"
   113  				expCounterpartyPayee = "arbitrary-string"
   114  			},
   115  		},
   116  		{
   117  			"channel does not exist",
   118  			false,
   119  			func() {
   120  				msg.ChannelId = "channel-100"
   121  			},
   122  		},
   123  		{
   124  			"channel is not fee enabled",
   125  			false,
   126  			func() {
   127  				suite.chainA.GetSimApp().IBCFeeKeeper.DeleteFeeEnabled(suite.chainA.GetContext(), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID)
   128  			},
   129  		},
   130  	}
   131  
   132  	for _, tc := range testCases {
   133  		suite.SetupTest()
   134  		suite.coordinator.Setup(suite.path) // setup channel
   135  
   136  		expCounterpartyPayee = suite.chainA.SenderAccounts()[1].SenderAccount.GetAddress().String()
   137  		msg = types.NewMsgRegisterCounterpartyPayee(
   138  			suite.path.EndpointA.ChannelConfig.PortID,
   139  			suite.path.EndpointA.ChannelID,
   140  			suite.chainA.SenderAccounts()[0].SenderAccount.GetAddress().String(),
   141  			expCounterpartyPayee,
   142  		)
   143  
   144  		tc.malleate()
   145  
   146  		res, err := suite.chainA.GetSimApp().IBCFeeKeeper.RegisterCounterpartyPayee(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   147  
   148  		if tc.expPass {
   149  			suite.Require().NoError(err)
   150  			suite.Require().NotNil(res)
   151  
   152  			counterpartyPayee, found := suite.chainA.GetSimApp().IBCFeeKeeper.GetCounterpartyPayeeAddress(
   153  				suite.chainA.GetContext(),
   154  				suite.chainA.SenderAccounts()[0].SenderAccount.GetAddress().String(),
   155  				ibctesting.FirstChannelID,
   156  			)
   157  
   158  			suite.Require().True(found)
   159  			suite.Require().Equal(expCounterpartyPayee, counterpartyPayee)
   160  		} else {
   161  			suite.Require().Error(err)
   162  		}
   163  	}
   164  }
   165  
   166  func (suite *KeeperTestSuite) TestPayPacketFee() {
   167  	var (
   168  		expEscrowBalance sdk.Coins
   169  		expFeesInEscrow  []types.PacketFee
   170  		msg              *types.MsgPayPacketFee
   171  		fee              types.Fee
   172  	)
   173  
   174  	testCases := []struct {
   175  		name     string
   176  		malleate func()
   177  		expPass  bool
   178  	}{
   179  		//{
   180  		//	"success",
   181  		//	func() {},
   182  		//	true,
   183  		//},
   184  		//{
   185  		//	"success with existing packet fees in escrow",
   186  		//	func() {
   187  		//		fee := types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)
   188  		//
   189  		//		packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, 1)
   190  		//		packetFee := types.NewPacketFee(fee, suite.chainA.SenderAccount().GetAddress().String(), nil)
   191  		//		feesInEscrow := types.NewPacketFees([]types.PacketFee{packetFee})
   192  		//
   193  		//		suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, feesInEscrow)
   194  		//		err := suite.chainA.GetSimApp().SupplyKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), suite.chainA.SenderAccount().GetAddress(), types.ModuleName, fee.Total().ToCoins())
   195  		//		suite.Require().NoError(err)
   196  		//
   197  		//		expEscrowBalance = expEscrowBalance.Add(fee.Total().ToCoins()...)
   198  		//		expFeesInEscrow = append(expFeesInEscrow, packetFee)
   199  		//	},
   200  		//	true,
   201  		//},
   202  		{
   203  			"refund account is module account",
   204  			func() {
   205  				msg.Signer = suite.chainA.GetSimApp().SupplyKeeper.GetModuleAddress(ibcmock.ModuleName).String()
   206  				addr := suite.chainA.GetSimApp().SupplyKeeper.GetModuleAccount(suite.chainA.GetContext(), ibcmock.ModuleName)
   207  				suite.chainA.GetSimApp().SupplyKeeper.SendCoins(suite.chainA.GetContext(), suite.chainA.SenderAccount().GetAddress(), addr.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))))
   208  				expPacketFee := types.NewPacketFee(fee, msg.Signer, nil)
   209  				expFeesInEscrow = []types.PacketFee{expPacketFee}
   210  			},
   211  			true,
   212  		},
   213  		{
   214  			"fee module is locked",
   215  			func() {
   216  				lockFeeModule(suite.chainA)
   217  			},
   218  			false,
   219  		},
   220  		{
   221  			"fee module disabled on channel",
   222  			func() {
   223  				msg.SourcePortId = "invalid-port"
   224  				msg.SourceChannelId = "invalid-channel"
   225  			},
   226  			false,
   227  		},
   228  		{
   229  			"invalid refund address",
   230  			func() {
   231  				msg.Signer = "invalid-address"
   232  			},
   233  			false,
   234  		},
   235  		{
   236  			"refund account does not exist",
   237  			func() {
   238  				msg.Signer = suite.chainB.SenderAccount().GetAddress().String()
   239  			},
   240  			false,
   241  		},
   242  		{
   243  			"refund account is a blocked address",
   244  			func() {
   245  				blockedAddr := suite.chainA.GetSimApp().SupplyKeeper.GetModuleAccount(suite.chainA.GetContext(), transfertypes.ModuleName).GetAddress()
   246  				msg.Signer = blockedAddr.String()
   247  			},
   248  			false,
   249  		},
   250  		{
   251  			"acknowledgement fee balance not found",
   252  			func() {
   253  				msg.Fee.AckFee = invalidCoinsNotExist
   254  			},
   255  			false,
   256  		},
   257  		{
   258  			"receive fee balance not found",
   259  			func() {
   260  				msg.Fee.RecvFee = invalidCoinsNotExist
   261  			},
   262  			false,
   263  		},
   264  		{
   265  			"timeout fee balance not found",
   266  			func() {
   267  				msg.Fee.TimeoutFee = invalidCoinsNotExist
   268  			},
   269  			false,
   270  		},
   271  	}
   272  
   273  	for _, tc := range testCases {
   274  		tc := tc
   275  
   276  		suite.Run(tc.name, func() {
   277  			suite.SetupTest()
   278  			suite.coordinator.Setup(suite.path) // setup channel
   279  
   280  			fee = types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)
   281  			msg = types.NewMsgPayPacketFee(
   282  				fee,
   283  				suite.path.EndpointA.ChannelConfig.PortID,
   284  				suite.path.EndpointA.ChannelID,
   285  				suite.chainA.SenderAccount().GetAddress().String(),
   286  				nil,
   287  			)
   288  
   289  			expEscrowBalance = fee.Total().ToCoins()
   290  			expPacketFee := types.NewPacketFee(fee, suite.chainA.SenderAccount().GetAddress().String(), nil)
   291  			expFeesInEscrow = []types.PacketFee{expPacketFee}
   292  
   293  			tc.malleate()
   294  
   295  			_, err := suite.chainA.GetSimApp().IBCFeeKeeper.PayPacketFee(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   296  
   297  			if tc.expPass {
   298  				suite.Require().NoError(err) // message committed
   299  
   300  				packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, 1)
   301  				feesInEscrow, found := suite.chainA.GetSimApp().IBCFeeKeeper.GetFeesInEscrow(suite.chainA.GetContext(), packetID)
   302  				suite.Require().True(found)
   303  				suite.Require().Equal(expFeesInEscrow, feesInEscrow.PacketFees)
   304  
   305  				escrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.DefaultBondDenom)
   306  				suite.Require().Equal(expEscrowBalance.AmountOf(sdk.DefaultBondDenom), escrowBalance.Amount)
   307  			} else {
   308  				suite.Require().Error(err)
   309  
   310  				escrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.DefaultBondDenom)
   311  				suite.Require().Equal(sdk.NewInt(0), escrowBalance.Amount.TruncateInt())
   312  			}
   313  		})
   314  	}
   315  }
   316  
   317  func (suite *KeeperTestSuite) TestPayPacketFeeAsync() {
   318  	var (
   319  		packet           channeltypes.Packet
   320  		expEscrowBalance sdk.CoinAdapters
   321  		expFeesInEscrow  []types.PacketFee
   322  		msg              *types.MsgPayPacketFeeAsync
   323  	)
   324  
   325  	testCases := []struct {
   326  		name     string
   327  		malleate func()
   328  		expPass  bool
   329  	}{
   330  		{
   331  			"success",
   332  			func() {},
   333  			true,
   334  		},
   335  		{
   336  			"success with existing packet fees in escrow",
   337  			func() {
   338  				fee := types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)
   339  
   340  				packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, 1)
   341  				packetFee := types.NewPacketFee(fee, suite.chainA.SenderAccount().GetAddress().String(), nil)
   342  				feesInEscrow := types.NewPacketFees([]types.PacketFee{packetFee})
   343  
   344  				suite.chainA.GetSimApp().IBCFeeKeeper.SetFeesInEscrow(suite.chainA.GetContext(), packetID, feesInEscrow)
   345  				err := suite.chainA.GetSimApp().SupplyKeeper.SendCoinsFromAccountToModule(suite.chainA.GetContext(), suite.chainA.SenderAccount().GetAddress(), types.ModuleName, fee.Total().ToCoins())
   346  				suite.Require().NoError(err)
   347  
   348  				expEscrowBalance = expEscrowBalance.Add(fee.Total()...)
   349  				expFeesInEscrow = append(expFeesInEscrow, packetFee)
   350  			},
   351  			true,
   352  		},
   353  		{
   354  			"fee module is locked",
   355  			func() {
   356  				lockFeeModule(suite.chainA)
   357  			},
   358  			false,
   359  		},
   360  		{
   361  			"fee module disabled on channel",
   362  			func() {
   363  				msg.PacketId.PortId = "invalid-port"
   364  				msg.PacketId.ChannelId = "invalid-channel"
   365  			},
   366  			false,
   367  		},
   368  		{
   369  			"channel does not exist",
   370  			func() {
   371  				msg.PacketId.ChannelId = "channel-100"
   372  
   373  				// to test this functionality, we must set the fee to enabled for this non existent channel
   374  				// NOTE: the channel doesn't exist in 04-channel keeper, but we will add a mapping within ics29 anyways
   375  				suite.chainA.GetSimApp().IBCFeeKeeper.SetFeeEnabled(suite.chainA.GetContext(), msg.PacketId.PortId, msg.PacketId.ChannelId)
   376  			},
   377  			false,
   378  		},
   379  		{
   380  			"packet not sent",
   381  			func() {
   382  				msg.PacketId.Sequence = msg.PacketId.Sequence + 1
   383  			},
   384  			false,
   385  		},
   386  		{
   387  			"packet already acknowledged",
   388  			func() {
   389  				err := suite.path.RelayPacketV4(packet)
   390  				suite.Require().NoError(err)
   391  			},
   392  			false,
   393  		},
   394  		{
   395  			"packet already timed out",
   396  			func() {
   397  				// try to incentivze a packet which is timed out
   398  				packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, msg.PacketId.Sequence+1)
   399  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, packetID.Sequence, packetID.PortId, packetID.ChannelId, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), 0)
   400  
   401  				err := suite.path.EndpointA.SendPacket(packet)
   402  				suite.Require().NoError(err)
   403  
   404  				// need to update chainA's client representing chainB to prove missing ack
   405  				err = suite.path.EndpointA.UpdateClient()
   406  				suite.Require().NoError(err)
   407  
   408  				err = suite.path.EndpointA.TimeoutPacket(packet)
   409  				suite.Require().NoError(err)
   410  
   411  				msg.PacketId = packetID
   412  			},
   413  			false,
   414  		},
   415  		{
   416  			"invalid refund address",
   417  			func() {
   418  				msg.PacketFee.RefundAddress = "invalid-address"
   419  			},
   420  			false,
   421  		},
   422  		{
   423  			"refund account does not exist",
   424  			func() {
   425  				msg.PacketFee.RefundAddress = suite.chainB.SenderAccount().GetAddress().String()
   426  			},
   427  			false,
   428  		},
   429  		{
   430  			"refund account is a blocked address",
   431  			func() {
   432  				blockedAddr := suite.chainA.GetSimApp().SupplyKeeper.GetModuleAccount(suite.chainA.GetContext(), transfertypes.ModuleName).GetAddress()
   433  				msg.PacketFee.RefundAddress = blockedAddr.String()
   434  			},
   435  			false,
   436  		},
   437  		{
   438  			"acknowledgement fee balance not found",
   439  			func() {
   440  				msg.PacketFee.Fee.AckFee = invalidCoinsNotExist
   441  			},
   442  			false,
   443  		},
   444  		{
   445  			"receive fee balance not found",
   446  			func() {
   447  				msg.PacketFee.Fee.RecvFee = invalidCoinsNotExist
   448  			},
   449  			false,
   450  		},
   451  		{
   452  			"timeout fee balance not found",
   453  			func() {
   454  				msg.PacketFee.Fee.TimeoutFee = invalidCoinsNotExist
   455  			},
   456  			false,
   457  		},
   458  	}
   459  
   460  	for _, tc := range testCases {
   461  		tc := tc
   462  
   463  		suite.Run(tc.name, func() {
   464  			suite.SetupTest()
   465  			suite.coordinator.Setup(suite.path) // setup channel
   466  
   467  			// send a packet to incentivize
   468  			packetID := channeltypes.NewPacketId(suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, 1)
   469  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, packetID.Sequence, packetID.PortId, packetID.ChannelId, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(clienttypes.ParseChainID(suite.chainB.ChainID()), 100), 0)
   470  			err := suite.path.EndpointA.SendPacket(packet)
   471  			suite.Require().NoError(err)
   472  
   473  			fee := types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)
   474  			packetFee := types.NewPacketFee(fee, suite.chainA.SenderAccount().GetAddress().String(), nil)
   475  
   476  			expEscrowBalance = fee.Total()
   477  			expFeesInEscrow = []types.PacketFee{packetFee}
   478  			msg = types.NewMsgPayPacketFeeAsync(packetID, packetFee)
   479  
   480  			tc.malleate()
   481  
   482  			_, err = suite.chainA.GetSimApp().IBCFeeKeeper.PayPacketFeeAsync(sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   483  
   484  			if tc.expPass {
   485  				suite.Require().NoError(err) // message committed
   486  
   487  				feesInEscrow, found := suite.chainA.GetSimApp().IBCFeeKeeper.GetFeesInEscrow(suite.chainA.GetContext(), packetID)
   488  				suite.Require().True(found)
   489  				suite.Require().Equal(expFeesInEscrow, feesInEscrow.PacketFees)
   490  
   491  				escrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.DefaultBondDenom)
   492  				suite.Require().Equal(expEscrowBalance.ToCoins().AmountOf(sdk.DefaultBondDenom), escrowBalance.Amount)
   493  			} else {
   494  				suite.Require().Error(err)
   495  
   496  				escrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.GetSimApp().IBCFeeKeeper.GetFeeModuleAddress(), sdk.DefaultBondDenom)
   497  				fmt.Println(escrowBalance.String())
   498  				suite.Require().Equal(sdk.NewInt(0), escrowBalance.Amount.TruncateInt())
   499  			}
   500  		})
   501  	}
   502  }