@@ -23,6 +23,7 @@ import (
23
23
"github.com/CosmWasm/wasmd/app"
24
24
wasmibctesting "github.com/CosmWasm/wasmd/tests/ibctesting"
25
25
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
26
+ wasmvmtypes "github.com/CosmWasm/wasmvm/v2/types"
26
27
)
27
28
28
29
func TestIBCFeesTransfer (t * testing.T ) {
@@ -219,3 +220,119 @@ func TestIBCFeesWasm(t *testing.T) {
219
220
payeeBalance = chainB .AllBalances (payee )
220
221
assert .Equal (t , sdk .NewCoin (sdk .DefaultBondDenom , sdkmath .NewInt (2 )).String (), payeeBalance .String ())
221
222
}
223
+
224
+ func TestIBCFeesReflect (t * testing.T ) {
225
+ // scenario:
226
+ // given 2 chains with reflect on chain A
227
+ // and an ibc channel established
228
+ // when ibc-reflect sends a PayPacketFee and a PayPacketFeeAsync msg
229
+ // then the relayer's payee is receiving the fee(s) on success
230
+
231
+ marshaler := app .MakeEncodingConfig (t ).Codec
232
+ coord := wasmibctesting .NewCoordinator (t , 2 )
233
+ chainA := coord .GetChain (wasmibctesting .GetChainID (1 ))
234
+ chainB := coord .GetChain (ibctesting .GetChainID (2 ))
235
+ actorChainA := sdk .AccAddress (chainA .SenderPrivKey .PubKey ().Address ())
236
+ actorChainB := sdk .AccAddress (chainB .SenderPrivKey .PubKey ().Address ())
237
+
238
+ // setup chain A
239
+ codeID := chainA .StoreCodeFile ("./testdata/reflect_2_2.wasm" ).CodeID
240
+
241
+ initMsg := []byte ("{}" )
242
+ reflectContractAddr := chainA .InstantiateContract (codeID , initMsg )
243
+
244
+ payee := sdk .AccAddress (bytes .Repeat ([]byte {2 }, address .Len ))
245
+ oneToken := []wasmvmtypes.Coin {wasmvmtypes .NewCoin (1 , sdk .DefaultBondDenom )}
246
+
247
+ path := wasmibctesting .NewPath (chainA , chainB )
248
+ path .EndpointA .ChannelConfig = & ibctesting.ChannelConfig {
249
+ PortID : ibctransfertypes .PortID ,
250
+ Version : string (marshaler .MustMarshalJSON (& ibcfee.Metadata {FeeVersion : ibcfee .Version , AppVersion : ibctransfertypes .Version })),
251
+ Order : channeltypes .UNORDERED ,
252
+ }
253
+ path .EndpointB .ChannelConfig = & ibctesting.ChannelConfig {
254
+ PortID : ibctransfertypes .PortID ,
255
+ Version : string (marshaler .MustMarshalJSON (& ibcfee.Metadata {FeeVersion : ibcfee .Version , AppVersion : ibctransfertypes .Version })),
256
+ Order : channeltypes .UNORDERED ,
257
+ }
258
+ // with an ics-29 fee enabled channel setup between both chains
259
+ coord .Setup (path )
260
+ appA := chainA .App .(* app.WasmApp )
261
+ appB := chainB .App .(* app.WasmApp )
262
+ require .True (t , appA .IBCFeeKeeper .IsFeeEnabled (chainA .GetContext (), ibctransfertypes .PortID , path .EndpointA .ChannelID ))
263
+ require .True (t , appB .IBCFeeKeeper .IsFeeEnabled (chainB .GetContext (), ibctransfertypes .PortID , path .EndpointB .ChannelID ))
264
+ // and with a payee registered for A -> B
265
+ _ , err := chainA .SendMsgs (ibcfee .NewMsgRegisterPayee (ibctransfertypes .PortID , path .EndpointA .ChannelID , actorChainA .String (), payee .String ()))
266
+ require .NoError (t , err )
267
+ _ , err = chainB .SendMsgs (ibcfee .NewMsgRegisterCounterpartyPayee (ibctransfertypes .PortID , path .EndpointB .ChannelID , actorChainB .String (), payee .String ()))
268
+ require .NoError (t , err )
269
+
270
+ // when reflect contract on A sends a PayPacketFee msg, followed by a transfer
271
+ _ , err = ExecViaReflectContract (t , chainA , reflectContractAddr , []wasmvmtypes.CosmosMsg {
272
+ {
273
+ IBC : & wasmvmtypes.IBCMsg {
274
+ PayPacketFee : & wasmvmtypes.PayPacketFeeMsg {
275
+ Fee : wasmvmtypes.IBCFee {
276
+ AckFee : oneToken ,
277
+ ReceiveFee : oneToken ,
278
+ TimeoutFee : []wasmvmtypes.Coin {},
279
+ },
280
+ Relayers : []string {},
281
+ PortID : ibctransfertypes .PortID ,
282
+ ChannelID : path .EndpointA .ChannelID ,
283
+ },
284
+ },
285
+ },
286
+ {
287
+ IBC : & wasmvmtypes.IBCMsg {
288
+ Transfer : & wasmvmtypes.TransferMsg {
289
+ ChannelID : path .EndpointA .ChannelID ,
290
+ ToAddress : actorChainB .String (),
291
+ Amount : wasmvmtypes .NewCoin (10 , sdk .DefaultBondDenom ),
292
+ Timeout : wasmvmtypes.IBCTimeout {
293
+ Timestamp : 9999999999999999999 ,
294
+ },
295
+ },
296
+ },
297
+ },
298
+ })
299
+ require .NoError (t , err )
300
+
301
+ pendingIncentivisedPackages := appA .IBCFeeKeeper .GetIdentifiedPacketFeesForChannel (chainA .GetContext (), ibctransfertypes .PortID , path .EndpointA .ChannelID )
302
+ assert .Len (t , pendingIncentivisedPackages , 1 )
303
+
304
+ // and sends an PayPacketFeeAsync msg
305
+ _ , err = ExecViaReflectContract (t , chainA , reflectContractAddr , []wasmvmtypes.CosmosMsg {
306
+ {
307
+ IBC : & wasmvmtypes.IBCMsg {
308
+ PayPacketFeeAsync : & wasmvmtypes.PayPacketFeeAsyncMsg {
309
+ Fee : wasmvmtypes.IBCFee {
310
+ AckFee : []wasmvmtypes.Coin {},
311
+ ReceiveFee : oneToken ,
312
+ TimeoutFee : oneToken ,
313
+ },
314
+ Relayers : []string {},
315
+ Sequence : pendingIncentivisedPackages [0 ].PacketId .Sequence ,
316
+ PortID : ibctransfertypes .PortID ,
317
+ ChannelID : path .EndpointA .ChannelID ,
318
+ },
319
+ },
320
+ },
321
+ })
322
+ require .NoError (t , err )
323
+
324
+ // and packages relayed
325
+ require .NoError (t , coord .RelayAndAckPendingPackets (path ))
326
+
327
+ // then
328
+ // on chain A
329
+ payeeBalance := chainA .AllBalances (payee )
330
+ // 2 tokens from the PayPacketFee and 1 token from the PayPacketFeeAsync
331
+ assert .Equal (t , sdk .NewCoin (sdk .DefaultBondDenom , sdkmath .NewInt (3 )).String (), payeeBalance .String ())
332
+ // and on chain B
333
+ pendingIncentivisedPackages = appA .IBCFeeKeeper .GetIdentifiedPacketFeesForChannel (chainA .GetContext (), ibctransfertypes .PortID , path .EndpointA .ChannelID )
334
+ assert .Len (t , pendingIncentivisedPackages , 0 )
335
+ expBalance := ibctransfertypes .GetTransferCoin (path .EndpointB .ChannelConfig .PortID , path .EndpointB .ChannelID , sdk .DefaultBondDenom , sdkmath .NewInt (10 ))
336
+ gotBalance := chainB .Balance (actorChainB , expBalance .Denom )
337
+ assert .Equal (t , expBalance .String (), gotBalance .String (), chainB .AllBalances (actorChainB ))
338
+ }
0 commit comments