-
Notifications
You must be signed in to change notification settings - Fork 648
/
Copy pathtransfer_test.go
152 lines (121 loc) · 6.16 KB
/
transfer_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package e2e
import (
"context"
"fmt"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/strangelove-ventures/ibctest"
"github.com/strangelove-ventures/ibctest/chain/cosmos"
"github.com/strangelove-ventures/ibctest/ibc"
"github.com/strangelove-ventures/ibctest/test"
"github.com/stretchr/testify/suite"
"github.com/cosmos/ibc-go/e2e/testsuite"
"github.com/cosmos/ibc-go/e2e/testvalues"
transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types"
)
func TestTransferTestSuite(t *testing.T) {
suite.Run(t, new(TransferTestSuite))
}
type TransferTestSuite struct {
testsuite.E2ETestSuite
}
// Transfer broadcasts a MsgTransfer message.
func (s *TransferTestSuite) Transfer(ctx context.Context, chain *cosmos.CosmosChain, user *ibctest.User,
portID, channelID string, token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64,
) (sdk.TxResponse, error) {
msg := transfertypes.NewMsgTransfer(portID, channelID, token, sender, receiver, timeoutHeight, timeoutTimestamp)
return s.BroadcastMessages(ctx, chain, user, msg)
}
// QueryPacketCommitment queries the counterparty payee of the given chain and relayer address on the specified channel.
func (s *TransferTestSuite) QueryPacketCommitment(ctx context.Context, chain ibc.Chain, portID, channelID string, sequence uint64) ([]byte, error) {
queryClient := s.GetChainGRCPClients(chain).ChannelQueryClient
res, err := queryClient.PacketCommitment(ctx, &channeltypes.QueryPacketCommitmentRequest{
PortId: portID,
ChannelId: channelID,
Sequence: sequence,
})
if err != nil {
return nil, err
}
return res.Commitment, nil
}
// TestMsgTransfer_Succeeds_Nonincentivized will test sending successful IBC transfers from chainA to chainB.
// The transfer will occur over a basic transfer channel (non incentivized) and both native and non-native tokens
// will be sent forwards and backwards in the IBC transfer timeline (both chains will act as source and receiver chains).
func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized() {
t := s.T()
ctx := context.TODO()
relayer, channelA := s.SetupChainsRelayerAndChannel(ctx, transferChannelOptions())
chainA, chainB := s.GetChains()
chainADenom := chainA.Config().Denom
chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount)
chainAAddress := chainAWallet.Bech32Address(chainA.Config().Bech32Prefix)
chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount)
chainBAddress := chainBWallet.Bech32Address(chainB.Config().Bech32Prefix)
t.Run("relayer wallets recovered", func(t *testing.T) {
err := s.RecoverRelayerWallets(ctx, relayer)
s.Require().NoError(err)
})
s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks")
t.Run("native IBC token transfer from chainA (source) to chainB, sender is source", func(t *testing.T) {
transferTxResp, err := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.getTimeoutHeight(ctx, chainB), 0)
s.Require().NoError(err)
s.AssertValidTxResponse(transferTxResp)
})
t.Run("tokens are escrowed", func(t *testing.T) {
actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet)
s.Require().NoError(err)
expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance)
})
t.Run("start relayer", func(t *testing.T) {
s.StartRelayer(relayer)
})
chainBIBCToken := s.getIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID)
t.Run("packets are relayed", func(t *testing.T) {
actualBalance, err := chainB.GetBalance(ctx, chainBAddress, chainBIBCToken.IBCDenom())
s.Require().NoError(err)
expected := testvalues.IBCTransferAmount
s.Require().Equal(expected, actualBalance)
})
t.Run("non-native IBC token transfer from chainB to chainA (source), receiver is source", func(t *testing.T) {
transferTxResp, err := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), chainBAddress, chainAAddress, s.getTimeoutHeight(ctx, chainA), 0)
s.Require().NoError(err)
s.AssertValidTxResponse(transferTxResp)
})
t.Run("tokens are escrowed", func(t *testing.T) {
actualBalance, err := chainB.GetBalance(ctx, chainBAddress, chainBIBCToken.IBCDenom())
s.Require().NoError(err)
s.Require().Equal(int64(0), actualBalance)
})
s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks")
t.Run("packets are relayed", func(t *testing.T) {
commitment, err := s.QueryPacketCommitment(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1)
s.Require().Empty(commitment)
actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet)
s.Require().NoError(err)
expected := testvalues.StartingTokenAmount
s.Require().Equal(expected, actualBalance)
})
}
// transferChannelOptions configures both of the chains to have non-incentivized transfer channels.
func transferChannelOptions() func(options *ibc.CreateChannelOptions) {
return func(opts *ibc.CreateChannelOptions) {
opts.Version = "ics20-1"
opts.SourcePortName = "transfer"
opts.DestPortName = "transfer"
}
}
// getIBCToken returns the denomination of the full token denom sent to the receiving channel
func (s *TransferTestSuite) getIBCToken(fullTokenDenom string, portID, channelID string) transfertypes.DenomTrace {
return transfertypes.ParseDenomTrace(fmt.Sprintf("%s/%s/%s", portID, channelID, fullTokenDenom))
}
// getTimeoutHeight returns a timeout height of 1000 blocks above the current block height
// this function should be used when the timeout is never expected to be reached
func (s *TransferTestSuite) getTimeoutHeight(ctx context.Context, chain *cosmos.CosmosChain) clienttypes.Height {
height, err := chain.Height(ctx)
s.Require().NoError(err)
return clienttypes.NewHeight(clienttypes.ParseChainID(chain.Config().ChainID), uint64(height)+1000)
}