diff --git a/custom/wasm/keeper/handler_plugin.go b/custom/wasm/keeper/handler_plugin.go index 2f8fe2c6..836fff96 100644 --- a/custom/wasm/keeper/handler_plugin.go +++ b/custom/wasm/keeper/handler_plugin.go @@ -20,7 +20,7 @@ import ( marketexported "github.com/classic-terra/core/v3/x/market/exported" tax2gaskeeper "github.com/classic-terra/core/v3/x/tax2gas/keeper" - "github.com/classic-terra/core/v3/x/tax2gas/types" + tax2gastypes "github.com/classic-terra/core/v3/x/tax2gas/types" tax2gasutils "github.com/classic-terra/core/v3/x/tax2gas/utils" treasurykeeper "github.com/classic-terra/core/v3/x/treasury/keeper" ) @@ -93,11 +93,11 @@ func (h SDKMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddr if !taxes.IsZero() { eventManager := sdk.NewEventManager() - gas, err := tax2gasutils.ComputeGas(h.tax2gaskeeper.GetGasPrices(ctx), taxes) + taxGas, err := tax2gasutils.ComputeGas(h.tax2gaskeeper.GetGasPrices(ctx), taxes) if err != nil { return nil, nil, err } - ctx.GasMeter().ConsumeGas(gas, "tax gas") + ctx.TaxGasMeter().ConsumeGas(taxGas, "tax gas") events = eventManager.Events() } @@ -151,7 +151,7 @@ func isIBCDenom(denom string) bool { } // FilterMsgAndComputeTax computes the stability tax on messages. -func FilterMsgAndComputeTax(ctx sdk.Context, tk types.TreasuryKeeper, msgs ...sdk.Msg) sdk.Coins { +func FilterMsgAndComputeTax(ctx sdk.Context, tk tax2gastypes.TreasuryKeeper, msgs ...sdk.Msg) sdk.Coins { taxes := sdk.Coins{} for _, msg := range msgs { @@ -208,7 +208,7 @@ func FilterMsgAndComputeTax(ctx sdk.Context, tk types.TreasuryKeeper, msgs ...sd } // computes the stability tax according to tax-rate and tax-cap -func computeTax(ctx sdk.Context, tk types.TreasuryKeeper, principal sdk.Coins) sdk.Coins { +func computeTax(ctx sdk.Context, tk tax2gastypes.TreasuryKeeper, principal sdk.Coins) sdk.Coins { taxRate := tk.GetTaxRate(ctx) if taxRate.Equal(sdk.ZeroDec()) { return sdk.Coins{} diff --git a/go.mod b/go.mod index 4130d665..33486df1 100644 --- a/go.mod +++ b/go.mod @@ -229,7 +229,7 @@ replace ( // use cometbft github.com/cometbft/cometbft => github.com/classic-terra/cometbft v0.37.4-terra1 github.com/cometbft/cometbft-db => github.com/cometbft/cometbft-db v0.8.0 - github.com/cosmos/cosmos-sdk => github.com/classic-terra/cosmos-sdk v0.47.10-terra.1 + github.com/cosmos/cosmos-sdk => github.com/classic-terra/cosmos-sdk v0.47.10-terra.1.0.20240723054936-404ac399d771 github.com/cosmos/ibc-go/v7 => github.com/classic-terra/ibc-go/v7 v7.4.0-terra github.com/cosmos/ledger-cosmos-go => github.com/terra-money/ledger-terra-go v0.11.2 // replace goleveldb to optimized one diff --git a/go.sum b/go.sum index 6ca77d48..0655cf9b 100644 --- a/go.sum +++ b/go.sum @@ -350,8 +350,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/classic-terra/cometbft v0.37.4-terra1 h1:eT5B2n5KKi5WVW+3ZNOVTmtfKKaZrXOLX9G80m9mhZo= github.com/classic-terra/cometbft v0.37.4-terra1/go.mod h1:vFqj7Qe3uFFJvHZleTJPQDmJ/WscXHi4rKWqiCAaNZk= -github.com/classic-terra/cosmos-sdk v0.47.10-terra.1 h1:ek0vQ435fpeP3xGhszDO2yMIRy5XGMj9MCTlvpMUIkw= -github.com/classic-terra/cosmos-sdk v0.47.10-terra.1/go.mod h1:4mBvTB8zevoeTuQufWwTcNnthGG2afXO+9D42BKzlRo= +github.com/classic-terra/cosmos-sdk v0.47.10-terra.1.0.20240723054936-404ac399d771 h1:9yPDQUGx2iclFqwlahbzbNuNCAngivpTvOnXvjo5p0k= +github.com/classic-terra/cosmos-sdk v0.47.10-terra.1.0.20240723054936-404ac399d771/go.mod h1:4mBvTB8zevoeTuQufWwTcNnthGG2afXO+9D42BKzlRo= github.com/classic-terra/goleveldb v0.0.0-20230914223247-2b28f6655121 h1:fjpWDB0hm225wYg9vunyDyTH8ftd5xEUgINJKidj+Tw= github.com/classic-terra/goleveldb v0.0.0-20230914223247-2b28f6655121/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/classic-terra/ibc-go/v7 v7.4.0-terra h1:hawaq62XKlxyc8xLyIcc6IujDDEbqDBU+2U15SF+hj8= diff --git a/x/tax2gas/ante/ante.go b/x/tax2gas/ante/ante.go index 0a30e7e7..66dcabd0 100644 --- a/x/tax2gas/ante/ante.go +++ b/x/tax2gas/ante/ante.go @@ -91,7 +91,11 @@ func (fd FeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, nex } if feeTx.GetGas()-gasConsumed < taxGas { - return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidGasLimit, "must provide enough gas to cover taxes") + return ctx, errorsmod.Wrap( + sdkerrors.ErrInvalidGasLimit, + fmt.Sprintf("must provide enough gas to cover taxes, gas limit(%d) - gas consumed(%d) < tax gas(%d)", + feeTx.GetGas(), gasConsumed, taxGas), + ) } if !simulate && !taxes.IsZero() { @@ -110,7 +114,7 @@ func (fd FeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, nex newCtx := ctx.WithPriority(priority).WithValue(types.TaxGas, taxGas) if taxGas != 0 { - newCtx = newCtx.WithValue(types.TaxGas, taxGas) + newCtx.TaxGasMeter().ConsumeGas(taxGas, "ante handler taxGas") } newCtx = newCtx.WithValue(types.AnteConsumedGas, gasConsumed) if paidDenom != "" { diff --git a/x/tax2gas/post/post.go b/x/tax2gas/post/post.go index 9e9fcb7a..c8b06aa5 100644 --- a/x/tax2gas/post/post.go +++ b/x/tax2gas/post/post.go @@ -48,7 +48,9 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate feeCoins := feeTx.GetFee() anteConsumedGas, ok := ctx.Value(types.AnteConsumedGas).(uint64) if !ok { - return ctx, errorsmod.Wrap(types.ErrParsing, "Error parsing ante consumed gas") + // If cannot found the anteConsumedGas, that's mean the tx is bypass + // Skip this tx as it's bypass + return next(ctx, tx, simulate, success) } // Get paid denom identified in ante handler @@ -68,16 +70,14 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate // Deduct feeCoins with paid amount feeCoins = feeCoins.Sub(sdk.NewCoin(paidDenom, paidAmount.Ceil().RoundInt())) - taxGas, ok := ctx.Value(types.TaxGas).(uint64) - if !ok { - taxGas = 0 - } + taxGas := ctx.TaxGasMeter().GasConsumed() + // we consume the gas here as we need to calculate the tax for consumed gas ctx.GasMeter().ConsumeGas(taxGas, "tax gas") - gasConsumed := ctx.GasMeter().GasConsumed() + totalGasConsumed := ctx.GasMeter().GasConsumed() // Deduct the gas consumed amount spent on ante handler - gasRemaining := gasConsumed - anteConsumedGas + totalGasRemaining := totalGasConsumed - anteConsumedGas feePayer := feeTx.FeePayer() feeGranter := feeTx.FeeGranter() @@ -93,7 +93,7 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate return ctx, errorsmod.Wrapf(err, "fee-grant not found with granter %s and grantee %s", feeGranter, feePayer) } - gasRemainingFees, err := tax2gasutils.ComputeFeesOnGasConsumed(tx, gasPrices, gasRemaining) + gasRemainingFees, err := tax2gasutils.ComputeFeesOnGasConsumed(tx, gasPrices, totalGasRemaining) if err != nil { return ctx, err } @@ -111,6 +111,16 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate if err != nil { return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) } + + // Calculate tax fee and BurnTaxSplit + _, gasPrice := tax2gasutils.GetGasPriceByDenom(gasPrices, feeRequired.Denom) + taxFee := gasPrice.MulInt64(int64(taxGas)).Ceil().RoundInt() + if !simulate { + err := tgd.BurnTaxSplit(ctx, sdk.NewCoins(sdk.NewCoin(feeRequired.Denom, taxFee))) + if err != nil { + return ctx, err + } + } return next(ctx, tx, simulate, success) } } @@ -118,32 +128,15 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate } } - taxes := sdk.NewCoins() - for _, feeCoin := range feeCoins { - feePayer := tgd.accountKeeper.GetAccount(ctx, feePayer) - found, gasPrice := tax2gasutils.GetGasPriceByDenom(gasPrices, feeCoin.Denom) - if !found { - continue - } - feeRequired := sdk.NewCoin(feeCoin.Denom, gasPrice.MulInt64(int64(gasRemaining)).Ceil().RoundInt()) - - if feeCoin.IsGTE(feeRequired) { - err := tgd.bankKeeper.SendCoinsFromAccountToModule(ctx, feePayer.GetAddress(), authtypes.FeeCollectorName, sdk.NewCoins(feeRequired)) - if err != nil { - return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) - } - taxes = taxes.Add(feeRequired) - gasRemaining = 0 - break - } - - err := tgd.bankKeeper.SendCoinsFromAccountToModule(ctx, feePayer.GetAddress(), authtypes.FeeCollectorName, sdk.NewCoins(feeCoin)) - if err != nil { - return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) - } - taxes = taxes.Add(feeCoin) - feeRemaining := sdk.NewDecCoinFromCoin(feeRequired.Sub(feeCoin)) - gasRemaining = uint64(feeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt64()) + // First, we will deduct the fees covered taxGas and handle BurnTaxSplit + taxes, payableFees, gasRemaining := tax2gasutils.CalculateTaxesAndPayableFee(gasPrices, feeCoins, taxGas, totalGasRemaining) + if gasRemaining > 0 { + return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "fees are not enough to pay for gas, need to cover %d gas more", totalGasRemaining) + } + feePayerAccount := tgd.accountKeeper.GetAccount(ctx, feePayer) + err := tgd.bankKeeper.SendCoinsFromAccountToModule(ctx, feePayerAccount.GetAddress(), authtypes.FeeCollectorName, payableFees) + if err != nil { + return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) } if !simulate { @@ -153,9 +146,5 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate } } - if gasRemaining > 0 { - return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "fees are not enough to pay for gas") - } - return next(ctx, tx, simulate, success) } diff --git a/x/tax2gas/types/params.go b/x/tax2gas/types/params.go index ebf64d40..7b93ed11 100644 --- a/x/tax2gas/types/params.go +++ b/x/tax2gas/types/params.go @@ -38,9 +38,9 @@ var ( sdk.NewDecCoinFromDec("utwd", sdk.NewDecWithPrec(20, 0)), ) DefaultBypassMinFeeMsgTypes = []string{ + sdk.MsgTypeURL(&ibcclienttypes.MsgUpdateClient{}), sdk.MsgTypeURL(&ibcchanneltypes.MsgRecvPacket{}), sdk.MsgTypeURL(&ibcchanneltypes.MsgAcknowledgement{}), - sdk.MsgTypeURL(&ibcclienttypes.MsgUpdateClient{}), sdk.MsgTypeURL(&ibcchanneltypes.MsgTimeout{}), sdk.MsgTypeURL(&ibcchanneltypes.MsgTimeoutOnClose{}), } diff --git a/x/tax2gas/utils/utils.go b/x/tax2gas/utils/utils.go index 65e3d39c..c585384e 100644 --- a/x/tax2gas/utils/utils.go +++ b/x/tax2gas/utils/utils.go @@ -71,3 +71,55 @@ func GetGasPriceByDenom(gasPrices sdk.DecCoins, denom string) (bool, sdk.Dec) { } } } + +func CalculateTaxesAndPayableFee(gasPrices sdk.DecCoins, feeCoins sdk.Coins, taxGas uint64, totalGasRemaining uint64) (taxes sdk.Coins, payableFees sdk.Coins, gasRemaining uint64) { + taxGasRemaining := taxGas + taxes = sdk.NewCoins() + payableFees = sdk.NewCoins() + gasRemaining = totalGasRemaining + for _, feeCoin := range feeCoins { + found, gasPrice := GetGasPriceByDenom(gasPrices, feeCoin.Denom) + if !found { + continue + } + taxFeeRequired := sdk.NewCoin(feeCoin.Denom, gasPrice.MulInt64(int64(taxGasRemaining)).Ceil().RoundInt()) + totalFeeRequired := sdk.NewCoin(feeCoin.Denom, gasPrice.MulInt64(int64(gasRemaining)).Ceil().RoundInt()) + + switch { + case taxGasRemaining > 0: + switch { + case feeCoin.IsGTE(totalFeeRequired): + taxes = taxes.Add(taxFeeRequired) + payableFees = payableFees.Add(totalFeeRequired) + taxGasRemaining = 0 + gasRemaining = 0 + return + case feeCoin.IsGTE(taxFeeRequired): + taxes = taxes.Add(taxFeeRequired) + taxGasRemaining = 0 + payableFees = payableFees.Add(feeCoin) + totalFeeRemaining := sdk.NewDecCoinFromCoin(totalFeeRequired.Sub(feeCoin)) + gasRemaining = uint64(totalFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt64()) + default: + taxes = taxes.Add(feeCoin) + payableFees = payableFees.Add(feeCoin) + taxFeeRemaining := sdk.NewDecCoinFromCoin(taxFeeRequired.Sub(feeCoin)) + taxGasRemaining = uint64(taxFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt64()) + gasRemaining = gasRemaining - (taxGas - taxGasRemaining) + } + case gasRemaining > 0: + if feeCoin.IsGTE(totalFeeRequired) { + payableFees = payableFees.Add(totalFeeRequired) + gasRemaining = 0 + return + } else { + payableFees = payableFees.Add(feeCoin) + totalFeeRemaining := sdk.NewDecCoinFromCoin(totalFeeRequired.Sub(feeCoin)) + gasRemaining = uint64(totalFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt64()) + } + default: + return + } + } + return +}