Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement custom transfer method for ibc transfer wrapper keeper. #482

Merged
merged 4 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@

appKeepers.StakingMiddlewareKeeper = stakingmiddleware.NewKeeper(appCodec, appKeepers.keys[stakingmiddlewaretypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
appKeepers.IbcTransferMiddlewareKeeper = ibctransfermiddleware.NewKeeper(appCodec, appKeepers.keys[ibctransfermiddlewaretypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String(),
[]string{"centauri1ay9y5uns9khw2kzaqr3r33v2pkuptfnnr93j5j",

Check failure on line 199 in app/keepers/keepers.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)
"centauri14lz7gaw92valqjearnye4shex7zg2p05mlx9q0",
"centauri1r2zlh2xn85v8ljmwymnfrnsmdzjl7k6w6lytan",
"centauri10556m38z4x6pqalr9rl5ytf3cff8q46nk85k9m",
Expand Down Expand Up @@ -304,7 +304,7 @@
appKeepers.GetSubspace(transfermiddlewaretypes.ModuleName),
appCodec,
&appKeepers.RatelimitKeeper,
&appKeepers.TransferKeeper.Keeper,
&appKeepers.TransferKeeper,
appKeepers.BankKeeper,
authorityAddress,
)
Expand All @@ -319,7 +319,7 @@
appCodec,
appKeepers.keys[routertypes.StoreKey],
appKeepers.GetSubspace(routertypes.ModuleName),
appKeepers.TransferKeeper.Keeper,
appKeepers.TransferKeeper,
appKeepers.IBCKeeper.ChannelKeeper,
&appKeepers.DistrKeeper,
appKeepers.BankKeeper,
Expand All @@ -337,6 +337,7 @@
appKeepers.BankKeeper,
appKeepers.ScopedTransferKeeper,
&appKeepers.IbcTransferMiddlewareKeeper,
&appKeepers.BankKeeper,
)

appKeepers.RouterKeeper.SetTransferKeeper(appKeepers.TransferKeeper)
Expand Down Expand Up @@ -408,7 +409,7 @@
appKeepers.IBCKeeper.ChannelKeeper,
&appKeepers.IBCKeeper.PortKeeper,
appKeepers.ScopedWasmKeeper,
appKeepers.TransferKeeper.Keeper,
appKeepers.TransferKeeper,
bApp.MsgServiceRouter(),
bApp.GRPCQueryRouter(),
wasmDir,
Expand Down
79 changes: 79 additions & 0 deletions custom/ibc-transfer/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
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"
)

type Keeper struct {
ibctransferkeeper.Keeper
cdc codec.BinaryCodec
IbcTransfermiddleware *ibctransfermiddleware.Keeper
bank *custombankkeeper.Keeper
}

func NewKeeper(
Expand All @@ -29,11 +36,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.Keeper.Transfer(goCtx, msg)
}
Loading