From eaf66437d0a5cf6cb0769e3939896e11feb53ebc Mon Sep 17 00:00:00 2001 From: Tuan Tran Date: Mon, 8 Jul 2024 10:28:34 +0700 Subject: [PATCH] feat: add support for multiple denom fees(backport #206) (#208) * retract * add more tests --- go.mod | 2 ++ x/feeabs/ante/ante_test.go | 68 +++++++++++++++++++++++++++----------- x/feeabs/ante/decorate.go | 44 ++++++++++++------------ 3 files changed, 74 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index 9496eb87..508eec3e 100644 --- a/go.mod +++ b/go.mod @@ -334,3 +334,5 @@ replace ( google.golang.org/grpc => google.golang.org/grpc v1.54.0 ) + +retract v7.0.0 diff --git a/x/feeabs/ante/ante_test.go b/x/feeabs/ante/ante_test.go index 0440f291..a0de7010 100644 --- a/x/feeabs/ante/ante_test.go +++ b/x/feeabs/ante/ante_test.go @@ -6,6 +6,8 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -93,25 +95,53 @@ func TestMempoolDecorator(t *testing.T) { nil, }, // TODO: Add support for multiple denom fees(--fees 50ibc,50native) - // { - // "half native fee, half ibc fee, should pass", - // sdk.NewCoins(sdk.NewInt64Coin("native", 500*int64(gasLimit)), sdk.NewInt64Coin("ibcfee", 500*int64(gasLimit))), - // sdk.NewDecCoinsFromCoins(sdk.NewCoins(sdk.NewInt64Coin("native", 1000))...), - // func(suite *AnteTestSuite) { - // err := suite.feeabsKeeper.SetHostZoneConfig(suite.ctx, types.HostChainFeeAbsConfig{ - // IbcDenom: "ibcfee", - // OsmosisPoolTokenDenomIn: "osmosis", - // PoolId: 1, - // Status: types.HostChainFeeAbsStatus_UPDATED, - // MinSwapAmount: 0, - // }) - // require.NoError(t, err) - // suite.feeabsKeeper.SetTwapRate(suite.ctx, "ibcfee", sdk.NewDec(1)) - // suite.stakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("native").MinTimes(1) - // }, - // false, - // nil, - // }, + { + "half native fee, half ibc fee, should pass", + sdk.NewCoins(sdk.NewInt64Coin("native", 500*int64(gasLimit)), sdk.NewInt64Coin("ibcfee", 500*int64(gasLimit))), + sdk.NewDecCoinsFromCoins(sdk.NewCoins(sdk.NewInt64Coin("native", 1000))...), + func(suite *AnteTestSuite) { + err := suite.feeabsKeeper.SetHostZoneConfig(suite.ctx, types.HostChainFeeAbsConfig{ + IbcDenom: "ibcfee", + OsmosisPoolTokenDenomIn: "osmosis", + PoolId: 1, + Status: types.HostChainFeeAbsStatus_UPDATED, + MinSwapAmount: 0, + }) + require.NoError(t, err) + suite.feeabsKeeper.SetTwapRate(suite.ctx, "ibcfee", sdk.NewDec(1)) + suite.stakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("native").MinTimes(1) + }, + false, + nil, + }, + { + "3/4 ibc fee, 1/4 another ibc fee, should pass", + sdk.NewCoins(sdk.NewInt64Coin("ibcfee", 750*int64(gasLimit)), sdk.NewInt64Coin("ibcfee2", 250*int64(gasLimit))), + sdk.NewDecCoinsFromCoins(sdk.NewCoins(sdk.NewInt64Coin("native", 1000))...), + func(suite *AnteTestSuite) { + err := suite.feeabsKeeper.SetHostZoneConfig(suite.ctx, types.HostChainFeeAbsConfig{ + IbcDenom: "ibcfee", + OsmosisPoolTokenDenomIn: "osmosis", + PoolId: 1, + Status: types.HostChainFeeAbsStatus_UPDATED, + // MinSwapAmount: 0, + }) + require.NoError(t, err) + err = suite.feeabsKeeper.SetHostZoneConfig(suite.ctx, types.HostChainFeeAbsConfig{ + IbcDenom: "ibcfee2", + OsmosisPoolTokenDenomIn: "osmosis", + PoolId: 2, + Status: types.HostChainFeeAbsStatus_UPDATED, + // MinSwapAmount: 0, + }) + require.NoError(t, err) + suite.feeabsKeeper.SetTwapRate(suite.ctx, "ibcfee", math.LegacyNewDec(1)) + suite.feeabsKeeper.SetTwapRate(suite.ctx, "ibcfee2", math.LegacyNewDec(1)) + suite.stakingKeeper.EXPECT().BondDenom(gomock.Any()).Return("native").MinTimes(1) + }, + false, + nil, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/x/feeabs/ante/decorate.go b/x/feeabs/ante/decorate.go index abaa1df7..cae92795 100644 --- a/x/feeabs/ante/decorate.go +++ b/x/feeabs/ante/decorate.go @@ -268,30 +268,32 @@ func (famfd FeeAbstrationMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk // Check if feeDenom is defined in feeabs // If so, replace the amount of feeDenom in feeCoins with the // corresponding amount of native denom that allow to pay fee - // TODO: Support more fee token in feeRequired for fee-abstraction - if feeCoinsNonZeroDenom.Len() == 1 { - feeDenom := feeCoinsNonZeroDenom.GetDenomByIndex(0) - hostChainConfig, found := famfd.feeabsKeeper.GetHostZoneConfig(ctx, feeDenom) - if found { - if hostChainConfig.Status == feeabstypes.HostChainFeeAbsStatus_FROZEN { - return ctx, sdkerrors.Wrapf(feeabstypes.ErrHostZoneFrozen, "cannot deduct fee as host zone is frozen") + // Support more fee tokens in feeRequired for fee-abstraction + if feeCoinsNonZeroDenom.Len() > 0 { + nativeCoinsFees := sdk.NewCoins() + for _, feeCoin := range feeCoinsNonZeroDenom { + feeDenom := feeCoin.Denom + hostChainConfig, found := famfd.feeabsKeeper.GetHostZoneConfig(ctx, feeDenom) + if found { + if hostChainConfig.Status == feeabstypes.HostChainFeeAbsStatus_FROZEN { + return ctx, sdkerrors.Wrapf(feeabstypes.ErrHostZoneFrozen, "cannot deduct fee as host zone is frozen") + } + + // if hostChainConfig.Status == feeabstypes.HostChainFeeAbsStatus_OUTDATED { + // return ctx, sdkerrors.Wrapf(feeabstypes.ErrHostZoneOutdated, "cannot deduct fee as host zone is outdated") + // } + + nativeCoinFee, err := famfd.feeabsKeeper.CalculateNativeFromIBCCoins(ctx, sdk.NewCoins(feeCoin), hostChainConfig) + if err != nil { + return ctx, sdkerrors.Wrapf(errorstypes.ErrInsufficientFee, "unable to calculate native fee from ibc fee: %s", err) + } + nativeCoinsFees = nativeCoinsFees.Add(nativeCoinFee...) + } else { + nativeCoinsFees = nativeCoinsFees.Add(feeCoin) } - - // if hostChainConfig.Status == feeabstypes.HostChainFeeAbsStatus_OUTDATED { - // return ctx, sdkerrors.Wrapf(feeabstypes.ErrHostZoneOutdated, "cannot deduct fee as host zone is outdated") - // } - - nativeCoinsFees, err := famfd.feeabsKeeper.CalculateNativeFromIBCCoins(ctx, feeCoinsNonZeroDenom, hostChainConfig) - if err != nil { - return ctx, sdkerrors.Wrapf(errorstypes.ErrInsufficientFee, "unable to calculate native fees from ibc fees: %s", err) - } - fmt.Println("nativeCoinsFees", nativeCoinsFees) - feeCoinsNonZeroDenom = nativeCoinsFees } - } else if feeCoinsNonZeroDenom.Len() > 1 { - return ctx, sdkerrors.Wrapf(errorstypes.ErrNotSupported, "should have only one fee denom in feeCoinsNonZeroDenom, got %d", feeCoinsNonZeroDenom.Len()) + feeCoinsNonZeroDenom = nativeCoinsFees } - // After replace the feeCoinsNonZeroDenom, feeCoinsNonZeroDenom must be in denom subset of nonZeroCoinFeesReq if !feeCoinsNonZeroDenom.DenomsSubsetOf(nonZeroCoinFeesReq) { return ctx, sdkerrors.Wrapf(errorstypes.ErrInvalidCoins, "fee is not a subset of required fees; got %s, required: %s", feeCoinsNonZeroDenom.String(), feeRequired.String())