github.com/okex/exchain@v1.8.0/libs/ibc-go/modules/apps/transfer/transfer_test.go (about) 1 package transfer_test 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/suite" 7 8 sdk "github.com/okex/exchain/libs/cosmos-sdk/types" 9 "github.com/okex/exchain/libs/ibc-go/modules/apps/transfer/types" 10 clienttypes "github.com/okex/exchain/libs/ibc-go/modules/core/02-client/types" 11 channeltypes "github.com/okex/exchain/libs/ibc-go/modules/core/04-channel/types" 12 ibctesting "github.com/okex/exchain/libs/ibc-go/testing" 13 ) 14 15 type TransferTestSuite struct { 16 suite.Suite 17 18 coordinator *ibctesting.Coordinator 19 20 // testing chains used for convenience and readability 21 chainA ibctesting.TestChainI 22 chainB ibctesting.TestChainI 23 chainC ibctesting.TestChainI 24 } 25 26 func (suite *TransferTestSuite) SetupTest() { 27 suite.coordinator = ibctesting.NewCoordinator(suite.T(), 3) 28 suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) 29 suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) 30 suite.chainC = suite.coordinator.GetChain(ibctesting.GetChainID(2)) 31 } 32 33 func NewTransferPath(chainA, chainB ibctesting.TestChainI) *ibctesting.Path { 34 path := ibctesting.NewPath(chainA, chainB) 35 path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort 36 path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort 37 38 return path 39 } 40 func getBalance(coins sdk.Coins, denom string) *sdk.Coin { 41 for _, coin := range coins { 42 if coin.Denom == denom { 43 return &coin 44 } 45 } 46 return nil 47 } 48 49 // constructs a send from chainA to chainB on the established channel/connection 50 // and sends the same coin back from chainB to chainA. 51 func (suite *TransferTestSuite) TestHandleMsgTransfer() { 52 // setup between chainA and chainB 53 pathA2B := NewTransferPath(suite.chainA, suite.chainB) 54 suite.coordinator.Setup(pathA2B) 55 56 // originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount().GetAddress(), sdk.DefaultBondDenom) 57 timeoutHeight := clienttypes.NewHeight(0, 110) 58 59 amount, ok := sdk.NewIntFromString("92233720368547758080") // 2^63 (one above int64) 60 suite.Require().True(ok) 61 transferAmountDec := sdk.NewDecFromIntWithPrec(amount, 0) 62 coinToSendToB := sdk.NewCoin(sdk.DefaultIbcWei, amount) 63 64 // send from chainA to chainB 65 msg := types.NewMsgTransfer(pathA2B.EndpointA.ChannelConfig.PortID, pathA2B.EndpointA.ChannelID, coinToSendToB, suite.chainA.SenderAccount().GetAddress(), suite.chainB.SenderAccount().GetAddress().String(), timeoutHeight, 0) 66 67 _, err := suite.chainA.SendMsgs(msg) 68 suite.Require().NoError(err) // message committed 69 70 // relay send 71 72 fungibleTokenPacket := types.NewFungibleTokenPacketData(coinToSendToB.Denom, transferAmountDec.BigInt().String(), suite.chainA.SenderAccount().GetAddress().String(), suite.chainB.SenderAccount().GetAddress().String()) 73 packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, pathA2B.EndpointA.ChannelConfig.PortID, pathA2B.EndpointA.ChannelID, pathA2B.EndpointB.ChannelConfig.PortID, pathA2B.EndpointB.ChannelID, timeoutHeight, 0) 74 75 ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) 76 err = pathA2B.RelayPacket(packet, ack.Acknowledgement()) 77 suite.Require().NoError(err) // relay committed 78 79 // check that voucher exists on chain B 80 voucherDenomTrace := types.ParseDenomTrace(types.GetPrefixedDenom(packet.GetDestPort(), packet.GetDestChannel(), sdk.DefaultIbcWei)) 81 //balance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount().GetAddress(), voucherDenomTrace.IBCDenom()) 82 83 balanceB := suite.chainB.GetSimApp().BankKeeper.GetCoins(suite.chainB.GetContext(), suite.chainB.SenderAccount().GetAddress()) 84 85 denomTrace := types.ParseDenomTrace(types.GetPrefixedDenom(pathA2B.EndpointB.ChannelConfig.PortID, pathA2B.EndpointB.ChannelID, sdk.DefaultIbcWei)) 86 coinSentFromAToB := sdk.NewCoin(denomTrace.IBCDenom(), amount) 87 suite.Require().Equal(coinSentFromAToB, balanceB[0]) 88 89 // setup between chainB to chainC 90 // NOTE: 91 // pathBtoC.EndpointA = endpoint on chainB 92 // pathBtoC.EndpointB = endpoint on chainC 93 pathBtoC := NewTransferPath(suite.chainB, suite.chainC) 94 suite.coordinator.Setup(pathBtoC) 95 96 // send from chainB to chainC 97 msg = types.NewMsgTransfer(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, coinSentFromAToB, suite.chainB.SenderAccount().GetAddress(), suite.chainC.SenderAccount().GetAddress().String(), timeoutHeight, 0) 98 99 _, err = suite.chainB.SendMsgs(msg) 100 suite.Require().NoError(err) // message committed 101 102 // relay send 103 // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment 104 fullDenomPathB2C := types.GetPrefixedDenom(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, voucherDenomTrace.GetFullDenomPath()) 105 denom := types.ParseDenomTrace(fullDenomPathB2C).IBCDenom() 106 fungibleTokenPacket = types.NewFungibleTokenPacketData(voucherDenomTrace.GetFullDenomPath(), transferAmountDec.BigInt().String(), suite.chainB.SenderAccount().GetAddress().String(), suite.chainC.SenderAccount().GetAddress().String()) 107 packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, timeoutHeight, 0) 108 err = pathBtoC.RelayPacket(packet, ack.Acknowledgement()) 109 suite.Require().NoError(err) // relay committed 110 111 coinSentFromBToC := sdk.NewCoin(denom, amount) 112 balanceB = suite.chainB.GetSimApp().BankKeeper.GetCoins(suite.chainB.GetContext(), suite.chainB.SenderAccount().GetAddress()) 113 balanceC := suite.chainC.GetSimApp().BankKeeper.GetCoins(suite.chainC.GetContext(), suite.chainC.SenderAccount().GetAddress()) 114 115 // check that the balance is updated on chainC 116 suite.Require().Equal(coinSentFromBToC, *getBalance(balanceC, denom)) 117 118 // check that balance on chain B is empty 119 suite.Require().Nil(getBalance(balanceB, denom)) 120 121 // send from chainC back to chainB 122 msg = types.NewMsgTransfer(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, coinSentFromBToC, suite.chainC.SenderAccount().GetAddress(), suite.chainB.SenderAccount().GetAddress().String(), timeoutHeight, 0) 123 124 _, err = suite.chainC.SendMsgs(msg) 125 suite.Require().NoError(err) // message committed 126 127 // relay send 128 // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment 129 fungibleTokenPacket = types.NewFungibleTokenPacketData(fullDenomPathB2C, transferAmountDec.BigInt().String(), suite.chainC.SenderAccount().GetAddress().String(), suite.chainB.SenderAccount().GetAddress().String()) 130 packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, timeoutHeight, 0) 131 err = pathBtoC.RelayPacket(packet, ack.Acknowledgement()) 132 suite.Require().NoError(err) // relay committed 133 134 balanceB = suite.chainB.GetSimApp().BankKeeper.GetCoins(suite.chainB.GetContext(), suite.chainB.SenderAccount().GetAddress()) 135 // check that the balance on chainA returned back to the original state 136 suite.Require().Equal(coinSentFromAToB, balanceB[0]) 137 138 // check that module account escrow address is empty 139 escrowAddress := types.GetEscrowAddress(packet.GetDestPort(), packet.GetDestChannel()) 140 balanceEC := suite.chainB.GetSimApp().BankKeeper.GetCoins(suite.chainB.GetContext(), escrowAddress) 141 suite.Require().Nil(getBalance(balanceEC, denom)) 142 143 // check that balance on chain B is empty 144 balanceC = suite.chainC.GetSimApp().BankKeeper.GetCoins(suite.chainC.GetContext(), suite.chainC.SenderAccount().GetAddress()) 145 suite.Require().Nil(getBalance(balanceC, denom)) 146 } 147 148 func TestTransferTestSuite(t *testing.T) { 149 suite.Run(t, new(TransferTestSuite)) 150 }