From 3518ed4ab1ad7c5b06fb800261e4f70c529ce880 Mon Sep 17 00:00:00 2001 From: rustdev Date: Tue, 21 May 2024 22:56:51 +0100 Subject: [PATCH 01/16] added custom pfm middleware to substitue logic on onRecvPacket --- .../ibc_middleware.go | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 custom/packet-forward-middleware/ibc_middleware.go diff --git a/custom/packet-forward-middleware/ibc_middleware.go b/custom/packet-forward-middleware/ibc_middleware.go new file mode 100644 index 00000000..50232e09 --- /dev/null +++ b/custom/packet-forward-middleware/ibc_middleware.go @@ -0,0 +1,40 @@ +package packetforward + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + router "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +var _ porttypes.Middleware = &IBCMiddleware{} + +// IBCMiddleware implements the ICS26 callbacks for the forward middleware given the +// forward keeper and the underlying application. +type IBCMiddleware struct { + router.IBCMiddleware +} + +func NewIBCMiddleware( + app porttypes.IBCModule, + k *keeper.Keeper, + retriesOnTimeout uint8, + forwardTimeout time.Duration, + refundTimeout time.Duration, +) IBCMiddleware { + return IBCMiddleware{ + IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), + } +} + +func (im IBCMiddleware) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) +} From dbaa1a958379a3ea9f634ee779116a0d07edcf79 Mon Sep 17 00:00:00 2001 From: rustdev Date: Tue, 21 May 2024 23:31:00 +0100 Subject: [PATCH 02/16] import custom pfm into app.go --- app/app.go | 2 ++ custom/custompfm/keeper/keeper.go | 40 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 custom/custompfm/keeper/keeper.go diff --git a/app/app.go b/app/app.go index 9388901c..b61d2be5 100644 --- a/app/app.go +++ b/app/app.go @@ -87,6 +87,7 @@ import ( ibcclientclient "github.com/cosmos/ibc-go/v7/modules/core/02-client/client" ibchost "github.com/cosmos/ibc-go/v7/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" + custompfm "github.com/notional-labs/composable/v6/custom/custompfm/keeper" customibctransfer "github.com/notional-labs/composable/v6/custom/ibc-transfer" customstaking "github.com/notional-labs/composable/v6/custom/staking" "github.com/spf13/cast" @@ -338,6 +339,7 @@ func NewComposableApp( enabledProposals, ) + custompfm.NewIBCMiddleware() // transferModule := transfer.NewAppModule(app.TransferKeeper) transferModule := customibctransfer.NewAppModule(appCodec, app.TransferKeeper, app.BankKeeper) routerModule := router.NewAppModule(app.RouterKeeper) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go new file mode 100644 index 00000000..e38e19b1 --- /dev/null +++ b/custom/custompfm/keeper/keeper.go @@ -0,0 +1,40 @@ +package keeper + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + router "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +var _ porttypes.Middleware = &IBCMiddleware{} + +// IBCMiddleware implements the ICS26 callbacks for the forward middleware given the +// forward keeper and the underlying application. +type IBCMiddleware struct { + router.IBCMiddleware +} + +func NewIBCMiddleware( + app porttypes.IBCModule, + k *keeper.Keeper, + retriesOnTimeout uint8, + forwardTimeout time.Duration, + refundTimeout time.Duration, +) IBCMiddleware { + return IBCMiddleware{ + IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), + } +} + +func (im IBCMiddleware) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) +} From d8fa914836f59b88f0cc259bc1dd4b51feb1fd91 Mon Sep 17 00:00:00 2001 From: rustdev Date: Tue, 21 May 2024 23:32:50 +0100 Subject: [PATCH 03/16] remove old. --- .../ibc_middleware.go | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 custom/packet-forward-middleware/ibc_middleware.go diff --git a/custom/packet-forward-middleware/ibc_middleware.go b/custom/packet-forward-middleware/ibc_middleware.go deleted file mode 100644 index 50232e09..00000000 --- a/custom/packet-forward-middleware/ibc_middleware.go +++ /dev/null @@ -1,40 +0,0 @@ -package packetforward - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - router "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" - "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" - ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" -) - -var _ porttypes.Middleware = &IBCMiddleware{} - -// IBCMiddleware implements the ICS26 callbacks for the forward middleware given the -// forward keeper and the underlying application. -type IBCMiddleware struct { - router.IBCMiddleware -} - -func NewIBCMiddleware( - app porttypes.IBCModule, - k *keeper.Keeper, - retriesOnTimeout uint8, - forwardTimeout time.Duration, - refundTimeout time.Duration, -) IBCMiddleware { - return IBCMiddleware{ - IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), - } -} - -func (im IBCMiddleware) OnRecvPacket( - ctx sdk.Context, - packet channeltypes.Packet, - relayer sdk.AccAddress, -) ibcexported.Acknowledgement { - return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) -} From 079c9a7be722a751c980bfb46ac81a4a4fffba18 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 12:03:37 +0100 Subject: [PATCH 04/16] use custom pfm instead of original router. all test passed. --- app/app.go | 3 +-- app/keepers/keepers.go | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index b61d2be5..d38bf969 100644 --- a/app/app.go +++ b/app/app.go @@ -87,7 +87,6 @@ import ( ibcclientclient "github.com/cosmos/ibc-go/v7/modules/core/02-client/client" ibchost "github.com/cosmos/ibc-go/v7/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" - custompfm "github.com/notional-labs/composable/v6/custom/custompfm/keeper" customibctransfer "github.com/notional-labs/composable/v6/custom/ibc-transfer" customstaking "github.com/notional-labs/composable/v6/custom/staking" "github.com/spf13/cast" @@ -339,7 +338,7 @@ func NewComposableApp( enabledProposals, ) - custompfm.NewIBCMiddleware() + // custompfm.NewIBCMiddleware() // transferModule := transfer.NewAppModule(app.TransferKeeper) transferModule := customibctransfer.NewAppModule(appCodec, app.TransferKeeper, app.BankKeeper) routerModule := router.NewAppModule(app.RouterKeeper) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 588fea85..613ecf54 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -70,7 +70,6 @@ import ( custombankkeeper "github.com/notional-labs/composable/v6/custom/bank/keeper" - router "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" routerkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" routertypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" @@ -108,6 +107,7 @@ import ( stakingmiddleware "github.com/notional-labs/composable/v6/x/stakingmiddleware/keeper" stakingmiddlewaretypes "github.com/notional-labs/composable/v6/x/stakingmiddleware/types" + custompfm "github.com/notional-labs/composable/v6/custom/custompfm/keeper" ibctransfermiddleware "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/keeper" ibctransfermiddlewaretypes "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/types" ) @@ -367,7 +367,8 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.TransferMiddlewareKeeper, ) - ibcMiddlewareStack := router.NewIBCMiddleware( + ibcMiddlewareStack := custompfm.NewIBCMiddleware( + // ibcMiddlewareStack := router.NewIBCMiddleware( transfermiddlewareStack, appKeepers.RouterKeeper, 0, From d94d371bad9297a004de03d9f7dd9d1b2c661f48 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 12:43:01 +0100 Subject: [PATCH 05/16] clone the logic from original version to custom pfm to introduce fees. --- app/keepers/keepers.go | 1 + custom/custompfm/keeper/keeper.go | 222 +++++++++++++++++++++++++++++- 2 files changed, 222 insertions(+), 1 deletion(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 613ecf54..211b340e 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -374,6 +374,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( 0, routerkeeper.DefaultForwardTransferPacketTimeoutTimestamp, routerkeeper.DefaultRefundTransferPacketTimeoutTimestamp, + appKeepers.TransferMiddlewareKeeper, ) ratelimitMiddlewareStack := ratelimitmodule.NewIBCMiddleware(appKeepers.RatelimitKeeper, ibcMiddlewareStack) hooksTransferMiddleware := ibc_hooks.NewIBCMiddleware(ratelimitMiddlewareStack, &appKeepers.HooksICS4Wrapper) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index e38e19b1..b9b7476f 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -1,14 +1,22 @@ package keeper import ( + "encoding/json" + "fmt" + "strings" "time" + "github.com/armon/go-metrics" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" router "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + ibctransfermiddlewarekeeper "github.com/notional-labs/composable/v6/x/transfermiddleware/keeper" ) var _ porttypes.Middleware = &IBCMiddleware{} @@ -17,6 +25,14 @@ var _ porttypes.Middleware = &IBCMiddleware{} // forward keeper and the underlying application. type IBCMiddleware struct { router.IBCMiddleware + ibcfeekeeper ibctransfermiddlewarekeeper.Keeper + + app1 porttypes.IBCModule + keeper1 *keeper.Keeper + + retriesOnTimeout1 uint8 + forwardTimeout1 time.Duration + refundTimeout1 time.Duration } func NewIBCMiddleware( @@ -25,9 +41,18 @@ func NewIBCMiddleware( retriesOnTimeout uint8, forwardTimeout time.Duration, refundTimeout time.Duration, + ibcfeekeeper ibctransfermiddlewarekeeper.Keeper, ) IBCMiddleware { return IBCMiddleware{ IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), + ibcfeekeeper: ibcfeekeeper, + + //we need this bz this field is not exported in the parent struct + app1: app, + keeper1: k, + retriesOnTimeout1: retriesOnTimeout, + forwardTimeout1: forwardTimeout, + refundTimeout1: refundTimeout, } } @@ -36,5 +61,200 @@ func (im IBCMiddleware) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) ibcexported.Acknowledgement { - return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) + logger := im.keeper1.Logger(ctx) + + im.ibcfeekeeper.GetParams(ctx) + + var data transfertypes.FungibleTokenPacketData + if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + logger.Debug(fmt.Sprintf("packetForwardMiddleware OnRecvPacket payload is not a FungibleTokenPacketData: %s", err.Error())) + return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) + } + + logger.Debug("packetForwardMiddleware OnRecvPacket", + "sequence", packet.Sequence, + "src-channel", packet.SourceChannel, "src-port", packet.SourcePort, + "dst-channel", packet.DestinationChannel, "dst-port", packet.DestinationPort, + "amount", data.Amount, "denom", data.Denom, "memo", data.Memo, + ) + + d := make(map[string]interface{}) + err := json.Unmarshal([]byte(data.Memo), &d) + if err != nil || d["forward"] == nil { + // not a packet that should be forwarded + logger.Debug("packetForwardMiddleware OnRecvPacket forward metadata does not exist") + return im.app1.OnRecvPacket(ctx, packet, relayer) + } + m := &types.PacketMetadata{} + err = json.Unmarshal([]byte(data.Memo), m) + if err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket error parsing forward metadata", "error", err) + return newErrorAcknowledgement(fmt.Errorf("error parsing forward metadata: %w", err)) + } + + metadata := m.Forward + + goCtx := ctx.Context() + processed := getBoolFromAny(goCtx.Value(types.ProcessedKey{})) + nonrefundable := getBoolFromAny(goCtx.Value(types.NonrefundableKey{})) + disableDenomComposition := getBoolFromAny(goCtx.Value(types.DisableDenomCompositionKey{})) + + if err := metadata.Validate(); err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket forward metadata is invalid", "error", err) + return newErrorAcknowledgement(err) + } + + // override the receiver so that senders cannot move funds through arbitrary addresses. + overrideReceiver, err := getReceiver(packet.DestinationChannel, data.Sender) + if err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket failed to construct override receiver", "error", err) + return newErrorAcknowledgement(fmt.Errorf("failed to construct override receiver: %w", err)) + } + + // if this packet has been handled by another middleware in the stack there may be no need to call into the + // underlying app, otherwise the transfer module's OnRecvPacket callback could be invoked more than once + // which would mint/burn vouchers more than once + if !processed { + if err := im.receiveFunds(ctx, packet, data, overrideReceiver, relayer); err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket error receiving packet", "error", err) + return newErrorAcknowledgement(fmt.Errorf("error receiving packet: %w", err)) + } + } + + // if this packet's token denom is already the base denom for some native token on this chain, + // we do not need to do any further composition of the denom before forwarding the packet + denomOnThisChain := data.Denom + // Check if the packet was sent from Picasso + paraChainIBCTokenInfo, found := im.keeper1.GetParachainTokenInfoByAssetID(ctx, data.Denom) + if found && (paraChainIBCTokenInfo.ChannelID == packet.DestinationChannel) { + disableDenomComposition = true + denomOnThisChain = paraChainIBCTokenInfo.NativeDenom + } + + if !disableDenomComposition { + denomOnThisChain = getDenomForThisChain( + packet.DestinationPort, packet.DestinationChannel, + packet.SourcePort, packet.SourceChannel, + data.Denom, + ) + } + + amountInt, ok := sdk.NewIntFromString(data.Amount) + if !ok { + logger.Error("packetForwardMiddleware OnRecvPacket error parsing amount for forward", "amount", data.Amount) + return newErrorAcknowledgement(fmt.Errorf("error parsing amount for forward: %s", data.Amount)) + } + + token := sdk.NewCoin(denomOnThisChain, amountInt) + + timeout := time.Duration(metadata.Timeout) + + if timeout.Nanoseconds() <= 0 { + timeout = im.forwardTimeout1 + } + + var retries uint8 + if metadata.Retries != nil { + retries = *metadata.Retries + } else { + retries = im.retriesOnTimeout1 + } + + err = im.keeper1.ForwardTransferPacket(ctx, nil, packet, data.Sender, overrideReceiver, metadata, token, retries, timeout, []metrics.Label{}, nonrefundable) + if err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket error forwarding packet", "error", err) + return newErrorAcknowledgement(err) + } + + // returning nil ack will prevent WriteAcknowledgement from occurring for forwarded packet. + // This is intentional so that the acknowledgement will be written later based on the ack/timeout of the forwarded packet. + return nil + + // charge_coin := sdk.NewCoin(packet.Token.Denom, sdk.ZeroInt()) + // return channeltypes.NewErrorAcknowledgement(fmt.Errorf("error parsing forward metadata")) + // return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) +} + +func newErrorAcknowledgement(err error) channeltypes.Acknowledgement { + return channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: fmt.Sprintf("packet-forward-middleware error: %s", err.Error()), + }, + } +} + +func getBoolFromAny(value any) bool { + if value == nil { + return false + } + boolVal, ok := value.(bool) + if !ok { + return false + } + return boolVal +} + +func getReceiver(channel string, originalSender string) (string, error) { + senderStr := fmt.Sprintf("%s/%s", channel, originalSender) + senderHash32 := address.Hash(types.ModuleName, []byte(senderStr)) + sender := sdk.AccAddress(senderHash32[:20]) + bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + return sdk.Bech32ifyAddressBytes(bech32Prefix, sender) +} + +func (im IBCMiddleware) receiveFunds( + ctx sdk.Context, + packet channeltypes.Packet, + data transfertypes.FungibleTokenPacketData, + overrideReceiver string, + relayer sdk.AccAddress, +) error { + overrideData := transfertypes.FungibleTokenPacketData{ + Denom: data.Denom, + Amount: data.Amount, + Sender: data.Sender, + Receiver: overrideReceiver, // override receiver + // Memo explicitly zeroed + } + overrideDataBz := transfertypes.ModuleCdc.MustMarshalJSON(&overrideData) + overridePacket := channeltypes.Packet{ + Sequence: packet.Sequence, + SourcePort: packet.SourcePort, + SourceChannel: packet.SourceChannel, + DestinationPort: packet.DestinationPort, + DestinationChannel: packet.DestinationChannel, + Data: overrideDataBz, // override data + TimeoutHeight: packet.TimeoutHeight, + TimeoutTimestamp: packet.TimeoutTimestamp, + } + + ack := im.app1.OnRecvPacket(ctx, overridePacket, relayer) + + if ack == nil { + return fmt.Errorf("ack is nil") + } + + if !ack.Success() { + return fmt.Errorf("ack error: %s", string(ack.Acknowledgement())) + } + + return nil +} + +func getDenomForThisChain(port, channel, counterpartyPort, counterpartyChannel, denom string) string { + counterpartyPrefix := transfertypes.GetDenomPrefix(counterpartyPort, counterpartyChannel) + if strings.HasPrefix(denom, counterpartyPrefix) { + // unwind denom + unwoundDenom := denom[len(counterpartyPrefix):] + denomTrace := transfertypes.ParseDenomTrace(unwoundDenom) + if denomTrace.Path == "" { + // denom is now unwound back to native denom + return unwoundDenom + } + // denom is still IBC denom + return denomTrace.IBCDenom() + } + // append port and channel from this chain to denom + prefixedDenom := transfertypes.GetDenomPrefix(port, channel) + denom + return transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() } From 5e5010e09e983f3b8ebb4a66d4f86caea780de71 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 13:37:29 +0100 Subject: [PATCH 06/16] refactor and extract function responsible for finding fee for channel. --- custom/custompfm/keeper/keeper.go | 4 +- x/ibctransfermiddleware/keeper/keeper.go | 116 +++++++++++++++++++++++ 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index b9b7476f..f00cf7a4 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -63,14 +63,14 @@ func (im IBCMiddleware) OnRecvPacket( ) ibcexported.Acknowledgement { logger := im.keeper1.Logger(ctx) - im.ibcfeekeeper.GetParams(ctx) - var data transfertypes.FungibleTokenPacketData if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { logger.Debug(fmt.Sprintf("packetForwardMiddleware OnRecvPacket payload is not a FungibleTokenPacketData: %s", err.Error())) return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) } + // params := im.ibcfeekeeper.GetParams(ctx) + logger.Debug("packetForwardMiddleware OnRecvPacket", "sequence", packet.Sequence, "src-channel", packet.SourceChannel, "src-port", packet.SourcePort, diff --git a/x/ibctransfermiddleware/keeper/keeper.go b/x/ibctransfermiddleware/keeper/keeper.go index 597cf30a..a0f92102 100644 --- a/x/ibctransfermiddleware/keeper/keeper.go +++ b/x/ibctransfermiddleware/keeper/keeper.go @@ -1,12 +1,18 @@ package keeper import ( + "context" + "encoding/json" + "fmt" + "time" + "github.com/cometbft/cometbft/libs/log" "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/types" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + ibctypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" ) // Keeper of the staking middleware store @@ -104,3 +110,113 @@ func (k Keeper) GetChannelFeeAddress(ctx sdk.Context, targetChannelID string) st } return channelFee.FeeAddress } + +type BridgeFee struct { + fee sdk.Coin + sender sdk.AccAddress + reciever sdk.AccAddress +} + +func (k Keeper) Transfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + params := k.GetParams(ctx) + // charge_coin := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) + if params.ChannelFees != nil && len(params.ChannelFees) > 0 { + channelFee := findChannelParams(params.ChannelFees, msg.SourceChannel) + if channelFee != nil { + if channelFee.MinTimeoutTimestamp > 0 { + + goCtx := sdk.UnwrapSDKContext(goCtx) + blockTime := goCtx.BlockTime() + + timeoutTimeInFuture := time.Unix(0, int64(msg.TimeoutTimestamp)) + if timeoutTimeInFuture.Before(blockTime) { + return nil, fmt.Errorf("incorrect timeout timestamp found during ibc transfer. timeout timestamp is in the past") + } + + difference := timeoutTimeInFuture.Sub(blockTime).Nanoseconds() + if difference < channelFee.MinTimeoutTimestamp { + return nil, fmt.Errorf("incorrect timeout timestamp found during ibc transfer. too soon") + } + } + coin := findCoinByDenom(channelFee.AllowedTokens, msg.Token.Denom) + if coin == nil { + return nil, fmt.Errorf("token not allowed to be transferred in this channel") + } + + minFee := coin.MinFee.Amount + priority := GetPriority(msg.Memo) + if priority != nil { + p := findPriority(coin.TxPriorityFee, *priority) + if p != nil && coin.MinFee.Denom == p.PriorityFee.Denom { + minFee = minFee.Add(p.PriorityFee.Amount) + } + } + + charge := minFee + if charge.GT(msg.Token.Amount) { + charge = msg.Token.Amount + } + + newAmount := msg.Token.Amount.Sub(charge) + + if newAmount.IsPositive() { + percentageCharge := newAmount.QuoRaw(coin.Percentage) + newAmount = newAmount.Sub(percentageCharge) + charge = charge.Add(percentageCharge) + } + + msgSender, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, err + } + + feeAddress, err := sdk.AccAddressFromBech32(channelFee.FeeAddress) + if err != nil { + return nil, err + } + + charge_coin := sdk.NewCoin(msg.Token.Denom, charge) + // send_err := k.bank.SendCoins(ctx, msgSender, feeAddress, sdk.NewCoins(charge_coin)) + // if send_err != nil { + // return nil, send_err + // } + msg.Token.Amount = newAmount + return &BridgeFee{fee: charge_coin, sender: msgSender, reciever: feeAddress}, nil + + // if newAmount.LTE(sdk.ZeroInt()) { + // zeroTransfer := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) + // return &zeroTransfer, nil + // } + } + } + // ret, err := k.Keeper.Transfer(goCtx, msg) + // if err == nil && ret != nil && !charge_coin.IsZero() { + // if !charge_coin.IsZero() { + // k.SetSequenceFee(ctx, ret.Sequence, charge_coin) + // } + return nil, nil +} + +func GetPriority(jsonString string) *string { + var data map[string]interface{} + if err := json.Unmarshal([]byte(jsonString), &data); err != nil { + return nil + } + + priority, ok := data["priority"].(string) + if !ok { + return nil + } + + return &priority +} + +func findPriority(priorities []*types.TxPriorityFee, priority string) *types.TxPriorityFee { + for _, p := range priorities { + if p.Priority == priority { + return p + } + } + return nil +} From 80887ffd6730ca67c0c0a00fc67d68b7e93eeb89 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 13:45:20 +0100 Subject: [PATCH 07/16] add bank keeper into custom pfm module --- app/keepers/keepers.go | 1 + custom/custompfm/keeper/keeper.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 211b340e..223b9ca9 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -375,6 +375,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( routerkeeper.DefaultForwardTransferPacketTimeoutTimestamp, routerkeeper.DefaultRefundTransferPacketTimeoutTimestamp, appKeepers.TransferMiddlewareKeeper, + &appKeepers.BankKeeper, ) ratelimitMiddlewareStack := ratelimitmodule.NewIBCMiddleware(appKeepers.RatelimitKeeper, ibcMiddlewareStack) hooksTransferMiddleware := ibc_hooks.NewIBCMiddleware(ratelimitMiddlewareStack, &appKeepers.HooksICS4Wrapper) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index f00cf7a4..22c29c11 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -16,6 +16,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + custombankkeeper "github.com/notional-labs/composable/v6/custom/bank/keeper" ibctransfermiddlewarekeeper "github.com/notional-labs/composable/v6/x/transfermiddleware/keeper" ) @@ -33,6 +34,7 @@ type IBCMiddleware struct { retriesOnTimeout1 uint8 forwardTimeout1 time.Duration refundTimeout1 time.Duration + bank *custombankkeeper.Keeper } func NewIBCMiddleware( @@ -42,6 +44,7 @@ func NewIBCMiddleware( forwardTimeout time.Duration, refundTimeout time.Duration, ibcfeekeeper ibctransfermiddlewarekeeper.Keeper, + bankkeeper *custombankkeeper.Keeper, ) IBCMiddleware { return IBCMiddleware{ IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), @@ -53,6 +56,7 @@ func NewIBCMiddleware( retriesOnTimeout1: retriesOnTimeout, forwardTimeout1: forwardTimeout, refundTimeout1: refundTimeout, + bank: bankkeeper, } } From 8ec75856750c8aa33532e02cd02e15fdd2601563 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 14:47:20 +0100 Subject: [PATCH 08/16] charge fee if needed and return ack if fee > amount --- app/keepers/keepers.go | 2 +- custom/custompfm/keeper/keeper.go | 69 ++++++++++++++++++++++-- x/ibctransfermiddleware/keeper/keeper.go | 8 +-- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 223b9ca9..0c313d38 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -374,7 +374,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( 0, routerkeeper.DefaultForwardTransferPacketTimeoutTimestamp, routerkeeper.DefaultRefundTransferPacketTimeoutTimestamp, - appKeepers.TransferMiddlewareKeeper, + &appKeepers.IbcTransferMiddlewareKeeper, &appKeepers.BankKeeper, ) ratelimitMiddlewareStack := ratelimitmodule.NewIBCMiddleware(appKeepers.RatelimitKeeper, ibcMiddlewareStack) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index 22c29c11..e51ce1b8 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -13,11 +13,12 @@ import ( "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" custombankkeeper "github.com/notional-labs/composable/v6/custom/bank/keeper" - ibctransfermiddlewarekeeper "github.com/notional-labs/composable/v6/x/transfermiddleware/keeper" + ibctransfermiddlewarekeeper "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/keeper" ) var _ porttypes.Middleware = &IBCMiddleware{} @@ -26,7 +27,6 @@ var _ porttypes.Middleware = &IBCMiddleware{} // forward keeper and the underlying application. type IBCMiddleware struct { router.IBCMiddleware - ibcfeekeeper ibctransfermiddlewarekeeper.Keeper app1 porttypes.IBCModule keeper1 *keeper.Keeper @@ -34,6 +34,7 @@ type IBCMiddleware struct { retriesOnTimeout1 uint8 forwardTimeout1 time.Duration refundTimeout1 time.Duration + ibcfeekeeper *ibctransfermiddlewarekeeper.Keeper bank *custombankkeeper.Keeper } @@ -43,7 +44,7 @@ func NewIBCMiddleware( retriesOnTimeout uint8, forwardTimeout time.Duration, refundTimeout time.Duration, - ibcfeekeeper ibctransfermiddlewarekeeper.Keeper, + ibcfeekeeper *ibctransfermiddlewarekeeper.Keeper, bankkeeper *custombankkeeper.Keeper, ) IBCMiddleware { return IBCMiddleware{ @@ -164,6 +165,66 @@ func (im IBCMiddleware) OnRecvPacket( retries = im.retriesOnTimeout1 } + // im.ibcfeekeeper.Transfer() + + feeAmount := sdk.NewDecFromInt(token.Amount).Mul(im.keeper1.GetFeePercentage(ctx)).RoundInt() + packetAmount := token.Amount.Sub(feeAmount) + packetCoin := sdk.NewCoin(token.Denom, packetAmount) + + memo := "" + + // set memo for next transfer with next from this transfer. + if metadata.Next != nil { + memoBz, err := json.Marshal(metadata.Next) + if err != nil { + im.keeper1.Logger(ctx).Error("packetForwardMiddleware error marshaling next as JSON", + "error", err, + ) + // return errorsmod.Wrapf(sdkerrors.ErrJSONMarshal, err.Error()) + } + memo = string(memoBz) + } + + tr := transfertypes.NewMsgTransfer( + metadata.Port, + metadata.Channel, + packetCoin, + overrideReceiver, + metadata.Receiver, + clienttypes.Height{ + RevisionNumber: 0, + RevisionHeight: 0, + }, + uint64(ctx.BlockTime().UnixNano())+uint64(timeout.Nanoseconds()), + memo, + ) + + result, err := im.ibcfeekeeper.ChargeFee(goCtx, tr) + if err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket error charging fee", "error", err) + return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) + } + if result != nil { + if token.Amount.LTE(result.Fee.Amount) { + token = token.SubAmount(result.Fee.Amount) + } else { + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) //?????? + return ack + // logger.Error("fee is greater than the amount", "error") + // return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) + } + + // else { + // logger.Error("fee is greater than the amount", "error") + // return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) + // } + // token = sdk.NewCoin(result.Fee.Denom, result.Fee.Amount) + } + + // //fi amount < fee. it is spamer. we do not need proceed this packet. no timeout for this packet + // ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) + // return ack + err = im.keeper1.ForwardTransferPacket(ctx, nil, packet, data.Sender, overrideReceiver, metadata, token, retries, timeout, []metrics.Label{}, nonrefundable) if err != nil { logger.Error("packetForwardMiddleware OnRecvPacket error forwarding packet", "error", err) @@ -176,7 +237,7 @@ func (im IBCMiddleware) OnRecvPacket( // charge_coin := sdk.NewCoin(packet.Token.Denom, sdk.ZeroInt()) // return channeltypes.NewErrorAcknowledgement(fmt.Errorf("error parsing forward metadata")) - // return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) + return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) } func newErrorAcknowledgement(err error) channeltypes.Acknowledgement { diff --git a/x/ibctransfermiddleware/keeper/keeper.go b/x/ibctransfermiddleware/keeper/keeper.go index a0f92102..9ce644f5 100644 --- a/x/ibctransfermiddleware/keeper/keeper.go +++ b/x/ibctransfermiddleware/keeper/keeper.go @@ -112,12 +112,12 @@ func (k Keeper) GetChannelFeeAddress(ctx sdk.Context, targetChannelID string) st } type BridgeFee struct { - fee sdk.Coin - sender sdk.AccAddress - reciever sdk.AccAddress + Fee sdk.Coin + Sender sdk.AccAddress + Reciever sdk.AccAddress } -func (k Keeper) Transfer(goCtx context.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { +func (k Keeper) ChargeFee(goCtx context.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { ctx := sdk.UnwrapSDKContext(goCtx) params := k.GetParams(ctx) // charge_coin := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) From 458157a314e78dba096e3b4271a5189c9117fae7 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 14:59:04 +0100 Subject: [PATCH 09/16] added todo. to not forgot. --- custom/custompfm/keeper/keeper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index e51ce1b8..2c54111b 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -205,9 +205,10 @@ func (im IBCMiddleware) OnRecvPacket( return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) } if result != nil { - if token.Amount.LTE(result.Fee.Amount) { + if token.Amount.GTE(result.Fee.Amount) { token = token.SubAmount(result.Fee.Amount) } else { + //bank.send.......... ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) //?????? return ack // logger.Error("fee is greater than the amount", "error") From de17a3156a2cf525ecd6e0e0c375b8a4aa65674a Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 15:07:59 +0100 Subject: [PATCH 10/16] use bank. --- custom/custompfm/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index 2c54111b..aeeb5536 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -208,7 +208,7 @@ func (im IBCMiddleware) OnRecvPacket( if token.Amount.GTE(result.Fee.Amount) { token = token.SubAmount(result.Fee.Amount) } else { - //bank.send.......... + // send_err := im.bank.SendCoins(ctx, msgSender, feeAddress, sdk.NewCoins(charge_coin)) ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) //?????? return ack // logger.Error("fee is greater than the amount", "error") From 75baa0d31f6475d4f56bb65cc2e9ff7326ba56be Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 16:52:17 +0100 Subject: [PATCH 11/16] all test passed. with a new custom pfm module with a fee. --- custom/custompfm/keeper/keeper.go | 24 ++++++++---------------- x/ibctransfermiddleware/keeper/keeper.go | 9 +++------ 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index aeeb5536..48432a29 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -199,33 +199,25 @@ func (im IBCMiddleware) OnRecvPacket( memo, ) - result, err := im.ibcfeekeeper.ChargeFee(goCtx, tr) + result, err := im.ibcfeekeeper.ChargeFee(ctx, tr) if err != nil { logger.Error("packetForwardMiddleware OnRecvPacket error charging fee", "error", err) return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) } if result != nil { - if token.Amount.GTE(result.Fee.Amount) { + if result.Fee.Amount.LT(token.Amount) { token = token.SubAmount(result.Fee.Amount) } else { - // send_err := im.bank.SendCoins(ctx, msgSender, feeAddress, sdk.NewCoins(charge_coin)) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) //?????? + send_err := im.bank.SendCoins(ctx, result.Sender, result.Reciever, sdk.NewCoins(result.Fee)) + if send_err != nil { + logger.Error("packetForwardMiddleware OnRecvPacket error sending fee", "error", send_err) + return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", send_err)) + } + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) return ack - // logger.Error("fee is greater than the amount", "error") - // return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) } - - // else { - // logger.Error("fee is greater than the amount", "error") - // return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", err)) - // } - // token = sdk.NewCoin(result.Fee.Denom, result.Fee.Amount) } - // //fi amount < fee. it is spamer. we do not need proceed this packet. no timeout for this packet - // ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - // return ack - err = im.keeper1.ForwardTransferPacket(ctx, nil, packet, data.Sender, overrideReceiver, metadata, token, retries, timeout, []metrics.Label{}, nonrefundable) if err != nil { logger.Error("packetForwardMiddleware OnRecvPacket error forwarding packet", "error", err) diff --git a/x/ibctransfermiddleware/keeper/keeper.go b/x/ibctransfermiddleware/keeper/keeper.go index 9ce644f5..bf8b95d0 100644 --- a/x/ibctransfermiddleware/keeper/keeper.go +++ b/x/ibctransfermiddleware/keeper/keeper.go @@ -1,7 +1,6 @@ package keeper import ( - "context" "encoding/json" "fmt" "time" @@ -117,8 +116,7 @@ type BridgeFee struct { Reciever sdk.AccAddress } -func (k Keeper) ChargeFee(goCtx context.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { - ctx := sdk.UnwrapSDKContext(goCtx) +func (k Keeper) ChargeFee(ctx sdk.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { params := k.GetParams(ctx) // charge_coin := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) if params.ChannelFees != nil && len(params.ChannelFees) > 0 { @@ -126,8 +124,7 @@ func (k Keeper) ChargeFee(goCtx context.Context, msg *ibctypes.MsgTransfer) (*Br if channelFee != nil { if channelFee.MinTimeoutTimestamp > 0 { - goCtx := sdk.UnwrapSDKContext(goCtx) - blockTime := goCtx.BlockTime() + blockTime := ctx.BlockTime() timeoutTimeInFuture := time.Unix(0, int64(msg.TimeoutTimestamp)) if timeoutTimeInFuture.Before(blockTime) { @@ -182,7 +179,7 @@ func (k Keeper) ChargeFee(goCtx context.Context, msg *ibctypes.MsgTransfer) (*Br // return nil, send_err // } msg.Token.Amount = newAmount - return &BridgeFee{fee: charge_coin, sender: msgSender, reciever: feeAddress}, nil + return &BridgeFee{Fee: charge_coin, Sender: msgSender, Reciever: feeAddress}, nil // if newAmount.LTE(sdk.ZeroInt()) { // zeroTransfer := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) From 486a490e72e837505a540c1bf189fab5e58ac65e Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 16:53:19 +0100 Subject: [PATCH 12/16] remove unreachable code. --- custom/custompfm/keeper/keeper.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index 48432a29..58e2ee1d 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -74,8 +74,6 @@ func (im IBCMiddleware) OnRecvPacket( return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) } - // params := im.ibcfeekeeper.GetParams(ctx) - logger.Debug("packetForwardMiddleware OnRecvPacket", "sequence", packet.Sequence, "src-channel", packet.SourceChannel, "src-port", packet.SourcePort, @@ -227,10 +225,6 @@ func (im IBCMiddleware) OnRecvPacket( // returning nil ack will prevent WriteAcknowledgement from occurring for forwarded packet. // This is intentional so that the acknowledgement will be written later based on the ack/timeout of the forwarded packet. return nil - - // charge_coin := sdk.NewCoin(packet.Token.Denom, sdk.ZeroInt()) - // return channeltypes.NewErrorAcknowledgement(fmt.Errorf("error parsing forward metadata")) - return im.IBCMiddleware.OnRecvPacket(ctx, packet, relayer) } func newErrorAcknowledgement(err error) channeltypes.Acknowledgement { From 566074f26db6b5a759302604e90c0f3f76e48d25 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 17:00:17 +0100 Subject: [PATCH 13/16] fix lint --- custom/custompfm/keeper/keeper.go | 3 +-- x/ibctransfermiddleware/keeper/keeper.go | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index 58e2ee1d..9496a035 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -51,7 +51,6 @@ func NewIBCMiddleware( IBCMiddleware: router.NewIBCMiddleware(app, k, retriesOnTimeout, forwardTimeout, refundTimeout), ibcfeekeeper: ibcfeekeeper, - //we need this bz this field is not exported in the parent struct app1: app, keeper1: k, retriesOnTimeout1: retriesOnTimeout, @@ -206,7 +205,7 @@ func (im IBCMiddleware) OnRecvPacket( if result.Fee.Amount.LT(token.Amount) { token = token.SubAmount(result.Fee.Amount) } else { - send_err := im.bank.SendCoins(ctx, result.Sender, result.Reciever, sdk.NewCoins(result.Fee)) + send_err := im.bank.SendCoins(ctx, result.Sender, result.Receiver, sdk.NewCoins(result.Fee)) if send_err != nil { logger.Error("packetForwardMiddleware OnRecvPacket error sending fee", "error", send_err) return newErrorAcknowledgement(fmt.Errorf("error charging fee: %w", send_err)) diff --git a/x/ibctransfermiddleware/keeper/keeper.go b/x/ibctransfermiddleware/keeper/keeper.go index bf8b95d0..d43741d6 100644 --- a/x/ibctransfermiddleware/keeper/keeper.go +++ b/x/ibctransfermiddleware/keeper/keeper.go @@ -113,7 +113,7 @@ func (k Keeper) GetChannelFeeAddress(ctx sdk.Context, targetChannelID string) st type BridgeFee struct { Fee sdk.Coin Sender sdk.AccAddress - Reciever sdk.AccAddress + Receiver sdk.AccAddress } func (k Keeper) ChargeFee(ctx sdk.Context, msg *ibctypes.MsgTransfer) (*BridgeFee, error) { @@ -179,7 +179,7 @@ func (k Keeper) ChargeFee(ctx sdk.Context, msg *ibctypes.MsgTransfer) (*BridgeFe // return nil, send_err // } msg.Token.Amount = newAmount - return &BridgeFee{Fee: charge_coin, Sender: msgSender, Reciever: feeAddress}, nil + return &BridgeFee{Fee: charge_coin, Sender: msgSender, Receiver: feeAddress}, nil // if newAmount.LTE(sdk.ZeroInt()) { // zeroTransfer := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) From d5637a1d9701fdd876975d86dbba1979304e5202 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 17:24:57 +0100 Subject: [PATCH 14/16] remove custom logic in ibc transfer keeper. --- custom/ibc-transfer/keeper/keeper.go | 104 +-------------------------- 1 file changed, 1 insertion(+), 103 deletions(-) diff --git a/custom/ibc-transfer/keeper/keeper.go b/custom/ibc-transfer/keeper/keeper.go index 469c2eab..60f2ae52 100644 --- a/custom/ibc-transfer/keeper/keeper.go +++ b/custom/ibc-transfer/keeper/keeper.go @@ -2,22 +2,17 @@ package keeper import ( "context" - "encoding/json" - "fmt" - "time" "github.com/cosmos/cosmos-sdk/codec" ibctransferkeeper "github.com/cosmos/ibc-go/v7/modules/apps/transfer/keeper" storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" "github.com/cosmos/ibc-go/v7/modules/core/exported" custombankkeeper "github.com/notional-labs/composable/v6/custom/bank/keeper" ibctransfermiddleware "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/keeper" - ibctransfermiddlewaretypes "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/types" ) type Keeper struct { @@ -57,102 +52,5 @@ func NewKeeper( // If the transfer amount is less than the minimum fee, it will charge the full transfer amount. // If the transfer amount is greater than the minimum fee, it will charge the minimum fee and the percentage fee. func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - params := k.IbcTransfermiddleware.GetParams(ctx) - charge_coin := sdk.NewCoin(msg.Token.Denom, sdk.ZeroInt()) - if params.ChannelFees != nil && len(params.ChannelFees) > 0 { - channelFee := findChannelParams(params.ChannelFees, msg.SourceChannel) - if channelFee != nil { - if channelFee.MinTimeoutTimestamp > 0 { - - goCtx := sdk.UnwrapSDKContext(goCtx) - blockTime := goCtx.BlockTime() - - timeoutTimeInFuture := time.Unix(0, int64(msg.TimeoutTimestamp)) - if timeoutTimeInFuture.Before(blockTime) { - return nil, fmt.Errorf("incorrect timeout timestamp found during ibc transfer. timeout timestamp is in the past") - } - - difference := timeoutTimeInFuture.Sub(blockTime).Nanoseconds() - if difference < channelFee.MinTimeoutTimestamp { - return nil, fmt.Errorf("incorrect timeout timestamp found during ibc transfer. too soon") - } - } - coin := findCoinByDenom(channelFee.AllowedTokens, msg.Token.Denom) - if coin == nil { - return nil, fmt.Errorf("token not allowed to be transferred in this channel") - } - - minFee := coin.MinFee.Amount - priority := GetPriority(msg.Memo) - if priority != nil { - p := findPriority(coin.TxPriorityFee, *priority) - if p != nil && coin.MinFee.Denom == p.PriorityFee.Denom { - minFee = minFee.Add(p.PriorityFee.Amount) - } - } - - charge := minFee - if charge.GT(msg.Token.Amount) { - charge = msg.Token.Amount - } - - newAmount := msg.Token.Amount.Sub(charge) - - if newAmount.IsPositive() { - percentageCharge := newAmount.QuoRaw(coin.Percentage) - newAmount = newAmount.Sub(percentageCharge) - charge = charge.Add(percentageCharge) - } - - msgSender, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - return nil, err - } - - feeAddress, err := sdk.AccAddressFromBech32(channelFee.FeeAddress) - if err != nil { - return nil, err - } - - charge_coin = sdk.NewCoin(msg.Token.Denom, charge) - send_err := k.bank.SendCoins(ctx, msgSender, feeAddress, sdk.NewCoins(charge_coin)) - if send_err != nil { - return nil, send_err - } - - if newAmount.LTE(sdk.ZeroInt()) { - return &types.MsgTransferResponse{}, nil - } - msg.Token.Amount = newAmount - } - } - ret, err := k.Keeper.Transfer(goCtx, msg) - if err == nil && ret != nil && !charge_coin.IsZero() { - k.IbcTransfermiddleware.SetSequenceFee(ctx, ret.Sequence, charge_coin) - } - return ret, err -} - -func GetPriority(jsonString string) *string { - var data map[string]interface{} - if err := json.Unmarshal([]byte(jsonString), &data); err != nil { - return nil - } - - priority, ok := data["priority"].(string) - if !ok { - return nil - } - - return &priority -} - -func findPriority(priorities []*ibctransfermiddlewaretypes.TxPriorityFee, priority string) *ibctransfermiddlewaretypes.TxPriorityFee { - for _, p := range priorities { - if p.Priority == priority { - return p - } - } - return nil + return k.Keeper.Transfer(goCtx, msg) } From 1ba80f05e541d0948a3d8848f961287f359203e5 Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 22 May 2024 19:31:58 +0100 Subject: [PATCH 15/16] fix build --- custom/ibc-transfer/keeper/keeper.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/custom/ibc-transfer/keeper/keeper.go b/custom/ibc-transfer/keeper/keeper.go index 60f2ae52..349a2925 100644 --- a/custom/ibc-transfer/keeper/keeper.go +++ b/custom/ibc-transfer/keeper/keeper.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "encoding/json" "github.com/cosmos/cosmos-sdk/codec" ibctransferkeeper "github.com/cosmos/ibc-go/v7/modules/apps/transfer/keeper" @@ -13,6 +14,7 @@ import ( "github.com/cosmos/ibc-go/v7/modules/core/exported" custombankkeeper "github.com/notional-labs/composable/v6/custom/bank/keeper" ibctransfermiddleware "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/keeper" + ibctransfermiddlewaretypes "github.com/notional-labs/composable/v6/x/ibctransfermiddleware/types" ) type Keeper struct { @@ -54,3 +56,26 @@ func NewKeeper( func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { return k.Keeper.Transfer(goCtx, msg) } + +func GetPriority(jsonString string) *string { + var data map[string]interface{} + if err := json.Unmarshal([]byte(jsonString), &data); err != nil { + return nil + } + + priority, ok := data["priority"].(string) + if !ok { + return nil + } + + return &priority +} + +func findPriority(priorities []*ibctransfermiddlewaretypes.TxPriorityFee, priority string) *ibctransfermiddlewaretypes.TxPriorityFee { + for _, p := range priorities { + if p.Priority == priority { + return p + } + } + return nil +} From be2db57035cb9a025c1a039b95fd05ba060c71a2 Mon Sep 17 00:00:00 2001 From: rustdev Date: Thu, 23 May 2024 15:52:10 +0100 Subject: [PATCH 16/16] remove commented code. --- custom/custompfm/keeper/keeper.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/custom/custompfm/keeper/keeper.go b/custom/custompfm/keeper/keeper.go index 9496a035..27150ee4 100644 --- a/custom/custompfm/keeper/keeper.go +++ b/custom/custompfm/keeper/keeper.go @@ -162,8 +162,6 @@ func (im IBCMiddleware) OnRecvPacket( retries = im.retriesOnTimeout1 } - // im.ibcfeekeeper.Transfer() - feeAmount := sdk.NewDecFromInt(token.Amount).Mul(im.keeper1.GetFeePercentage(ctx)).RoundInt() packetAmount := token.Amount.Sub(feeAmount) packetCoin := sdk.NewCoin(token.Denom, packetAmount) @@ -177,7 +175,6 @@ func (im IBCMiddleware) OnRecvPacket( im.keeper1.Logger(ctx).Error("packetForwardMiddleware error marshaling next as JSON", "error", err, ) - // return errorsmod.Wrapf(sdkerrors.ErrJSONMarshal, err.Error()) } memo = string(memoBz) }