The RefundFeesOnChannelClosure
function refunds all the packets’ fees when a channel is closed. If multiple fees exist for a packet ID (identifiedPacketFee.PacketFees
variable), an inner loop will be executed to distribute the funds from the feeibc
module to the refund address. If the sdk.AccAddressFromBech32(packetFee.RefundAddress)
or SendCoinsFromModuleToAccount
functions in lines 208 or 215 fail, the failedToSendCoins
boolean will be set to true
, causing the packet ID not to be removed from the storage.
The issue is that the packet will not be deleted as long as one of the fee transfers fails. In other words, successful packet fees are not removed from the packet ID storage. This means that the storage will record both successful and failed fee transfers, which is incorrect because successful fee transfers need to be removed, as the funds have already been received by the recipient (notice that the cached context is committed).
If the governance decides to refund the failed fee transfers by checking the packet IDs in storage (e.g., using the GetAllIdentifiedPacketFees
function), the recipient will receive twice the refund amount. This may also happen during future developments that allow the receiver to initiate a refund for closed channels.
modules/apps/29-fee/keeper/escrow_test.go
.Consider modifying the RefundFeesOnChannelClosure
function so that when a packet fee is transferred successfully, it is excluded from the packet ID. If all the fees are removed, call DeleteFeesInEscrow
to remove the packet ID from the storage. If there are remaining fees, call SetFeesInEscrow
to update the packet ID in the storage.
Fixed in https://github.com/cosmos/ibc-go/pull/6255 from https://github.com/cosmos/ibc-go/releases/tag/v7.5.0.