From 17ecf0292dde1c1893b93828fca78eda3a05e958 Mon Sep 17 00:00:00 2001 From: rustdev Date: Tue, 2 Apr 2024 23:34:15 +0100 Subject: [PATCH 1/4] implement custom transfer method for keeper. --- app/keepers/keepers.go | 6 +-- custom/ibc-transfer/keeper/keeper.go | 81 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index ddcfd9bbe..4386258f3 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -304,7 +304,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.GetSubspace(transfermiddlewaretypes.ModuleName), appCodec, &appKeepers.RatelimitKeeper, - &appKeepers.TransferKeeper.Keeper, + &appKeepers.TransferKeeper, //the solution to introduce the transfer keeper to the middleware appKeepers.BankKeeper, authorityAddress, ) @@ -319,7 +319,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appCodec, appKeepers.keys[routertypes.StoreKey], appKeepers.GetSubspace(routertypes.ModuleName), - appKeepers.TransferKeeper.Keeper, + appKeepers.TransferKeeper, appKeepers.IBCKeeper.ChannelKeeper, &appKeepers.DistrKeeper, appKeepers.BankKeeper, @@ -408,7 +408,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.IBCKeeper.ChannelKeeper, &appKeepers.IBCKeeper.PortKeeper, appKeepers.ScopedWasmKeeper, - appKeepers.TransferKeeper.Keeper, + appKeepers.TransferKeeper, bApp.MsgServiceRouter(), bApp.GRPCQueryRouter(), wasmDir, diff --git a/custom/ibc-transfer/keeper/keeper.go b/custom/ibc-transfer/keeper/keeper.go index cc4bc6773..6b1eb7e10 100644 --- a/custom/ibc-transfer/keeper/keeper.go +++ b/custom/ibc-transfer/keeper/keeper.go @@ -1,6 +1,8 @@ package keeper import ( + "context" + "github.com/cosmos/cosmos-sdk/codec" ibctransferkeeper "github.com/cosmos/ibc-go/v7/modules/apps/transfer/keeper" @@ -9,13 +11,20 @@ import ( "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" + + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" ) type Keeper struct { ibctransferkeeper.Keeper cdc codec.BinaryCodec IbcTransfermiddleware *ibctransfermiddleware.Keeper + bank *custombankkeeper.Keeper } func NewKeeper( @@ -29,11 +38,83 @@ func NewKeeper( bk types.BankKeeper, scopedKeeper exported.ScopedKeeper, ibcTransfermiddleware *ibctransfermiddleware.Keeper, + bankKeeper *custombankkeeper.Keeper, ) Keeper { keeper := Keeper{ Keeper: ibctransferkeeper.NewKeeper(cdc, key, paramSpace, ics4Wrapper, channelKeeper, portKeeper, authKeeper, bk, scopedKeeper), IbcTransfermiddleware: ibcTransfermiddleware, cdc: cdc, + bank: bankKeeper, } return keeper } + +// Transfer is the server API around the Transfer method of the IBC transfer module. +// It checks if the sender is allowed to transfer the token and if the channel has fees. +// If the channel has fees, it will charge the sender and send the fees to the fee address. +// If the sender is not allowed to transfer the token because this tokens does not exists in the allowed tokens list, it just return without doing anything. +// If the sender is allowed to transfer the token, it will call the original transfer method. +// 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) + 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 + 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 + } + + send_err := k.bank.SendCoins(ctx, msgSender, feeAddress, sdk.NewCoins(sdk.NewCoin(msg.Token.Denom, charge))) + if send_err != nil { + return nil, send_err + } + + if newAmount.LTE(sdk.ZeroInt()) { + return &types.MsgTransferResponse{}, nil + } + msg.Token.Amount = newAmount + } + } + return k.Transfer(goCtx, msg) +} From 4cbbf0148cb3474b732a12d7ec6ba9ea9ca44c8b Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 3 Apr 2024 10:06:24 +0100 Subject: [PATCH 2/4] add param to new keeper call. --- app/keepers/keepers.go | 1 + 1 file changed, 1 insertion(+) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 4386258f3..d99eb5b91 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -337,6 +337,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.BankKeeper, appKeepers.ScopedTransferKeeper, &appKeepers.IbcTransferMiddlewareKeeper, + &appKeepers.BankKeeper, ) appKeepers.RouterKeeper.SetTransferKeeper(appKeepers.TransferKeeper) From 01878848c01e5441361d4844f733bd85c861665f Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 3 Apr 2024 10:13:52 +0100 Subject: [PATCH 3/4] call the default keeper Transfer instead of recursion. --- custom/ibc-transfer/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom/ibc-transfer/keeper/keeper.go b/custom/ibc-transfer/keeper/keeper.go index 6b1eb7e10..08ac54a00 100644 --- a/custom/ibc-transfer/keeper/keeper.go +++ b/custom/ibc-transfer/keeper/keeper.go @@ -116,5 +116,5 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types. msg.Token.Amount = newAmount } } - return k.Transfer(goCtx, msg) + return k.Keeper.Transfer(goCtx, msg) } From fd055bca72e7eb82e0f157c9415b7a538d8d507a Mon Sep 17 00:00:00 2001 From: rustdev Date: Wed, 3 Apr 2024 10:25:34 +0100 Subject: [PATCH 4/4] fix lint --- app/keepers/keepers.go | 2 +- custom/ibc-transfer/keeper/keeper.go | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index d99eb5b91..334e16d07 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -304,7 +304,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.GetSubspace(transfermiddlewaretypes.ModuleName), appCodec, &appKeepers.RatelimitKeeper, - &appKeepers.TransferKeeper, //the solution to introduce the transfer keeper to the middleware + &appKeepers.TransferKeeper, appKeepers.BankKeeper, authorityAddress, ) diff --git a/custom/ibc-transfer/keeper/keeper.go b/custom/ibc-transfer/keeper/keeper.go index 08ac54a00..4d1fdcbc3 100644 --- a/custom/ibc-transfer/keeper/keeper.go +++ b/custom/ibc-transfer/keeper/keeper.go @@ -2,22 +2,20 @@ package keeper import ( "context" + "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" - - "fmt" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" ) type Keeper struct {