From 58cf32219b8ca8b3b636c7e56815fd5efc52f62e Mon Sep 17 00:00:00 2001 From: Tuan Tran Date: Wed, 24 Jan 2024 14:48:56 +0700 Subject: [PATCH] fix: fix conflict with main, will refactor later --- utils/coins.go | 32 ++++++----- .../keeper/ibc_packet_handlers.go | 54 ++++++++++++++----- .../keeper/ibc_packet_handlers_test.go | 38 ++++++------- 3 files changed, 72 insertions(+), 52 deletions(-) diff --git a/utils/coins.go b/utils/coins.go index a8c027d5a..aa218ad25 100644 --- a/utils/coins.go +++ b/utils/coins.go @@ -2,12 +2,10 @@ package utils import ( "fmt" - "strings" sdk "github.com/cosmos/cosmos-sdk/types" ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - bankutils "github.com/quicksilver-zone/quicksilver/v7/utils/bankutils" - + "github.com/quicksilver-zone/quicksilver/v7/utils/bankutils" ) func DenomFromRequestKey(query []byte, accAddr sdk.AccAddress) (string, error) { @@ -28,18 +26,18 @@ func DenomFromRequestKey(query []byte, accAddr sdk.AccAddress) (string, error) { return denom, nil } -// DeriveIbcDenom mirrors getDenomForThisChain from the packet-forward-middleware/v5, used under MIT License. -// See: https://github.com/strangelove-ventures/packet-forward-middleware/blob/86f045c12cc48ffc1f016ff122b89a9f6ac8ed63/router/ibc_middleware.go#L104 -func DeriveIbcDenom(port, channel, counterpartyPort, counterpartyChannel, denom string) string { - counterpartyPrefix := transfertypes.GetDenomPrefix(counterpartyPort, counterpartyChannel) - if strings.HasPrefix(denom, counterpartyPrefix) { - unwoundDenom := denom[len(counterpartyPrefix):] - denomTrace := transfertypes.ParseDenomTrace(unwoundDenom) - if denomTrace.Path == "" { - return unwoundDenom - } - return denomTrace.IBCDenom() - } - prefixedDenom := transfertypes.GetDenomPrefix(port, channel) + denom - return transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() +func DeriveIbcDenom(port, channel, denom string) string { + return DeriveIbcDenomTrace(port, channel, denom).IBCDenom() +} + +func DeriveIbcDenomTrace(port, channel, denom string) ibctransfertypes.DenomTrace { + // generate denomination prefix + sourcePrefix := ibctransfertypes.GetDenomPrefix(port, channel) + // NOTE: sourcePrefix contains the trailing "/" + prefixedDenom := sourcePrefix + denom + + // construct the denomination trace from the full raw denomination + denomTrace := ibctransfertypes.ParseDenomTrace(prefixedDenom) + + return denomTrace } diff --git a/x/interchainstaking/keeper/ibc_packet_handlers.go b/x/interchainstaking/keeper/ibc_packet_handlers.go index e8fcd4b4c..a8aa3e495 100644 --- a/x/interchainstaking/keeper/ibc_packet_handlers.go +++ b/x/interchainstaking/keeper/ibc_packet_handlers.go @@ -274,9 +274,21 @@ func (k *Keeper) HandleAcknowledgement(ctx sdk.Context, packet channeltypes.Pack return err } case "/ibc.applications.transfer.v1.MsgTransfer": - k.Logger(ctx).Debug("Received MsgTransfer acknowledgement; no action") - return nil + // this should be okay to fail; we'll pick it up next time around. + if !success { + return nil + } + response := ibctransfertypes.MsgTransferResponse{} + err = proto.Unmarshal(msgResponse, &response) + if err != nil { + k.Logger(ctx).Error("unable to unpack MsgTransfer response", "error", err) + return err + } + k.Logger(ctx).Info("MsgTranfer acknowledgement received") + if err := k.HandleMsgTransfer(ctx, msg.Msg); err != nil { + return err + } default: k.Logger(ctx).Error("unhandled acknowledgement packet", "type", reflect.TypeOf(msg.Msg).Name()) } @@ -291,28 +303,46 @@ func (*Keeper) HandleTimeout(_ sdk.Context, _ channeltypes.Packet) error { // ---------------------------------------------------------------- -func (k *Keeper) HandleMsgTransfer(ctx sdk.Context, msg ibctransfertypes.FungibleTokenPacketData, ibcDenom string) error { +func (k *Keeper) HandleMsgTransfer(ctx sdk.Context, msg sdk.Msg) error { k.Logger(ctx).Info("Received MsgTransfer acknowledgement") // first, type assertion. we should have ibctransfertypes.MsgTransfer + sMsg, ok := msg.(*ibctransfertypes.MsgTransfer) + if !ok { + k.Logger(ctx).Error("unable to cast source message to MsgTransfer") + return errors.New("unable to cast source message to MsgTransfer") + } // check if destination is interchainstaking module account (spoiler: it was) - if msg.Receiver != k.AccountKeeper.GetModuleAddress(types.ModuleName).String() { + if sMsg.Receiver != k.AccountKeeper.GetModuleAddress(types.ModuleName).String() { k.Logger(ctx).Error("msgTransfer to unknown account!") return errors.New("unexpected recipient") } - receivedAmount, ok := sdkmath.NewIntFromString(msg.Amount) - if !ok { - return fmt.Errorf("unable to marshal amount into math.Int: %s", msg.Amount) - } - receivedCoin := sdk.NewCoin(ibcDenom, receivedAmount) + receivedCoin := sMsg.Token - zone, found := k.GetZoneForWithdrawalAccount(ctx, msg.Sender) + zone, found := k.GetZoneForWithdrawalAccount(ctx, sMsg.Sender) if !found { - return fmt.Errorf("zone not found for withdrawal account %s", msg.Sender) + return fmt.Errorf("zone not found for withdrawal account %s", sMsg.Sender) } - if found && msg.Denom != zone.BaseDenom { + var channel *channeltypes.IdentifiedChannel + k.IBCKeeper.ChannelKeeper.IterateChannels(ctx, func(ic channeltypes.IdentifiedChannel) bool { + if ic.Counterparty.ChannelId == sMsg.SourceChannel && ic.Counterparty.PortId == sMsg.SourcePort && len(ic.ConnectionHops) == 1 && ic.ConnectionHops[0] == zone.ConnectionId && ic.State == channeltypes.OPEN { + channel = &ic + return true + } + return false + }) + + if channel == nil { + k.Logger(ctx).Error("channel not found for the packet", "port", sMsg.SourcePort, "channel", sMsg.SourceChannel) + return errors.New("channel not found for the packet") + } + + denomTrace := utils.DeriveIbcDenomTrace(channel.PortId, channel.ChannelId, receivedCoin.Denom) + receivedCoin.Denom = denomTrace.IBCDenom() + + if found && denomTrace.BaseDenom != zone.BaseDenom { // k.Logger(ctx).Error("got withdrawal account and NOT staking denom", "rx", receivedCoin.Denom, "trace_base_denom", denomTrace.BaseDenom, "zone_base_denom", zone.BaseDenom) feeAmount := sdkmath.LegacyNewDecFromInt(receivedCoin.Amount).Mul(k.GetCommissionRate(ctx)).TruncateInt() rewardCoin := receivedCoin.SubAmount(feeAmount) diff --git a/x/interchainstaking/keeper/ibc_packet_handlers_test.go b/x/interchainstaking/keeper/ibc_packet_handlers_test.go index 18b6d362b..a1d8172e5 100644 --- a/x/interchainstaking/keeper/ibc_packet_handlers_test.go +++ b/x/interchainstaking/keeper/ibc_packet_handlers_test.go @@ -56,12 +56,6 @@ func (suite *KeeperTestSuite) TestHandleMsgTransferGood() { fcAmount: math.NewInt(100), withdrawalAmount: math.ZeroInt(), }, - { - name: "ibc denom denom - all goes to fc", - amount: sdk.NewCoin("transfer/channel-569/untrn", math.NewInt(100)), - fcAmount: math.NewInt(2), - withdrawalAmount: math.NewInt(98), - }, { name: "non staking denom - default (2.5%) to fc, remainder to withdrawal", amount: sdk.NewCoin("ujuno", math.NewInt(100)), @@ -88,7 +82,7 @@ func (suite *KeeperTestSuite) TestHandleMsgTransferGood() { channel, cfound := quicksilver.InterchainstakingKeeper.IBCKeeper.ChannelKeeper.GetChannel(ctx, "transfer", "channel-0") suite.True(cfound) - ibcDenom := utils.DeriveIbcDenom("transfer", "channel-0", channel.Counterparty.PortId, channel.Counterparty.ChannelId, tc.amount.Denom) + ibcDenom := utils.DeriveIbcDenom(channel.Counterparty.PortId, channel.Counterparty.ChannelId, tc.amount.Denom) err := quicksilver.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(ibcDenom, tc.amount.Amount))) suite.NoError(err) @@ -108,14 +102,14 @@ func (suite *KeeperTestSuite) TestHandleMsgTransferGood() { txMacc := quicksilver.AccountKeeper.GetModuleAddress(types.ModuleName) feeMacc := quicksilver.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName) - transferPacket := ibctransfertypes.FungibleTokenPacketData{ - Amount: tc.amount.Amount.String(), - Denom: tc.amount.Denom, - Sender: sender, - Receiver: quicksilver.AccountKeeper.GetModuleAddress(types.ModuleName).String(), + transferMsg := ibctransfertypes.MsgTransfer{ + SourcePort: "transfer", + SourceChannel: "channel-0", + Token: tc.amount, + Sender: sender, + Receiver: quicksilver.AccountKeeper.GetModuleAddress(types.ModuleName).String(), } - - suite.NoError(quicksilver.InterchainstakingKeeper.HandleMsgTransfer(ctx, transferPacket, utils.DeriveIbcDenom("transfer", "channel-0", channel.Counterparty.PortId, channel.Counterparty.ChannelId, tc.amount.Denom))) + suite.NoError(quicksilver.InterchainstakingKeeper.HandleMsgTransfer(ctx, &transferMsg)) txMaccBalance := quicksilver.BankKeeper.GetAllBalances(ctx, txMacc) feeMaccBalance := quicksilver.BankKeeper.GetAllBalances(ctx, feeMacc) @@ -158,9 +152,8 @@ func TestHandleMsgTransferBadRecipient(t *testing.T) { Token: sdk.NewCoin("denom", sdkmath.NewInt(100)), Sender: senderAddr, Receiver: recipient.String(), - } - require.Error(t, quicksilver.InterchainstakingKeeper.HandleMsgTransfer(ctx, transferMsg, "raa")) + require.Error(t, quicksilver.InterchainstakingKeeper.HandleMsgTransfer(ctx, &transferMsg)) } func (suite *KeeperTestSuite) TestHandleQueuedUnbondings() { @@ -1816,8 +1809,9 @@ func (suite *KeeperTestSuite) Test_v045Callback() { if !found { suite.Fail("unable to retrieve zone for test") } + sender := zone.WithdrawalAddress.Address - val := quicksilver.InterchainstakingKeeper.GetValidatorAddresses(ctx, zone.ChainId)[0] + quicksilver.InterchainstakingKeeper.IBCKeeper.ChannelKeeper.SetChannel(ctx, "transfer", "channel-0", TestChannel) ibcDenom := utils.DeriveIbcDenom("transfer", "channel-0", zone.BaseDenom) err := quicksilver.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(ibcDenom, sdkmath.NewInt(100)))) @@ -1833,10 +1827,9 @@ func (suite *KeeperTestSuite) Test_v045Callback() { response := ibctransfertypes.MsgTransferResponse{ Sequence: 1, } - response := stakingtypes.MsgDelegateResponse{} respBytes := icatypes.ModuleCdc.MustMarshal(&response) - return []sdk.Msg{&sendMsg}, respBytes + return []sdk.Msg{&transferMsg}, respBytes }, assertStatements: func(ctx sdk.Context, quicksilver *app.Quicksilver) bool { zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID) @@ -1946,8 +1939,9 @@ func (suite *KeeperTestSuite) Test_v046Callback() { if !found { suite.Fail("unable to retrieve zone for test") } + sender := zone.WithdrawalAddress.Address - val := quicksilver.InterchainstakingKeeper.GetValidatorAddresses(ctx, zone.ChainId)[0] + quicksilver.InterchainstakingKeeper.IBCKeeper.ChannelKeeper.SetChannel(ctx, "transfer", "channel-0", TestChannel) ibcDenom := utils.DeriveIbcDenom("transfer", "channel-0", zone.BaseDenom) err := quicksilver.BankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(ibcDenom, sdkmath.NewInt(100)))) @@ -1963,11 +1957,10 @@ func (suite *KeeperTestSuite) Test_v046Callback() { response := ibctransfertypes.MsgTransferResponse{ Sequence: 1, } - response := stakingtypes.MsgDelegateResponse{} anyResponse, err := codectypes.NewAnyWithValue(&response) suite.NoError(err) - return []sdk.Msg{&sendMsg}, anyResponse + return []sdk.Msg{&transferMsg}, anyResponse }, assertStatements: func(ctx sdk.Context, quicksilver *app.Quicksilver) bool { zone, found := quicksilver.InterchainstakingKeeper.GetZone(ctx, suite.chainB.ChainID) @@ -2057,7 +2050,6 @@ func (suite *KeeperTestSuite) Test_v046Callback() { Data: packetBytes, } - ctx = ctx.WithContext(context.WithValue(ctx.Context(), utils.ContextKey("connectionID"), "connection-0")) suite.NoError(quicksilver.InterchainstakingKeeper.HandleAcknowledgement(ctx, packet, icatypes.ModuleCdc.MustMarshalJSON(&acknowledgement))) suite.True(test.assertStatements(ctx, quicksilver))