Skip to content

Commit a737132

Browse files
authored
feat: ics 29 packet callbacks (#357)
1 parent 885fb9a commit a737132

File tree

11 files changed

+474
-39
lines changed

11 files changed

+474
-39
lines changed

modules/apps/29-fee/fee_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55

66
"github.com/stretchr/testify/suite"
77

8+
sdk "github.com/cosmos/cosmos-sdk/types"
9+
810
"github.com/cosmos/ibc-go/modules/apps/29-fee/types"
911
transfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
12+
clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
1013
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
1114
ibctesting "github.com/cosmos/ibc-go/testing"
1215
)
@@ -39,3 +42,24 @@ func (suite *FeeTestSuite) SetupTest() {
3942
func TestIBCFeeTestSuite(t *testing.T) {
4043
suite.Run(t, new(FeeTestSuite))
4144
}
45+
46+
func (suite *FeeTestSuite) CreateICS20Packet(coin sdk.Coin) channeltypes.Packet {
47+
48+
fungibleTokenPacket := transfertypes.NewFungibleTokenPacketData(
49+
coin.Denom,
50+
sdk.NewInt(100).Uint64(),
51+
suite.chainA.SenderAccount.GetAddress().String(),
52+
suite.chainB.SenderAccount.GetAddress().String(),
53+
)
54+
55+
return channeltypes.NewPacket(
56+
fungibleTokenPacket.GetBytes(),
57+
suite.chainA.SenderAccount.GetSequence(),
58+
suite.path.EndpointA.ChannelConfig.PortID,
59+
suite.path.EndpointA.ChannelID,
60+
suite.path.EndpointB.ChannelConfig.PortID,
61+
suite.path.EndpointB.ChannelID,
62+
clienttypes.NewHeight(0, 100),
63+
0,
64+
)
65+
}

modules/apps/29-fee/ibc_module.go

+80-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/cosmos/ibc-go/modules/apps/29-fee/types"
1010
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
1111
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
12-
ibcexported "github.com/cosmos/ibc-go/modules/core/exported"
12+
"github.com/cosmos/ibc-go/modules/core/exported"
1313
)
1414

1515
// IBCModule implements the ICS26 callbacks for the fee middleware given the fee keeper and the underlying application.
@@ -171,32 +171,105 @@ func (im IBCModule) OnChanCloseConfirm(
171171
}
172172

173173
// OnRecvPacket implements the IBCModule interface.
174+
// If fees are not enabled, this callback will default to the ibc-core packet callback
174175
func (im IBCModule) OnRecvPacket(
175176
ctx sdk.Context,
176177
packet channeltypes.Packet,
177178
relayer sdk.AccAddress,
178-
) ibcexported.Acknowledgement {
179-
// TODO: Implement fee specific logic if fee is enabled for the given channel
180-
return im.app.OnRecvPacket(ctx, packet, relayer)
179+
) exported.Acknowledgement {
180+
if !im.keeper.IsFeeEnabled(ctx, packet.DestinationPort, packet.DestinationChannel) {
181+
return im.app.OnRecvPacket(ctx, packet, relayer)
182+
}
183+
184+
ack := im.app.OnRecvPacket(ctx, packet, relayer)
185+
186+
forwardRelayer, found := im.keeper.GetCounterpartyAddress(ctx, relayer.String())
187+
if !found {
188+
forwardRelayer = ""
189+
}
190+
191+
return types.IncentivizedAcknowledgement{
192+
Result: ack.Acknowledgement(),
193+
ForwardRelayerAddress: forwardRelayer,
194+
}
181195
}
182196

183197
// OnAcknowledgementPacket implements the IBCModule interface
198+
// If fees are not enabled, this callback will default to the ibc-core packet callback
184199
func (im IBCModule) OnAcknowledgementPacket(
185200
ctx sdk.Context,
186201
packet channeltypes.Packet,
187202
acknowledgement []byte,
188203
relayer sdk.AccAddress,
189204
) error {
190-
// TODO: Implement fee specific logic if fee is enabled for the given channel
191-
return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
205+
if !im.keeper.IsFeeEnabled(ctx, packet.SourcePort, packet.SourceChannel) {
206+
return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
207+
}
208+
209+
ack := new(types.IncentivizedAcknowledgement)
210+
if err := types.ModuleCdc.UnmarshalJSON(acknowledgement, ack); err != nil {
211+
return sdkerrors.Wrapf(err, "cannot unmarshal ICS-29 incentivized packet acknowledgement: %v", ack)
212+
}
213+
214+
packetId := channeltypes.NewPacketId(packet.SourceChannel, packet.SourcePort, packet.Sequence)
215+
identifiedPacketFee, found := im.keeper.GetFeeInEscrow(ctx, packetId)
216+
217+
if !found {
218+
// return underlying callback if no fee found for given packetID
219+
return im.app.OnAcknowledgementPacket(ctx, packet, ack.Result, relayer)
220+
}
221+
222+
// cache context before trying to distribute the fee
223+
cacheCtx, writeFn := ctx.CacheContext()
224+
225+
forwardRelayer, _ := sdk.AccAddressFromBech32(ack.ForwardRelayerAddress)
226+
refundAcc, _ := sdk.AccAddressFromBech32(identifiedPacketFee.RefundAddress)
227+
228+
err := im.keeper.DistributeFee(cacheCtx, refundAcc, forwardRelayer, relayer, packetId)
229+
230+
if err == nil {
231+
// write the cache and then call underlying callback
232+
writeFn()
233+
// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
234+
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
235+
}
236+
// otherwise discard cache and call underlying callback
237+
return im.app.OnAcknowledgementPacket(ctx, packet, ack.Result, relayer)
192238
}
193239

194240
// OnTimeoutPacket implements the IBCModule interface
241+
// If fees are not enabled, this callback will default to the ibc-core packet callback
195242
func (im IBCModule) OnTimeoutPacket(
196243
ctx sdk.Context,
197244
packet channeltypes.Packet,
198245
relayer sdk.AccAddress,
199246
) error {
200-
// TODO: Implement fee specific logic if fee is enabled for the given channel
247+
if !im.keeper.IsFeeEnabled(ctx, packet.SourcePort, packet.SourceChannel) {
248+
return im.app.OnTimeoutPacket(ctx, packet, relayer)
249+
}
250+
251+
packetId := channeltypes.NewPacketId(packet.SourceChannel, packet.SourcePort, packet.Sequence)
252+
253+
identifiedPacketFee, found := im.keeper.GetFeeInEscrow(ctx, packetId)
254+
255+
if !found {
256+
// return underlying callback if fee not found for given packetID
257+
return im.app.OnTimeoutPacket(ctx, packet, relayer)
258+
}
259+
260+
// cache context before trying to distribute the fee
261+
cacheCtx, writeFn := ctx.CacheContext()
262+
263+
refundAcc, _ := sdk.AccAddressFromBech32(identifiedPacketFee.RefundAddress)
264+
err := im.keeper.DistributeFeeTimeout(cacheCtx, refundAcc, relayer, packetId)
265+
266+
if err == nil {
267+
// write the cache and then call underlying callback
268+
writeFn()
269+
// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
270+
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
271+
}
272+
273+
// otherwise discard cache and call underlying callback
201274
return im.app.OnTimeoutPacket(ctx, packet, relayer)
202275
}

0 commit comments

Comments
 (0)