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  }