diff --git a/modules/apps/29-fee/keeper/escrow.go b/modules/apps/29-fee/keeper/escrow.go index 8914279a71d..d64f5354ef4 100644 --- a/modules/apps/29-fee/keeper/escrow.go +++ b/modules/apps/29-fee/keeper/escrow.go @@ -167,6 +167,10 @@ func (k Keeper) distributeFee(ctx sdk.Context, receiver, refundAccAddress sdk.Ac k.Logger(ctx).Error("error refunding fee to the original sender", "refund address", refundAccAddress, "fee", fee) return // if sending to the refund address fails, no-op } + + EmitDistributeFeeEvent(ctx, refundAccAddress.String(), fee) + } else { + EmitDistributeFeeEvent(ctx, receiver.String(), fee) } // write the cache diff --git a/modules/apps/29-fee/keeper/events.go b/modules/apps/29-fee/keeper/events.go index ae931862fc7..24122b54be7 100644 --- a/modules/apps/29-fee/keeper/events.go +++ b/modules/apps/29-fee/keeper/events.go @@ -75,3 +75,18 @@ func EmitRegisterCounterpartyPayeeEvent(ctx sdk.Context, relayer, counterpartyPa ), }) } + +// EmitDistributeFeeEvent emits an event containing a distribution fee and receiver address +func EmitDistributeFeeEvent(ctx sdk.Context, receiver string, fee sdk.Coins) { + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeDistributeFee, + sdk.NewAttribute(types.AttributeKeyReceiver, receiver), + sdk.NewAttribute(types.AttributeKeyFee, fee.String()), + ), + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), + ), + }) +} diff --git a/modules/apps/29-fee/keeper/events_test.go b/modules/apps/29-fee/keeper/events_test.go index 24d67acdeca..d149479beaa 100644 --- a/modules/apps/29-fee/keeper/events_test.go +++ b/modules/apps/29-fee/keeper/events_test.go @@ -5,6 +5,11 @@ import ( abcitypes "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/ibc-go/v6/modules/apps/29-fee/types" + transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v6/modules/core/24-host" + ibctesting "github.com/cosmos/ibc-go/v6/testing" ) func (suite *KeeperTestSuite) TestIncentivizePacketEvent() { @@ -81,3 +86,83 @@ func (suite *KeeperTestSuite) TestIncentivizePacketEvent() { } } } + +func (suite *KeeperTestSuite) TestDistributeFeeEvent() { + // create an incentivized transfer path + path := ibctesting.NewPath(suite.chainA, suite.chainB) + feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.Version})) + path.EndpointA.ChannelConfig.Version = feeTransferVersion + path.EndpointB.ChannelConfig.Version = feeTransferVersion + path.EndpointA.ChannelConfig.PortID = transfertypes.PortID + path.EndpointB.ChannelConfig.PortID = transfertypes.PortID + + suite.coordinator.Setup(path) + + // send a new MsgPayPacketFee and MsgTransfer to chainA + fee := types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee) + msgPayPacketFee := types.NewMsgPayPacketFee( + fee, + path.EndpointA.ChannelConfig.PortID, + path.EndpointA.ChannelID, + suite.chainA.SenderAccount.GetAddress().String(), + nil, + ) + + msgTransfer := transfertypes.NewMsgTransfer( + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), + clienttypes.NewHeight(1, 100), 0, "", + ) + + res, err := suite.chainA.SendMsgs(msgPayPacketFee, msgTransfer) + suite.Require().NoError(err) + suite.Require().NotNil(res) + + // parse the packet from result events and recv packet on chainB + packet, err := ibctesting.ParsePacketFromEvents(res.GetEvents()) + suite.Require().NoError(err) + suite.Require().NotNil(packet) + + err = path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + res, err = path.EndpointB.RecvPacketWithResult(packet) + suite.Require().NoError(err) + suite.Require().NotNil(res) + + // parse the acknowledgement from result events and acknowledge packet on chainA + ack, err := ibctesting.ParseAckFromEvents(res.GetEvents()) + suite.Require().NoError(err) + suite.Require().NotNil(ack) + + packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + proof, proofHeight := path.EndpointA.Counterparty.QueryProof(packetKey) + + msgAcknowledgement := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, path.EndpointA.Chain.SenderAccount.GetAddress().String()) + res, err = suite.chainA.SendMsgs(msgAcknowledgement) + suite.Require().NoError(err) + suite.Require().NotNil(res) + + events := res.GetEvents() + expectedEvents := sdk.Events{ + sdk.NewEvent( + types.EventTypeDistributeFee, + sdk.NewAttribute(types.AttributeKeyReceiver, suite.chainA.SenderAccount.GetAddress().String()), + sdk.NewAttribute(types.AttributeKeyFee, defaultRecvFee.String()), + ), + sdk.NewEvent( + types.EventTypeDistributeFee, + sdk.NewAttribute(types.AttributeKeyReceiver, suite.chainA.SenderAccount.GetAddress().String()), + sdk.NewAttribute(types.AttributeKeyFee, defaultAckFee.String()), + ), + sdk.NewEvent( + types.EventTypeDistributeFee, + sdk.NewAttribute(types.AttributeKeyReceiver, suite.chainA.SenderAccount.GetAddress().String()), + sdk.NewAttribute(types.AttributeKeyFee, defaultTimeoutFee.String()), + ), + } + + for _, evt := range expectedEvents { + suite.Require().Contains(events, evt) + } +} diff --git a/modules/apps/29-fee/types/events.go b/modules/apps/29-fee/types/events.go index cffca5dabdd..ea9cdd0f870 100644 --- a/modules/apps/29-fee/types/events.go +++ b/modules/apps/29-fee/types/events.go @@ -5,6 +5,7 @@ const ( EventTypeIncentivizedPacket = "incentivized_ibc_packet" EventTypeRegisterPayee = "register_payee" EventTypeRegisterCounterpartyPayee = "register_counterparty_payee" + EventTypeDistributeFee = "distribute_fee" AttributeKeyRecvFee = "recv_fee" AttributeKeyAckFee = "ack_fee" @@ -13,4 +14,6 @@ const ( AttributeKeyRelayer = "relayer" AttributeKeyPayee = "payee" AttributeKeyCounterpartyPayee = "counterparty_payee" + AttributeKeyReceiver = "receiver" + AttributeKeyFee = "fee" )