From 1971cc2da77b495ed5909d27cb37d3994089197f Mon Sep 17 00:00:00 2001 From: vishal Date: Fri, 20 Sep 2024 12:12:17 +0530 Subject: [PATCH] chore: added denom resolver logic for feemarket --- ante/ante_feeabs_feemarket.go | 114 ++++++++++++++++++++++++++++++++++ ante/errors.go | 17 +++++ app/app.go | 9 ++- 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 ante/ante_feeabs_feemarket.go create mode 100644 ante/errors.go diff --git a/ante/ante_feeabs_feemarket.go b/ante/ante_feeabs_feemarket.go new file mode 100644 index 000000000..e770b7c84 --- /dev/null +++ b/ante/ante_feeabs_feemarket.go @@ -0,0 +1,114 @@ +package ante + +import ( + "fmt" + + feeabskeeper "github.com/osmosis-labs/fee-abstraction/v7/x/feeabs/keeper" + feeabstypes "github.com/osmosis-labs/fee-abstraction/v7/x/feeabs/types" + feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DenomResolverImpl is Gaia's implementation of x/feemarket's DenomResolver +type DenomResolverImpl struct { + FeeabsKeeper feeabskeeper.Keeper + StakingKeeper feeabstypes.StakingKeeper +} + +var _ feemarkettypes.DenomResolver = &DenomResolverImpl{} + +// ConvertToDenom converts any given coin to the native denom of the chain or the other way around. +// Return error if neither of coin.Denom and denom is the native denom of the chain. +// If the denom is the bond denom, convert `coin` to the native denom. return error if coin.Denom is not in the allowed list +// If the denom is not the bond denom, convert the `coin` to the given denom. return error if denom is not in the allowed list +func (r *DenomResolverImpl) ConvertToDenom(ctx sdk.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error) { + bondDenom := r.StakingKeeper.BondDenom(ctx) + fmt.Println("Here>>>>>>>>>>>>>>>> ConvertToDenom and bondDenom and denom", bondDenom, denom, coin) + if denom != bondDenom && coin.Denom != bondDenom { + return sdk.DecCoin{}, ErrNeitherNativeDenom(coin.Denom, denom) + } + var amount sdk.Coins + var hostZoneConfig feeabstypes.HostChainFeeAbsConfig + var found bool + var err error + + if denom == bondDenom { + + fmt.Println("Here<<<<<<<<<<<<<<<<<<< in if statement") + hostZoneConfig, found = r.FeeabsKeeper.GetHostZoneConfig(ctx, coin.Denom) + if !found { + return sdk.DecCoin{}, ErrDenomNotRegistered(coin.Denom) + } + amount, err = r.getIBCCoinFromNative(ctx, sdk.NewCoins(sdk.NewCoin(coin. + Denom, coin.Amount.TruncateInt())), hostZoneConfig) + } else if coin.Denom == bondDenom { + fmt.Println("here in elseif>>>>>>>>>>", coin.Denom, bondDenom) + hostZoneConfig, found := r.FeeabsKeeper.GetHostZoneConfig(ctx, denom) + if !found { + return sdk.DecCoin{}, ErrDenomNotRegistered(denom) + } + amount, err = r.FeeabsKeeper.CalculateNativeFromIBCCoins(ctx, sdk.NewCoins(sdk.NewCoin(denom, coin.Amount.TruncateInt())), hostZoneConfig) + } + + if err != nil { + return sdk.DecCoin{}, err + } + fmt.Println(">>>>>>>>>>>>>>>>>>>", sdk.NewDecCoinFromDec(denom, amount[0].Amount.ToLegacyDec())) + return sdk.NewDecCoinFromDec(denom, amount[0].Amount.ToLegacyDec()), nil +} + +// ExtraDenoms should be all denoms that have been registered via governance(host zone) +func (r *DenomResolverImpl) ExtraDenoms(ctx sdk.Context) ([]string, error) { + allHostZoneConfigs, err := r.FeeabsKeeper.GetAllHostZoneConfig(ctx) + if err != nil { + return nil, err + } + denoms := make([]string, 0, len(allHostZoneConfigs)) + for _, hostZoneConfig := range allHostZoneConfigs { + denoms = append(denoms, hostZoneConfig.IbcDenom) + } + return denoms, nil +} + +// ////////////////////////////////////// +// Helper functions for DenomResolver // +// ////////////////////////////////////// + +func (r *DenomResolverImpl) getIBCCoinFromNative(ctx sdk.Context, nativeCoins sdk.Coins, chainConfig feeabstypes.HostChainFeeAbsConfig) (coins sdk.Coins, err error) { + if len(nativeCoins) != 1 { + return sdk.Coins{}, ErrExpectedOneCoin(len(nativeCoins)) + } + + nativeCoin := nativeCoins[0] + + twapRate, err := r.FeeabsKeeper.GetTwapRate(ctx, chainConfig.IbcDenom) + if err != nil { + return sdk.Coins{}, err + } + + // Divide native amount by twap rate to get IBC amount + ibcAmount := nativeCoin.Amount.ToLegacyDec().Quo(twapRate).RoundInt() + ibcCoin := sdk.NewCoin(chainConfig.IbcDenom, ibcAmount) + + // Verify the resulting IBC coin + err = r.verifyIBCCoins(ctx, sdk.NewCoins(ibcCoin)) + if err != nil { + return sdk.Coins{}, err + } + + return sdk.NewCoins(ibcCoin), nil +} + +// return err if IBC token isn't in allowed_list +func (r *DenomResolverImpl) verifyIBCCoins(ctx sdk.Context, ibcCoins sdk.Coins) error { + if ibcCoins.Len() != 1 { + return feeabstypes.ErrInvalidIBCFees + } + + ibcDenom := ibcCoins[0].Denom + if r.FeeabsKeeper.HasHostZoneConfig(ctx, ibcDenom) { + return nil + } + return feeabstypes.ErrUnsupportedDenom.Wrapf("unsupported denom: %s", ibcDenom) +} diff --git a/ante/errors.go b/ante/errors.go new file mode 100644 index 000000000..ff259718f --- /dev/null +++ b/ante/errors.go @@ -0,0 +1,17 @@ +package ante + +import ( + "fmt" +) + +func ErrNeitherNativeDenom(coinDenom, denom string) error { + return fmt.Errorf("neither of coin.Denom %s and denom %s is the native denom of the chain", coinDenom, denom) +} + +func ErrDenomNotRegistered(denom string) error { + return fmt.Errorf("denom %s not registered in host zone", denom) +} + +func ErrExpectedOneCoin(count int) error { + return fmt.Errorf("expected exactly one native coin, got %d", count) +} diff --git a/app/app.go b/app/app.go index efdd2074c..ba50f98be 100644 --- a/app/app.go +++ b/app/app.go @@ -137,6 +137,7 @@ import ( feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types" // unnamed import of statik for swagger UI support + cheqdante "github.com/cheqd/cheqd-node/ante" _ "github.com/cheqd/cheqd-node/app/client/docs/statik" upgradeV3 "github.com/cheqd/cheqd-node/app/upgrades/v3" ) @@ -483,8 +484,7 @@ func New( scopedIBCKeeper, ) - app.FeeMarketKeeper = feemarketkeeper.NewKeeper(appCodec, keys[feemarkettypes.StoreKey], app.AccountKeeper, &feemarkettypes.TestDenomResolver{}, authtypes.NewModuleAddress(govtypes.ModuleName).String()) - app.FeeMarketKeeper.SetDenomResolver(&feemarkettypes.TestDenomResolver{}) // TODO + app.FeeMarketKeeper = feemarketkeeper.NewKeeper(appCodec, keys[feemarkettypes.StoreKey], app.AccountKeeper, &cheqdante.DenomResolverImpl{}, authtypes.NewModuleAddress(govtypes.ModuleName).String()) // IBC Fee Module keeper app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( appCodec, @@ -550,6 +550,11 @@ func New( scopedFeeabsKeeper, ) + app.FeeMarketKeeper.SetDenomResolver(&cheqdante.DenomResolverImpl{ + StakingKeeper: app.StakingKeeper, + FeeabsKeeper: app.FeeabsKeeper, + }) + // register the proposal types govRouter := govv1beta1.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).