Skip to content

Commit

Permalink
revert logic to deduct correct amount needed for gas and tax
Browse files Browse the repository at this point in the history
  • Loading branch information
phamminh0811 committed Aug 1, 2024
1 parent 5f4d877 commit b3d175d
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 110 deletions.
126 changes: 63 additions & 63 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)
Expand Down Expand Up @@ -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),
Expand All @@ -195,17 +195,17 @@ 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})

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)
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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)
}
9 changes: 5 additions & 4 deletions x/tax2gas/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check failure on line 99 in x/tax2gas/ante/ante.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gofumpt`-ed (gofumpt)
priority = int64(math.MaxInt64)
if !isOracleTx {
priority = tax2gasutils.GetTxPriority(feeCoins, int64(gas))
if taxGas.IsInt64() {
priority = taxGas.Int64()
}
}
}

Expand Down
55 changes: 39 additions & 16 deletions x/tax2gas/post/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down
Loading

0 comments on commit b3d175d

Please sign in to comment.