Skip to content

Commit 0a4f81e

Browse files
authored
fix: handled ibc-v2 universal error ack (#260)
* fix: handled ibc-v2 universal error ack * test: added new test case for universal error ack
1 parent 2062d6f commit 0a4f81e

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

modules/rate-limiting/keeper/packet.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package keeper
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
67

@@ -15,6 +16,7 @@ import (
1516
transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
1617
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
1718
channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types"
19+
channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types"
1820
ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported"
1921
)
2022

@@ -29,6 +31,11 @@ type RateLimitedPacketInfo struct {
2931
// CheckAcknowledementSucceeded unmarshals IBC Acknowledgements, and determines
3032
// whether the tx was successful
3133
func (k Keeper) CheckAcknowledementSucceeded(ctx sdk.Context, ack []byte) (success bool, err error) {
34+
// Check if the ack is the IBC v2 universal error acknowledgement
35+
if bytes.Equal(ack, channeltypesv2.ErrorAcknowledgement[:]) {
36+
return false, nil
37+
}
38+
3239
// Unmarshal the raw ack response
3340
var acknowledgement channeltypes.Acknowledgement
3441
if err := transfertypes.ModuleCdc.UnmarshalJSON(ack, &acknowledgement); err != nil {

modules/rate-limiting/keeper/packet_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
1818
channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types"
19+
channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types"
1920
)
2021

2122
const (
@@ -391,6 +392,51 @@ func (s *KeeperTestSuite) TestAcknowledgeRateLimitedPacket_AckFailure() {
391392
s.Require().Equal(initialOutflow.Sub(packetAmount).Int64(), rateLimit.Flow.Outflow.Int64(), "outflow")
392393
}
393394

395+
func (s *KeeperTestSuite) TestAcknowledgeRateLimitedPacket_UniversalErrorAck() {
396+
// For ack packets, the source will be stride and the destination will be the host
397+
denom := ustrd
398+
sourceChannel := channelOnStride
399+
destinationChannel := channelOnHost
400+
initialOutflow := sdkmath.NewInt(100)
401+
packetAmount := sdkmath.NewInt(10)
402+
sequence := uint64(10)
403+
404+
// Create rate limit - only outflow is needed to this tests
405+
s.App.RatelimitKeeper.SetRateLimit(s.Ctx, types.RateLimit{
406+
Path: &types.Path{Denom: denom, ChannelOrClientId: channelId},
407+
Flow: &types.Flow{Outflow: initialOutflow},
408+
})
409+
410+
// Store the pending packet for this sequence number
411+
s.App.RatelimitKeeper.SetPendingSendPacket(s.Ctx, sourceChannel, sequence)
412+
413+
// Build the ack packet
414+
packetData, err := json.Marshal(transfertypes.FungibleTokenPacketData{Denom: denom, Amount: packetAmount.String()})
415+
s.Require().NoError(err)
416+
packet := channeltypes.Packet{
417+
SourcePort: transferPort,
418+
SourceChannel: sourceChannel,
419+
DestinationPort: transferPort,
420+
DestinationChannel: destinationChannel,
421+
Data: packetData,
422+
Sequence: sequence,
423+
}
424+
ackFailure := channeltypesv2.ErrorAcknowledgement[:]
425+
426+
// Call OnTimeoutPacket with the failed ack
427+
err = s.App.RatelimitKeeper.AcknowledgeRateLimitedPacket(s.Ctx, packet, ackFailure)
428+
s.Require().NoError(err, "no error expected during AckPacket")
429+
430+
// Confirm the pending packet was removed
431+
found := s.App.RatelimitKeeper.CheckPacketSentDuringCurrentQuota(s.Ctx, sourceChannel, sequence)
432+
s.Require().False(found, "send packet should have been removed")
433+
434+
// Confirm the flow was adjusted
435+
rateLimit, found := s.App.RatelimitKeeper.GetRateLimit(s.Ctx, denom, sourceChannel)
436+
s.Require().True(found)
437+
s.Require().Equal(initialOutflow.Sub(packetAmount).Int64(), rateLimit.Flow.Outflow.Int64(), "outflow")
438+
}
439+
394440
func (s *KeeperTestSuite) TestTimeoutRateLimitedPacket() {
395441
// For timeout packets, the source will be stride and the destination will be the host
396442
denom := ustrd

0 commit comments

Comments
 (0)