diff --git a/custom/auth/ante/fee.go b/custom/auth/ante/fee.go index 8e8cf402c..a292be06d 100644 --- a/custom/auth/ante/fee.go +++ b/custom/auth/ante/fee.go @@ -51,7 +51,7 @@ func (fd FeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, nex msgs := feeTx.GetMsgs() // Compute taxes - taxes := FilterMsgAndComputeTax(ctx, fd.treasuryKeeper, msgs...) + taxes := FilterMsgAndComputeTax(ctx, fd.treasuryKeeper, simulate, msgs...) if !simulate { priority, err = fd.checkTxFee(ctx, tx, taxes) @@ -101,9 +101,24 @@ func (fd FeeDecorator) checkDeductFee(ctx sdk.Context, feeTx sdk.FeeTx, taxes sd feesOrTax := fee - // deduct the fees - if fee.IsZero() && simulate { - feesOrTax = taxes + if simulate { + if fee.IsZero() { + feesOrTax = taxes + } + + // even if fee is not zero it might be it is lower than the increased tax from computeTax + // so we need to check if the tax is higher than the fee to not run into deduction errors + for _, tax := range taxes { + feeAmount := feesOrTax.AmountOf(tax.Denom) + // if the fee amount is zero, add the tax amount to feesOrTax + if feeAmount.IsZero() { + feesOrTax = feesOrTax.Add(tax) + } else if feeAmount.LT(tax.Amount) { + // Update feesOrTax if the tax amount is higher + missingAmount := tax.Amount.Sub(feeAmount) + feesOrTax = feesOrTax.Add(sdk.NewCoin(tax.Denom, missingAmount)) + } + } } if !feesOrTax.IsZero() { diff --git a/custom/auth/ante/fee_tax.go b/custom/auth/ante/fee_tax.go index 96a0e48d6..be76869b3 100644 --- a/custom/auth/ante/fee_tax.go +++ b/custom/auth/ante/fee_tax.go @@ -20,14 +20,14 @@ func isIBCDenom(denom string) bool { } // FilterMsgAndComputeTax computes the stability tax on messages. -func FilterMsgAndComputeTax(ctx sdk.Context, tk TreasuryKeeper, msgs ...sdk.Msg) sdk.Coins { +func FilterMsgAndComputeTax(ctx sdk.Context, tk TreasuryKeeper, simulate bool, msgs ...sdk.Msg) sdk.Coins { taxes := sdk.Coins{} for _, msg := range msgs { switch msg := msg.(type) { case *banktypes.MsgSend: if !tk.HasBurnTaxExemptionAddress(ctx, msg.FromAddress, msg.ToAddress) { - taxes = taxes.Add(computeTax(ctx, tk, msg.Amount)...) + taxes = taxes.Add(computeTax(ctx, tk, msg.Amount, simulate)...) } case *banktypes.MsgMultiSend: @@ -47,28 +47,28 @@ func FilterMsgAndComputeTax(ctx sdk.Context, tk TreasuryKeeper, msgs ...sdk.Msg) if tainted != len(msg.Inputs)+len(msg.Outputs) { for _, input := range msg.Inputs { - taxes = taxes.Add(computeTax(ctx, tk, input.Coins)...) + taxes = taxes.Add(computeTax(ctx, tk, input.Coins, simulate)...) } } case *marketexported.MsgSwapSend: - taxes = taxes.Add(computeTax(ctx, tk, sdk.NewCoins(msg.OfferCoin))...) + taxes = taxes.Add(computeTax(ctx, tk, sdk.NewCoins(msg.OfferCoin), simulate)...) case *wasmtypes.MsgInstantiateContract: - taxes = taxes.Add(computeTax(ctx, tk, msg.Funds)...) + taxes = taxes.Add(computeTax(ctx, tk, msg.Funds, simulate)...) case *wasmtypes.MsgInstantiateContract2: - taxes = taxes.Add(computeTax(ctx, tk, msg.Funds)...) + taxes = taxes.Add(computeTax(ctx, tk, msg.Funds, simulate)...) case *wasmtypes.MsgExecuteContract: if !tk.HasBurnTaxExemptionContract(ctx, msg.Contract) { - taxes = taxes.Add(computeTax(ctx, tk, msg.Funds)...) + taxes = taxes.Add(computeTax(ctx, tk, msg.Funds, simulate)...) } case *authz.MsgExec: messages, err := msg.GetMessages() if err == nil { - taxes = taxes.Add(FilterMsgAndComputeTax(ctx, tk, messages...)...) + taxes = taxes.Add(FilterMsgAndComputeTax(ctx, tk, simulate, messages...)...) } } } @@ -77,7 +77,7 @@ func FilterMsgAndComputeTax(ctx sdk.Context, tk TreasuryKeeper, msgs ...sdk.Msg) } // computes the stability tax according to tax-rate and tax-cap -func computeTax(ctx sdk.Context, tk TreasuryKeeper, principal sdk.Coins) sdk.Coins { +func computeTax(ctx sdk.Context, tk TreasuryKeeper, principal sdk.Coins, simulate bool) sdk.Coins { taxRate := tk.GetTaxRate(ctx) if taxRate.Equal(sdk.ZeroDec()) { return sdk.Coins{} @@ -95,6 +95,12 @@ func computeTax(ctx sdk.Context, tk TreasuryKeeper, principal sdk.Coins) sdk.Coi } taxDue := sdk.NewDecFromInt(coin.Amount).Mul(taxRate).TruncateInt() + // we need to check all taxes if they are GTE 100 because otherwise we will not be able to + // simulate the split processes (i.e. BurnTaxSplit and OracleSplit) + // if they are less than 100, we will set them to 100 + if simulate && taxDue.LT(sdk.NewInt(100)) { + taxDue = sdk.NewInt(100) + } // If tax due is greater than the tax cap, cap! taxCap := tk.GetTaxCap(ctx, coin.Denom) diff --git a/custom/auth/ante/fee_test.go b/custom/auth/ante/fee_test.go index ecd8a634f..68f8482f3 100644 --- a/custom/auth/ante/fee_test.go +++ b/custom/auth/ante/fee_test.go @@ -832,7 +832,7 @@ func (s *AnteTestSuite) runBurnSplitTaxTest(burnSplitRate sdk.Dec, oracleSplitRa feeCollectorAfter := bk.GetAllBalances(s.ctx, ak.GetModuleAddress(authtypes.FeeCollectorName)) oracleAfter := bk.GetAllBalances(s.ctx, ak.GetModuleAddress(oracletypes.ModuleName)) - taxes := ante.FilterMsgAndComputeTax(s.ctx, tk, msg) + taxes := ante.FilterMsgAndComputeTax(s.ctx, tk, false, msg) communityPoolAfter, _ := dk.GetFeePoolCommunityCoins(s.ctx).TruncateDecimal() if communityPoolAfter.IsZero() { communityPoolAfter = sdk.NewCoins(sdk.NewCoin(core.MicroSDRDenom, sdk.ZeroInt())) diff --git a/custom/auth/tx/service.go b/custom/auth/tx/service.go index 63710d04e..a9c803c2c 100644 --- a/custom/auth/tx/service.go +++ b/custom/auth/tx/service.go @@ -52,7 +52,7 @@ func (ts txServer) ComputeTax(c context.Context, req *ComputeTaxRequest) (*Compu return nil, status.Errorf(codes.InvalidArgument, "empty txBytes is not allowed") } - taxAmount := customante.FilterMsgAndComputeTax(ctx, ts.treasuryKeeper, msgs...) + taxAmount := customante.FilterMsgAndComputeTax(ctx, ts.treasuryKeeper, false, msgs...) return &ComputeTaxResponse{ TaxAmount: taxAmount, }, nil diff --git a/custom/wasm/keeper/handler_plugin.go b/custom/wasm/keeper/handler_plugin.go index f3a24801b..479f96848 100644 --- a/custom/wasm/keeper/handler_plugin.go +++ b/custom/wasm/keeper/handler_plugin.go @@ -78,7 +78,9 @@ func (h SDKMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddr for _, sdkMsg := range sdkMsgs { // Charge tax on result msg - taxes := ante.FilterMsgAndComputeTax(ctx, h.treasuryKeeper, sdkMsg) + // we set simulate to false here as it is not available and we don't need to + // increase the tax amount for simulation inside of wasm + taxes := ante.FilterMsgAndComputeTax(ctx, h.treasuryKeeper, false, sdkMsg) if !taxes.IsZero() { eventManager := sdk.NewEventManager() contractAcc := h.accountKeeper.GetAccount(ctx, contractAddr)