Skip to content

Commit

Permalink
Use taxGasMeter in sdk to handle tax2Gas logic (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
phamminh0811 authored Jul 23, 2024
1 parent fb0344f commit 3deac13
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 49 deletions.
10 changes: 5 additions & 5 deletions custom/wasm/keeper/handler_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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()
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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{}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
8 changes: 6 additions & 2 deletions x/tax2gas/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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 != "" {
Expand Down
65 changes: 27 additions & 38 deletions x/tax2gas/post/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,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
Expand All @@ -70,16 +72,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()
Expand All @@ -95,7 +95,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
}
Expand All @@ -113,39 +113,32 @@ 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)
}
}
return ctx, errorsmod.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer)
}
}

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 {
Expand All @@ -155,9 +148,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)
}
2 changes: 1 addition & 1 deletion x/tax2gas/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}),
}
Expand Down
52 changes: 52 additions & 0 deletions x/tax2gas/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Check failure on line 108 in x/tax2gas/utils/utils.go

View workflow job for this annotation

GitHub Actions / golangci-lint

assignOp: replace `gasRemaining = gasRemaining - (taxGas - taxGasRemaining)` with `gasRemaining -= (taxGas - taxGasRemaining)` (gocritic)
}
case gasRemaining > 0:
if feeCoin.IsGTE(totalFeeRequired) {
payableFees = payableFees.Add(totalFeeRequired)
gasRemaining = 0
return
} else {

Check warning on line 115 in x/tax2gas/utils/utils.go

View workflow job for this annotation

GitHub Actions / golangci-lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
payableFees = payableFees.Add(feeCoin)
totalFeeRemaining := sdk.NewDecCoinFromCoin(totalFeeRequired.Sub(feeCoin))

Check failure on line 117 in x/tax2gas/utils/utils.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gofumpt`-ed (gofumpt)
gasRemaining = uint64(totalFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt64())
}
default:
return
}
}
return
}

0 comments on commit 3deac13

Please sign in to comment.