diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 71cc75c2..6c8ecb62 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -124,12 +124,12 @@ func (s *IntegrationTestSuite) TestFeeTax() { // Test 1: banktypes.MsgSend // burn tax with bank send - subAmount := transferAmount1.Add(initialization.TaxRate.MulInt(transferAmount1).Mul(initialization.GasAdjustment).TruncateInt()) + subAmount := transferAmount1.Add(initialization.TaxRate.MulInt(transferAmount1).TruncateInt()) node.BankSend(transferCoin1.String(), validatorAddr, test1Addr, []string{initialization.TerraDenom}) // Due to the fee estimate when using - decremented := validatorBalance.Sub(sdk.NewCoin(initialization.TerraDenom, subAmount.AddRaw(1))) + decremented := validatorBalance.Sub(sdk.NewCoin(initialization.TerraDenom, subAmount.AddRaw(2))) newValidatorBalance, err := node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) s.Require().NoError(err) @@ -149,8 +149,8 @@ func (s *IntegrationTestSuite) TestFeeTax() { newValidatorBalance, err = node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) s.Require().NoError(err) - subAmount = totalTransferAmount.Add(initialization.TaxRate.MulInt(totalTransferAmount).Mul(initialization.GasAdjustment).TruncateInt()) - s.Require().Equal(newValidatorBalance, validatorBalance.Sub(sdk.NewCoin(initialization.TerraDenom, subAmount.AddRaw(1)))) + subAmount = totalTransferAmount.Add(initialization.TaxRate.MulInt(totalTransferAmount).TruncateInt()) + s.Require().Equal(newValidatorBalance, validatorBalance.Sub(sdk.NewCoin(initialization.TerraDenom, subAmount.AddRaw(2)))) } // Each tx gas will cost 2 uluna (1 is for ante handler, 1 is for post handler) @@ -179,8 +179,8 @@ func (s *IntegrationTestSuite) TestFeeTaxWasm() { balance1, err := node.QuerySpecificBalance(testAddr, initialization.TerraDenom) s.Require().NoError(err) // 400000000 - 100000000 - 100000000 * TaxRate - 2 (gas) = 300000000 - 10000000 * TaxRate - 2 (gas) - taxAmount := initialization.TaxRate.MulInt(transferAmount).Mul(initialization.GasAdjustment).TruncateInt() - s.Require().Equal(balance1.Amount, transferAmount.Mul(sdk.NewInt(3)).Sub(taxAmount).SubRaw(1)) + taxAmount := initialization.TaxRate.MulInt(transferAmount).TruncateInt() + s.Require().Equal(balance1.Amount, transferAmount.Mul(sdk.NewInt(3)).Sub(taxAmount).SubRaw(2)) node.Instantiate2WasmContract( strconv.Itoa(chain.LatestCodeID), @@ -195,8 +195,8 @@ func (s *IntegrationTestSuite) TestFeeTaxWasm() { balance2, err := node.QuerySpecificBalance(testAddr, initialization.TerraDenom) s.Require().NoError(err) // balance1 - 100000000 - 100000000 * TaxRate - 2 (gas) - taxAmount = initialization.TaxRate.MulInt(transferAmount).Mul(initialization.GasAdjustment).TruncateInt() - s.Require().Equal(balance2.Amount, balance1.Amount.Sub(transferAmount).Sub(taxAmount).SubRaw(1)) + taxAmount = initialization.TaxRate.MulInt(transferAmount).TruncateInt() + s.Require().Equal(balance2.Amount, balance1.Amount.Sub(transferAmount).Sub(taxAmount).SubRaw(2)) contractAddr := contracts[0] node.WasmExecute(contractAddr, `{"donate": {}}`, transferCoin.String(), "test-wasm", []string{initialization.TerraDenom}) @@ -204,8 +204,8 @@ func (s *IntegrationTestSuite) TestFeeTaxWasm() { balance3, err := node.QuerySpecificBalance(testAddr, initialization.TerraDenom) s.Require().NoError(err) // balance2 - 100000000 - 100000000 * TaxRate - 2 (gas) - taxAmount = initialization.TaxRate.MulInt(transferAmount).Mul(initialization.GasAdjustment).TruncateInt() - s.Require().Equal(balance3.Amount, balance2.Amount.Sub(transferAmount).Sub(taxAmount).SubRaw(1)) + taxAmount = initialization.TaxRate.MulInt(transferAmount).TruncateInt() + s.Require().Equal(balance3.Amount, balance2.Amount.Sub(transferAmount).Sub(taxAmount).SubRaw(2)) } // Each tx gas will cost 2 token (1 is for ante handler, 1 is for post handler) @@ -246,54 +246,54 @@ func (s *IntegrationTestSuite) TestFeeTaxGrant() { s.Require().Equal(balanceTest1, transferCoin1) s.Require().Equal(newValidatorBalance, validatorBalance.Add(transferCoin1)) // addr2 lost 10uluna to pay for grant msg's gas, 100000000 * TaxRate + 1uluna to pay for bank send msg's tx fees, - s.Require().Equal(balanceTest2.Amount, transferAmount1.Sub(initialization.TaxRate.MulInt(transferAmount1).Mul(initialization.GasAdjustment).TruncateInt()).SubRaw(11)) - - // // Test 3: try bank send with no grant - // transferAmount2 := sdkmath.NewInt(200000000) - // transferUsdCoin2 := sdk.NewCoin(initialization.UsdDenom, transferAmount2) - // transferTerraCoin2 := sdk.NewCoin(initialization.TerraDenom, transferAmount2) - - // node.BankSend(transferTerraCoin2.String(), validatorAddr, test1Addr, []string{initialization.TerraDenom}) - // node.BankSend(transferUsdCoin2.String(), validatorAddr, test1Addr, []string{initialization.UsdDenom}) - // node.BankSend(transferUsdCoin2.String(), validatorAddr, test2Addr, []string{initialization.UsdDenom}) - - // // Revoke previous grant and grant new ones - // node.RevokeGrant(test2Addr, test1Addr, "test2-grant", initialization.UsdDenom) - // feeAmountTerraDenom := sdkmath.NewInt(10) - // feeCoinTerraDenom := sdk.NewCoin(initialization.TerraDenom, feeAmountTerraDenom) - // node.GrantAddress(test2Addr, test1Addr, "test2-grant", initialization.UsdDenom, sdk.NewCoins(transferUsdCoin2, feeCoinTerraDenom).String()) - - // validatorTerraBalance, err := node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) - // s.Require().NoError(err) - // balanceTest2TerraBalance, err := node.QuerySpecificBalance(test2Addr, initialization.TerraDenom) - // s.Require().NoError(err) - - // node.BankSendFeeGrantWithWallet(transferTerraCoin2.String(), test1Addr, validatorAddr, test2Addr, "test1-grant", []string{}, transferUsdCoin2, feeCoinTerraDenom) - - // newValidatorTerraBalance, err := node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) - // s.Require().NoError(err) - // balanceTest1TerraBalance, err := node.QuerySpecificBalance(test1Addr, initialization.TerraDenom) - // s.Require().NoError(err) - // balanceTest1UsdBalance, err := node.QuerySpecificBalance(test1Addr, initialization.UsdDenom) - // s.Require().NoError(err) - // newBalanceTest2TerraBalance, err := node.QuerySpecificBalance(test2Addr, initialization.TerraDenom) - // s.Require().NoError(err) - // balanceTest2UsdBalance, err := node.QuerySpecificBalance(test2Addr, initialization.UsdDenom) - // s.Require().NoError(err) - // // The fee grant msg only support to pay by one denom, so only uusd balance will change - // s.Require().Equal(newValidatorTerraBalance, validatorTerraBalance.Add(transferTerraCoin2)) - // s.Require().Equal(balanceTest1TerraBalance, balanceTest1) - // s.Require().Equal(balanceTest1UsdBalance, transferUsdCoin2) - // // 1uluna will be used for ante handler - // s.Require().Equal(newBalanceTest2TerraBalance.Amount, balanceTest2TerraBalance.Amount.SubRaw(1)) - // s.Require().Equal( - // balanceTest2UsdBalance.Amount, - // transferAmount2.Sub( - // initialization.TaxRate.MulInt(transferAmount2). // tax amount in the form of terra denom - // Mul(initialization.UsdGasPrice.Quo(initialization.TerraGasPrice)). // convert terra denom to usd denom base on gas price - // TruncateInt(), - // ).SubRaw(5), // addr2 lost 2uusd to pay for revoke msg's gas, 2uusd to pay for grant msg's gas, 1uusd to pay for band send msg's gas - // ) + s.Require().Equal(balanceTest2.Amount, transferAmount1.Sub(initialization.TaxRate.MulInt(transferAmount1).TruncateInt()).SubRaw(4)) + + // Test 3: try bank send with no grant + transferAmount2 := sdkmath.NewInt(200000000) + transferUsdCoin2 := sdk.NewCoin(initialization.UsdDenom, transferAmount2) + transferTerraCoin2 := sdk.NewCoin(initialization.TerraDenom, transferAmount2) + + node.BankSend(transferTerraCoin2.String(), validatorAddr, test1Addr, []string{initialization.TerraDenom}) + node.BankSend(transferUsdCoin2.String(), validatorAddr, test1Addr, []string{initialization.UsdDenom}) + node.BankSend(transferUsdCoin2.String(), validatorAddr, test2Addr, []string{initialization.UsdDenom}) + + // Revoke previous grant and grant new ones + node.RevokeGrant(test2Addr, test1Addr, "test2-grant", initialization.UsdDenom) + feeAmountTerraDenom := sdkmath.NewInt(10) + feeCoinTerraDenom := sdk.NewCoin(initialization.TerraDenom, feeAmountTerraDenom) + node.GrantAddress(test2Addr, test1Addr, "test2-grant", initialization.UsdDenom, sdk.NewCoins(transferUsdCoin2, feeCoinTerraDenom).String()) + + validatorTerraBalance, err := node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) + s.Require().NoError(err) + balanceTest2TerraBalance, err := node.QuerySpecificBalance(test2Addr, initialization.TerraDenom) + s.Require().NoError(err) + + node.BankSendFeeGrantWithWallet(transferTerraCoin2.String(), test1Addr, validatorAddr, test2Addr, "test1-grant", []string{}, transferUsdCoin2, feeCoinTerraDenom) + + newValidatorTerraBalance, err := node.QuerySpecificBalance(validatorAddr, initialization.TerraDenom) + s.Require().NoError(err) + balanceTest1TerraBalance, err := node.QuerySpecificBalance(test1Addr, initialization.TerraDenom) + s.Require().NoError(err) + balanceTest1UsdBalance, err := node.QuerySpecificBalance(test1Addr, initialization.UsdDenom) + s.Require().NoError(err) + newBalanceTest2TerraBalance, err := node.QuerySpecificBalance(test2Addr, initialization.TerraDenom) + s.Require().NoError(err) + balanceTest2UsdBalance, err := node.QuerySpecificBalance(test2Addr, initialization.UsdDenom) + s.Require().NoError(err) + // The fee grant msg only support to pay by one denom, so only uusd balance will change + s.Require().Equal(newValidatorTerraBalance, validatorTerraBalance.Add(transferTerraCoin2)) + s.Require().Equal(balanceTest1TerraBalance, balanceTest1) + s.Require().Equal(balanceTest1UsdBalance, transferUsdCoin2) + // 1uluna will be used for ante handler + s.Require().Equal(newBalanceTest2TerraBalance.Amount, balanceTest2TerraBalance.Amount.SubRaw(1)) + s.Require().Equal( + balanceTest2UsdBalance.Amount, + transferAmount2.Sub( + initialization.TaxRate.MulInt(transferAmount2). // tax amount in the form of terra denom + Mul(initialization.UsdGasPrice.Quo(initialization.TerraGasPrice)). // convert terra denom to usd denom base on gas price + TruncateInt(), + ).SubRaw(5), // addr2 lost 2uusd to pay for revoke msg's gas, 2uusd to pay for grant msg's gas, 1uusd to pay for band send msg's gas + ) } func (s *IntegrationTestSuite) TestFeeTaxNotSupport() { @@ -364,7 +364,7 @@ func (s *IntegrationTestSuite) TestFeeTaxNotSupport() { newTerraBalance, err := nodeB.QuerySpecificBalance(test1AddrChainB, initialization.TerraDenom) s.Require().NoError(err) // Tx will only cost 10uluna on chain B as gas - s.Require().Equal(newTerraBalance.Amount, terraBalance.Amount.Sub(sdkmath.NewInt(10))) + s.Require().Equal(newTerraBalance.Amount, terraBalance.Amount.Sub(sdkmath.NewInt(2))) } func (s *IntegrationTestSuite) TestFeeTaxMultipleDenoms() { @@ -458,7 +458,7 @@ func (s *IntegrationTestSuite) TestFeeTaxForwardWasm() { s.Require().Equal(test1AddrBalance.Amount, transferAmount1.Sub(transferAmount2). // User 1 will paid 2 times on taxes due to the contract execute bank send msg // 2uluna will be used for gas - Sub(initialization.TaxRate.MulInt(transferAmount2.MulRaw(2)).Mul(initialization.GasAdjustment).TruncateInt()).SubRaw(1)) + Sub(initialization.TaxRate.MulInt(transferAmount2.MulRaw(2)).TruncateInt()).SubRaw(2)) // Test 2: Contract trigger another contract's execute msg node.InstantiateWasmContract( @@ -488,7 +488,7 @@ func (s *IntegrationTestSuite) TestFeeTaxForwardWasm() { s.Require().Equal(newTest1AddrBalance.Amount, test1AddrBalance.Amount.Sub(transferAmount2). // User 1 will paid 3 times on taxes: execute contract1 msg, contract 1 execute contract 2 msg, contract 2 execute bank msg // 2uluna will be used for gas - Sub(initialization.TaxRate.MulInt(transferAmount2.MulRaw(3)).Mul(initialization.GasAdjustment).TruncateInt()).SubRaw(1)) + Sub(initialization.TaxRate.MulInt(transferAmount2.MulRaw(3)).TruncateInt()).SubRaw(2)) // Test 3: Error when forward tx test1AddrBalance = newTest1AddrBalance @@ -542,7 +542,7 @@ func (s *IntegrationTestSuite) TestFeeTaxNotAcceptDenom() { // Test 2: Try to trick the chain by paying with both uluna and non-value denom - feeTerra := initialization.TaxRate.MulInt(transferAmount2).Mul(initialization.GasAdjustment).TruncateInt().AddRaw(1) + feeTerra := initialization.TaxRate.MulInt(transferAmount2).TruncateInt().AddRaw(2) feeTerraCoin := sdk.NewCoin(initialization.TerraDenom, feeTerra) fees = sdk.NewCoins(sdk.NewCoin(initialization.NonValueDenom, transferAmount2), feeTerraCoin) @@ -555,5 +555,5 @@ func (s *IntegrationTestSuite) TestFeeTaxNotAcceptDenom() { s.Require().NoError(err) s.Require().Equal(balanceTest1Terra.Amount, transferAmount1.Sub(transferAmount2).Sub(feeTerra)) - s.Require().Equal(balanceTest1NonValueDenom.Amount, transferAmount1.Sub(transferAmount2)) + s.Require().Equal(balanceTest1NonValueDenom.Amount, transferAmount1) } diff --git a/x/tax2gas/ante/ante.go b/x/tax2gas/ante/ante.go index 43d930be..51984de3 100644 --- a/x/tax2gas/ante/ante.go +++ b/x/tax2gas/ante/ante.go @@ -95,12 +95,13 @@ func (fd FeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, nex if !simulate { isOracleTx := tax2gasutils.IsOracleTx(msgs) - feeCoins := feeTx.GetFee() - gas := feeTx.GetGas() - + // the priority to be added in mempool is based on + // the tax gas that user need to pay priority = int64(math.MaxInt64) if !isOracleTx { - priority = tax2gasutils.GetTxPriority(feeCoins, int64(gas)) + if taxGas.IsInt64() { + priority = taxGas.Int64() + } } } diff --git a/x/tax2gas/post/post.go b/x/tax2gas/post/post.go index e7d31fd8..7feccddc 100644 --- a/x/tax2gas/post/post.go +++ b/x/tax2gas/post/post.go @@ -102,25 +102,50 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate feePayer := feeTx.FeePayer() feeGranter := feeTx.FeeGranter() - deductFeesFrom := feePayer // if feegranter set deduct fee from feegranter account. // this works with only when feegrant enabled. if feeGranter != nil { - if tgd.feegrantKeeper == nil { - return ctx, sdkerrors.ErrInvalidRequest.Wrap("fee grants are not enabled") - } else if !feeGranter.Equals(feePayer) { + allowance, err := tgd.feegrantKeeper.GetAllowance(ctx, feeGranter, feePayer) + if err != nil { + return ctx, errorsmod.Wrapf(err, "fee-grant not found with granter %s and grantee %s", feeGranter, feePayer) + } - err := tgd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, feeCoins, feeTx.GetMsgs()) - if err != nil { - return ctx, errorsmod.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer) + gasRemainingFees, err := tax2gasutils.ComputeFeesOnGasConsumed(tx, gasPrices, totalGasRemaining) + if err != nil { + return ctx, err + } + + // For this tx, we only accept to pay by one denom + for _, feeRequired := range gasRemainingFees { + _, err := allowance.Accept(ctx, sdk.NewCoins(feeRequired), feeTx.GetMsgs()) + if err == nil { + err = tgd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, sdk.NewCoins(feeRequired), feeTx.GetMsgs()) + if err != nil { + return ctx, errorsmod.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer) + } + feeGranter := tgd.accountKeeper.GetAccount(ctx, feeGranter) + err = tgd.bankKeeper.SendCoinsFromAccountToModule(ctx, feeGranter.GetAddress(), authtypes.FeeCollectorName, sdk.NewCoins(feeRequired)) + if err != nil { + return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) + } + + // Calculate tax fee and BurnTaxSplit + _, gasPrice := tax2gasutils.GetGasPriceByDenom(gasPrices, feeRequired.Denom) + taxFee := gasPrice.MulInt(taxGas).Ceil().RoundInt() + + err := tgd.BurnTaxSplit(ctx, sdk.NewCoins(sdk.NewCoin(feeRequired.Denom, taxFee))) + if err != nil { + return ctx, err + } + return next(ctx, tx, simulate, success) } } - deductFeesFrom = feeGranter + return ctx, errorsmod.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer) } // First, we will deduct the fees covered taxGas and handle BurnTaxSplit - taxes, gasRemaining := tax2gasutils.CalculateTaxesAndGasRemaining(gasPrices, feeCoins, taxGas, totalGasRemaining) + taxes, payableFees, gasRemaining := tax2gasutils.CalculateTaxesAndPayableFee(gasPrices, feeCoins, taxGas, totalGasRemaining) if !simulate && !ctx.IsCheckTx() && gasRemaining.IsPositive() { gasRemainingFees, err := tax2gasutils.ComputeFeesOnGasConsumed(tx, gasPrices, gasRemaining) if err != nil { @@ -129,15 +154,13 @@ func (tgd Tax2gasPostDecorator) PostHandle(ctx sdk.Context, tx sdk.Tx, simulate return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "fees are not enough to pay for gas, need to cover %s gas more, which equal to %q ", gasRemaining.String(), gasRemainingFees) } - deductFeesFromAcc := tgd.accountKeeper.GetAccount(ctx, deductFeesFrom) - if !feeCoins.IsZero() { - err := tgd.bankKeeper.SendCoinsFromAccountToModule(ctx, deductFeesFromAcc.GetAddress(), authtypes.FeeCollectorName, feeCoins) - if err != nil { - return ctx, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) - } + 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()) } - err := tgd.BurnTaxSplit(ctx, taxes) + err = tgd.BurnTaxSplit(ctx, taxes) if err != nil { return ctx, err } diff --git a/x/tax2gas/utils/utils.go b/x/tax2gas/utils/utils.go index caeaff0a..f234d916 100644 --- a/x/tax2gas/utils/utils.go +++ b/x/tax2gas/utils/utils.go @@ -1,34 +1,12 @@ package utils import ( - "math" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" oracleexported "github.com/classic-terra/core/v3/x/oracle/exported" ) -// GetTxPriority returns a naive tx priority based on the amount of the smallest denomination of the gas price -// provided in a transaction. -// NOTE: This implementation should be used with a great consideration as it opens potential attack vectors -// where txs with multiple coins could not be prioritize as expected. -func GetTxPriority(fee sdk.Coins, gas int64) int64 { - var priority int64 - for _, c := range fee { - p := int64(math.MaxInt64) - gasPrice := c.Amount.QuoRaw(gas) - if gasPrice.IsInt64() { - p = gasPrice.Int64() - } - if priority == 0 || p < priority { - priority = p - } - } - - return priority -} - func IsOracleTx(msgs []sdk.Msg) bool { for _, msg := range msgs { switch msg.(type) { @@ -73,9 +51,10 @@ func GetGasPriceByDenom(gasPrices sdk.DecCoins, denom string) (bool, sdk.Dec) { } } -func CalculateTaxesAndGasRemaining(gasPrices sdk.DecCoins, feeCoins sdk.Coins, taxGas sdkmath.Int, totalGasRemaining sdkmath.Int) (taxes sdk.Coins, gasRemaining sdkmath.Int) { +func CalculateTaxesAndPayableFee(gasPrices sdk.DecCoins, feeCoins sdk.Coins, taxGas sdkmath.Int, totalGasRemaining sdkmath.Int) (taxes, payableFees sdk.Coins, gasRemaining sdkmath.Int) { taxGasRemaining := taxGas taxes = sdk.NewCoins() + payableFees = sdk.NewCoins() gasRemaining = totalGasRemaining for _, feeCoin := range feeCoins { found, gasPrice := GetGasPriceByDenom(gasPrices, feeCoin.Denom) @@ -90,29 +69,34 @@ func CalculateTaxesAndGasRemaining(gasPrices sdk.DecCoins, feeCoins sdk.Coins, t switch { case feeCoin.IsGTE(totalFeeRequired): taxes = taxes.Add(taxFeeRequired) + payableFees = payableFees.Add(totalFeeRequired) gasRemaining = sdkmath.ZeroInt() - return taxes, gasRemaining + return taxes, payableFees, gasRemaining case feeCoin.IsGTE(taxFeeRequired): taxes = taxes.Add(taxFeeRequired) taxGasRemaining = sdkmath.ZeroInt() + payableFees = payableFees.Add(feeCoin) totalFeeRemaining := sdk.NewDecCoinFromCoin(totalFeeRequired.Sub(feeCoin)) gasRemaining = totalFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt() default: taxes = taxes.Add(feeCoin) + payableFees = payableFees.Add(feeCoin) taxFeeRemaining := sdk.NewDecCoinFromCoin(taxFeeRequired.Sub(feeCoin)) taxGasRemaining = taxFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt() gasRemaining = gasRemaining.Sub(taxGas.Sub(taxGasRemaining)) } case gasRemaining.IsPositive(): if feeCoin.IsGTE(totalFeeRequired) { + payableFees = payableFees.Add(totalFeeRequired) gasRemaining = sdkmath.ZeroInt() - return taxes, gasRemaining + return taxes, payableFees, gasRemaining } + payableFees = payableFees.Add(feeCoin) totalFeeRemaining := sdk.NewDecCoinFromCoin(totalFeeRequired.Sub(feeCoin)) gasRemaining = totalFeeRemaining.Amount.Quo(gasPrice).Ceil().RoundInt() default: - return taxes, gasRemaining + return taxes, payableFees, gasRemaining } } - return taxes, gasRemaining + return taxes, payableFees, gasRemaining }