Skip to content

Commit

Permalink
test: add more multi-denom test cases (#6545)
Browse files Browse the repository at this point in the history
* test: add more multi-denom test cases

* Move success case up

---------

Co-authored-by: Carlos Rodriguez <[email protected]>
  • Loading branch information
gjermundgaraba and crodriguezvega authored Jun 12, 2024
1 parent 794d8a0 commit 3c4d8b3
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 149 deletions.
109 changes: 64 additions & 45 deletions modules/apps/29-fee/transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,81 @@ import (

// Integration test to ensure ics29 works with ics20
func (suite *FeeTestSuite) TestFeeTransfer() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2}))
path.EndpointA.ChannelConfig.Version = feeTransferVersion
path.EndpointB.ChannelConfig.Version = feeTransferVersion
path.EndpointA.ChannelConfig.PortID = transfertypes.PortID
path.EndpointB.ChannelConfig.PortID = transfertypes.PortID
testCases := []struct {
name string
coinsToTransfer sdk.Coins
}{
{
"transfer single denom",
sdk.NewCoins(ibctesting.TestCoin),
},
{
"transfer multiple denoms",
sdk.NewCoins(ibctesting.TestCoin, ibctesting.SecondaryTestCoin),
},
}

path.Setup()
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest() // reset

// set up coin & ics20 packet
coin := ibctesting.TestCoin
fee := types.Fee{
RecvFee: defaultRecvFee,
AckFee: defaultAckFee,
TimeoutFee: defaultTimeoutFee,
}
path := ibctesting.NewPath(suite.chainA, suite.chainB)
feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2}))
path.EndpointA.ChannelConfig.Version = feeTransferVersion
path.EndpointB.ChannelConfig.Version = feeTransferVersion
path.EndpointA.ChannelConfig.PortID = transfertypes.PortID
path.EndpointB.ChannelConfig.PortID = transfertypes.PortID

msgs := []sdk.Msg{
types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil),
transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoins(coin), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, ""),
}
res, err := suite.chainA.SendMsgs(msgs...)
suite.Require().NoError(err) // message committed
path.Setup()

// after incentivizing the packets
originalChainASenderAccountBalance := sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))
fee := types.Fee{
RecvFee: defaultRecvFee,
AckFee: defaultAckFee,
TimeoutFee: defaultTimeoutFee,
}

packet, err := ibctesting.ParsePacketFromEvents(res.Events)
suite.Require().NoError(err)
msgs := []sdk.Msg{
types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil),
transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, tc.coinsToTransfer, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, ""),
}

// register counterparty address on chainB
// relayerAddress is address of sender account on chainB, but we will use it on chainA
// to differentiate from the chainA.SenderAccount for checking successful relay payouts
relayerAddress := suite.chainB.SenderAccount.GetAddress()
res, err := suite.chainA.SendMsgs(msgs...)
suite.Require().NoError(err) // message committed

msgRegister := types.NewMsgRegisterCounterpartyPayee(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, suite.chainB.SenderAccount.GetAddress().String(), relayerAddress.String())
_, err = suite.chainB.SendMsgs(msgRegister)
suite.Require().NoError(err) // message committed
// after incentivizing the packets
originalChainASenderAccountBalance := sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))

// relay packet
err = path.RelayPacket(packet)
suite.Require().NoError(err) // relay committed
packet, err := ibctesting.ParsePacketFromEvents(res.Events)
suite.Require().NoError(err)

// register counterparty address on chainB
// relayerAddress is address of sender account on chainB, but we will use it on chainA
// to differentiate from the chainA.SenderAccount for checking successful relay payouts
relayerAddress := suite.chainB.SenderAccount.GetAddress()

msgRegister := types.NewMsgRegisterCounterpartyPayee(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, suite.chainB.SenderAccount.GetAddress().String(), relayerAddress.String())
_, err = suite.chainB.SendMsgs(msgRegister)
suite.Require().NoError(err) // message committed

// ensure relayers got paid
// relayer for forward relay: chainB.SenderAccount
// relayer for reverse relay: chainA.SenderAccount
// relay packet
err = path.RelayPacket(packet)
suite.Require().NoError(err) // relay committed

// check forward relay balance
suite.Require().Equal(
fee.RecvFee,
sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)),
)
// ensure relayers got paid
// relayer for forward relay: chainB.SenderAccount
// relayer for reverse relay: chainA.SenderAccount

suite.Require().Equal(
fee.AckFee, // ack fee paid, no refund needed since timeout_fee = recv_fee + ack_fee
sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)).Sub(originalChainASenderAccountBalance[0]))
// check forward relay balance
suite.Require().Equal(
fee.RecvFee,
sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)),
)

suite.Require().Equal(
fee.AckFee, // ack fee paid, no refund needed since timeout_fee = recv_fee + ack_fee
sdk.NewCoins(suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)).Sub(originalChainASenderAccountBalance[0]))
})
}
}

func (suite *FeeTestSuite) TestTransferFeeUpgrade() {
Expand Down
12 changes: 12 additions & 0 deletions modules/apps/callbacks/ibc_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ func (s *CallbacksTestSuite) TestSendPacket() {
false,
nil,
},
{
"success: multiple denoms",
func() {
packetData.Tokens = append(packetData.Tokens, transfertypes.Token{
Denom: transfertypes.NewDenom(ibctesting.SecondaryDenom),
Amount: ibctesting.SecondaryTestCoin.Amount.String(),
})
},
types.CallbackTypeSendPacket,
false,
nil,
},
{
"success: no-op on callback data is not valid",
func() {
Expand Down
23 changes: 14 additions & 9 deletions modules/apps/transfer/keeper/invariants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,29 @@ import (

func (suite *KeeperTestSuite) TestTotalEscrowPerDenomInvariant() {
testCases := []struct {
name string
malleate func()
expPass bool
name string
coinsToTransfer sdk.Coins
malleate func()
expPass bool
}{
{
"success",
sdk.NewCoins(ibctesting.TestCoin, ibctesting.SecondaryTestCoin),
func() {},
true,
},
{
"success with single denom",
sdk.NewCoins(ibctesting.TestCoin),
func() {},
true,
},
{
"fails with broken invariant",
sdk.NewCoins(ibctesting.TestCoin),
func() {
// set amount for denom higher than actual value in escrow
amount := sdkmath.NewInt(200)
amount := ibctesting.TestCoin.Amount.Add(sdkmath.NewInt(100))
suite.chainA.GetSimApp().TransferKeeper.SetTotalEscrowForDenom(suite.chainA.GetContext(), sdk.NewCoin(sdk.DefaultBondDenom, amount))
},
false,
Expand All @@ -40,14 +49,10 @@ func (suite *KeeperTestSuite) TestTotalEscrowPerDenomInvariant() {
path := ibctesting.NewTransferPath(suite.chainA, suite.chainB)
path.Setup()

amount := sdkmath.NewInt(100)

// send coins from chain A to chain B so that we have them in escrow
coin := sdk.NewCoin(sdk.DefaultBondDenom, amount)
msg := types.NewMsgTransfer(
path.EndpointA.ChannelConfig.PortID,
path.EndpointA.ChannelID,
sdk.NewCoins(coin),
tc.coinsToTransfer,
suite.chainA.SenderAccount.GetAddress().String(),
suite.chainB.SenderAccount.GetAddress().String(),
suite.chainA.GetTimeoutHeight(), 0, "",
Expand Down
Loading

0 comments on commit 3c4d8b3

Please sign in to comment.