|
| 1 | +package interchaintest_test |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "testing" |
| 7 | + |
| 8 | + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" |
| 9 | + relayertest "github.com/cosmos/relayer/v2/interchaintest" |
| 10 | + interchaintest "github.com/strangelove-ventures/interchaintest/v7" |
| 11 | + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" |
| 12 | + ibc "github.com/strangelove-ventures/interchaintest/v7/ibc" |
| 13 | + "github.com/strangelove-ventures/interchaintest/v7/testreporter" |
| 14 | + "github.com/strangelove-ventures/interchaintest/v7/testutil" |
| 15 | + "github.com/stretchr/testify/require" |
| 16 | + "go.uber.org/zap/zaptest" |
| 17 | +) |
| 18 | + |
| 19 | +func TestScenarioFeeMiddleware(t *testing.T) { |
| 20 | + if testing.Short() { |
| 21 | + t.Skip() |
| 22 | + } |
| 23 | + |
| 24 | + t.Parallel() |
| 25 | + |
| 26 | + nv := 1 |
| 27 | + nf := 0 |
| 28 | + |
| 29 | + // Get both chains |
| 30 | + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ |
| 31 | + {Name: "juno", ChainName: "chaina", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chaina", GasPrices: "0.0ujuno"}}, |
| 32 | + {Name: "juno", ChainName: "chainb", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chainb", GasPrices: "0.0ujuno"}}}, |
| 33 | + ) |
| 34 | + |
| 35 | + chains, err := cf.Chains(t.Name()) |
| 36 | + require.NoError(t, err) |
| 37 | + chainA, chainB := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain) |
| 38 | + |
| 39 | + ctx := context.Background() |
| 40 | + client, network := interchaintest.DockerSetup(t) |
| 41 | + |
| 42 | + rf := relayertest.NewRelayerFactory(relayertest.RelayerConfig{InitialBlockHistory: 50}) |
| 43 | + r := rf.Build(t, client, network) |
| 44 | + |
| 45 | + const pathChainAChainB = "chainA-chainB" |
| 46 | + |
| 47 | + // Build the network |
| 48 | + ic := interchaintest.NewInterchain(). |
| 49 | + AddChain(chainA). |
| 50 | + AddChain(chainB). |
| 51 | + AddRelayer(r, "relayer"). |
| 52 | + AddLink(interchaintest.InterchainLink{ |
| 53 | + Chain1: chainA, |
| 54 | + Chain2: chainB, |
| 55 | + Relayer: r, |
| 56 | + Path: pathChainAChainB, |
| 57 | + CreateChannelOpts: ibc.CreateChannelOptions{ |
| 58 | + SourcePortName: "transfer", |
| 59 | + DestPortName: "transfer", |
| 60 | + Order: ibc.Unordered, |
| 61 | + Version: "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}", |
| 62 | + }, |
| 63 | + CreateClientOpts: ibc.DefaultClientOpts(), |
| 64 | + }) |
| 65 | + |
| 66 | + rep := testreporter.NewNopReporter() |
| 67 | + eRep := rep.RelayerExecReporter(t) |
| 68 | + |
| 69 | + require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ |
| 70 | + TestName: t.Name(), |
| 71 | + Client: client, |
| 72 | + NetworkID: network, |
| 73 | + SkipPathCreation: false, |
| 74 | + })) |
| 75 | + |
| 76 | + t.Cleanup(func() { |
| 77 | + _ = ic.Close() |
| 78 | + }) |
| 79 | + |
| 80 | + err = testutil.WaitForBlocks(ctx, 10, chainA, chainB) |
| 81 | + require.NoError(t, err) |
| 82 | + |
| 83 | + // ChainID of ChainA |
| 84 | + chainIDA := chainA.Config().ChainID |
| 85 | + |
| 86 | + // Channel of ChainA |
| 87 | + chA, err := r.GetChannels(ctx, eRep, chainIDA) |
| 88 | + require.NoError(t, err) |
| 89 | + channelA := chA[0] |
| 90 | + |
| 91 | + // Fund a user account on chain1 and chain2 |
| 92 | + const userFunds = int64(1_000_000_000_000) |
| 93 | + users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chainA, chainB) |
| 94 | + userA := users[0] |
| 95 | + userAddressA := userA.FormattedAddress() |
| 96 | + userB := users[1] |
| 97 | + userAddressB := userB.FormattedAddress() |
| 98 | + |
| 99 | + // Addresses of both the chains |
| 100 | + walletA, _ := r.GetWallet(chainA.Config().ChainID) |
| 101 | + rlyAddressA := walletA.FormattedAddress() |
| 102 | + |
| 103 | + walletB, _ := r.GetWallet(chainB.Config().ChainID) |
| 104 | + rlyAddressB := walletB.FormattedAddress() |
| 105 | + |
| 106 | + // register CounterpartyPayee |
| 107 | + cmd := []string{ |
| 108 | + "tx", "register-counterparty", |
| 109 | + chainA.Config().Name, |
| 110 | + channelA.ChannelID, |
| 111 | + "transfer", |
| 112 | + rlyAddressA, |
| 113 | + rlyAddressB, |
| 114 | + } |
| 115 | + _ = r.Exec(ctx, eRep, cmd, nil) |
| 116 | + require.NoError(t, err) |
| 117 | + |
| 118 | + // Query the relayer CounterpartyPayee on a given channel |
| 119 | + query := []string{ |
| 120 | + chainA.Config().Bin, "query", "ibc-fee", "counterparty-payee", channelA.ChannelID, rlyAddressA, |
| 121 | + "--chain-id", chainIDA, |
| 122 | + "--node", chainA.GetRPCAddress(), |
| 123 | + "--home", chainA.HomeDir(), |
| 124 | + "--trace", |
| 125 | + } |
| 126 | + _, _, err = chainA.Exec(ctx, query, nil) |
| 127 | + require.NoError(t, err) |
| 128 | + |
| 129 | + // Get initial account balances |
| 130 | + userAOrigBal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom) |
| 131 | + require.NoError(t, err) |
| 132 | + require.Equal(t, userFunds, userAOrigBal) |
| 133 | + |
| 134 | + userBOrigBal, err := chainB.GetBalance(ctx, userAddressB, chainB.Config().Denom) |
| 135 | + require.NoError(t, err) |
| 136 | + require.Equal(t, userFunds, userBOrigBal) |
| 137 | + |
| 138 | + rlyAOrigBal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom) |
| 139 | + require.NoError(t, err) |
| 140 | + require.Equal(t, userFunds, rlyAOrigBal) |
| 141 | + |
| 142 | + rlyBOrigBal, err := chainB.GetBalance(ctx, rlyAddressB, chainB.Config().Denom) |
| 143 | + require.NoError(t, err) |
| 144 | + require.Equal(t, userFunds, rlyBOrigBal) |
| 145 | + |
| 146 | + // send tx |
| 147 | + const txAmount = 1000 |
| 148 | + transfer := ibc.WalletAmount{Address: userAddressB, Denom: chainA.Config().Denom, Amount: txAmount} |
| 149 | + _, err = chainA.SendIBCTransfer(ctx, channelA.ChannelID, userAddressA, transfer, ibc.TransferOptions{}) |
| 150 | + require.NoError(t, err) |
| 151 | + |
| 152 | + // Incentivizing async packet by returning MsgPayPacketFeeAsync |
| 153 | + packetFeeAsync := []string{ |
| 154 | + chainA.Config().Bin, "tx", "ibc-fee", "pay-packet-fee", "transfer", channelA.ChannelID, "1", |
| 155 | + "--recv-fee", fmt.Sprintf("1000%s", chainA.Config().Denom), |
| 156 | + "--ack-fee", fmt.Sprintf("1000%s", chainA.Config().Denom), |
| 157 | + "--timeout-fee", fmt.Sprintf("1000%s", chainA.Config().Denom), |
| 158 | + "--chain-id", chainIDA, |
| 159 | + "--node", chainA.GetRPCAddress(), |
| 160 | + "--from", userA.FormattedAddress(), |
| 161 | + "--keyring-backend", "test", |
| 162 | + "--gas", "400000", |
| 163 | + "--yes", |
| 164 | + "--home", chainA.HomeDir(), |
| 165 | + } |
| 166 | + _, _, err = chainA.Exec(ctx, packetFeeAsync, nil) |
| 167 | + require.NoError(t, err) |
| 168 | + |
| 169 | + // start the relayer |
| 170 | + err = r.StartRelayer(ctx, eRep, pathChainAChainB) |
| 171 | + require.NoError(t, err) |
| 172 | + |
| 173 | + t.Cleanup( |
| 174 | + func() { |
| 175 | + err := r.StopRelayer(ctx, eRep) |
| 176 | + if err != nil { |
| 177 | + t.Logf("an error occured while stopping the relayer: %s", err) |
| 178 | + } |
| 179 | + }, |
| 180 | + ) |
| 181 | + |
| 182 | + // Wait for relayer to run |
| 183 | + err = testutil.WaitForBlocks(ctx, 5, chainA, chainB) |
| 184 | + require.NoError(t, err) |
| 185 | + |
| 186 | + // Assigning denom |
| 187 | + chainATokenDenom := transfertypes.GetPrefixedDenom(channelA.PortID, channelA.ChannelID, chainA.Config().Denom) |
| 188 | + chainADenomTrace := transfertypes.ParseDenomTrace(chainATokenDenom) |
| 189 | + |
| 190 | + // Get balances after the fees |
| 191 | + chainABal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom) |
| 192 | + require.NoError(t, err) |
| 193 | + require.Equal(t, userAOrigBal-(txAmount+1000), chainABal) |
| 194 | + |
| 195 | + chainBBal, err := chainB.GetBalance(ctx, userAddressB, chainADenomTrace.IBCDenom()) |
| 196 | + require.NoError(t, err) |
| 197 | + require.Equal(t, int64(txAmount), chainBBal) |
| 198 | + |
| 199 | + rlyABal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom) |
| 200 | + require.NoError(t, err) |
| 201 | + require.Equal(t, rlyAOrigBal+1000, rlyABal) |
| 202 | +} |
0 commit comments