Skip to content

Commit 68249e0

Browse files
authored
fix: Added embedded fee offset calculation on feecheck + realistic unit test assurance (#846)
* fix: Added embedded fee offset calculation on feecheck + realistic unit test assurance * Debug * Fixed cast * Bump gas adjustment * Switch literal * Bump significantly * Bump * Reducal to average * Bump fixed * Bump to greater / more stable value * Recalc diff * Debug * Removed redundant * Debug * Added explicit initialisation * Debug * Removed redundant + fixed fee bump * Bump
1 parent 1a4d415 commit 68249e0

File tree

10 files changed

+221
-12
lines changed

10 files changed

+221
-12
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ jobs:
259259
- name: Run integration tests on upgraded network
260260
working-directory: ./tests/integration
261261
run: |
262-
ginkgo -r --tags integration --race --randomize-suites --keep-going --trace --junit-report ../../report-upgraded-integration.xml
262+
ginkgo -r --tags integration --race --randomize-suites --keep-going --trace --skip-file cli_defi_test.go --junit-report ../../report-upgraded-integration.xml
263263
264264
- name: Upload post-upgrade integration tests result
265265
uses: actions/upload-artifact@v4
@@ -286,7 +286,7 @@ jobs:
286286
- name: Run pricing integration tests after successful param change proposal
287287
working-directory: ./tests/integration
288288
run: |
289-
ginkgo -r --tags integration --race --randomize-suites --keep-going --trace --skip-file cli_diddoc_test.go --skip-file cli_diddoc_negative_test.go --skip-file cli_resource_test.go --skip-file cli_resource_negative_test.go --junit-report ../../report-pricing-change.xml
289+
ginkgo -r --tags integration --race --randomize-suites --keep-going --trace --skip-file cli_diddoc_test.go --skip-file cli_diddoc_negative_test.go --skip-file cli_resource_test.go --skip-file cli_resource_negative_test.go --skip-file cli_defi_test.go --junit-report ../../report-pricing-change.xml
290290
291291
- name: Upload pricing change tests result
292292
uses: actions/upload-artifact@v4

ante/fee.go

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
errorsmod "cosmossdk.io/errors"
77
sdkmath "cosmossdk.io/math"
8+
didtypes "github.com/cheqd/cheqd-node/x/did/types"
89
sdk "github.com/cosmos/cosmos-sdk/types"
910
)
1011

@@ -68,6 +69,9 @@ func CheckTxFee(ctx sdk.Context, gasPrice sdk.DecCoin, feeCoin sdk.Coin, feeGas
6869
gcDec := sdkmath.LegacyNewDec(gasConsumed)
6970
glDec := sdkmath.LegacyNewDec(feeGas)
7071

72+
// multiply gasPrice by offset
73+
gasPrice.Amount = gasPrice.Amount.Mul(sdkmath.LegacyNewDec(didtypes.FeeOffset))
74+
7175
consumedFeeAmount := gasPrice.Amount.Mul(gcDec)
7276
limitFee := gasPrice.Amount.Mul(glDec)
7377

ante/fee_test.go

+94
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,100 @@ var _ = Describe("Fee tests on DeliverTx", func() {
399399
Expect((feeCollectorBalance.Amount).GT(math.NewInt(0)))
400400
})
401401

402+
It("Non TaxableTx Lifecycle - Ensure minimum gas prices", func() {
403+
// keys and addresses
404+
priv1, _, addr1 := testdata.KeyTestPubAddr()
405+
406+
// msg and signatures
407+
msg := testdata.NewTestMsg(addr1)
408+
feeAmount := sdk.NewCoins(sdk.NewInt64Coin(didtypes.BaseMinimalDenom, 1*didtypes.BaseFactor)) // 1 CHEQ
409+
gasLimit := testdata.NewTestGasLimit()
410+
Expect(s.txBuilder.SetMsgs(msg)).To(BeNil())
411+
s.txBuilder.SetFeeAmount(feeAmount)
412+
s.txBuilder.SetGasLimit(gasLimit)
413+
s.txBuilder.SetFeePayer(addr1)
414+
415+
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
416+
tx, err := s.CreateTestTx(privs, accNums, accSeqs, s.ctx.ChainID())
417+
Expect(err).To(BeNil())
418+
419+
// set account with sufficient funds
420+
acc := s.app.AccountKeeper.NewAccountWithAddress(s.ctx, addr1)
421+
s.app.AccountKeeper.SetAccount(s.ctx, acc)
422+
amount := sdk.NewInt(300_000_000_000) // 300 CHEQ
423+
err = testutil.FundAccount(s.app.BankKeeper, s.ctx, addr1, sdk.NewCoins(sdk.NewCoin(didtypes.BaseMinimalDenom, amount)))
424+
Expect(err).To(BeNil())
425+
426+
dfd := cheqdante.NewOverAllDecorator(decorators...)
427+
antehandler := sdk.ChainAnteDecorators(dfd)
428+
429+
// get feemarket params
430+
feemarketParams, err := s.app.FeeMarketKeeper.GetParams(s.ctx)
431+
Expect(err).To(BeNil())
432+
433+
// enforced enablement
434+
feemarketParams.Enabled = true
435+
436+
// enforce burn
437+
feemarketParams.DistributeFees = false
438+
439+
// enforce maximum block utilisation
440+
feemarketParams.MaxBlockUtilization = feemarkettypes.DefaultMaxBlockUtilization
441+
442+
// set minimum gas prices to realistic value
443+
feemarketParams.MinBaseGasPrice = sdk.MustNewDecFromStr("0.5")
444+
445+
err = s.app.FeeMarketKeeper.SetParams(s.ctx, feemarketParams)
446+
Expect(err).To(BeNil())
447+
448+
// get feemarket state
449+
feemarketState, err := s.app.FeeMarketKeeper.GetState(s.ctx)
450+
Expect(err).To(BeNil())
451+
452+
// set base gas price to realistic value
453+
feemarketState.BaseGasPrice = sdk.MustNewDecFromStr("0.5")
454+
455+
// set feemarket state
456+
err = s.app.FeeMarketKeeper.SetState(s.ctx, feemarketState)
457+
Expect(err).To(BeNil())
458+
459+
taxDecorator := cheqdpost.NewTaxDecorator(s.app.AccountKeeper, s.app.BankKeeper, s.app.FeeGrantKeeper, s.app.DidKeeper, s.app.ResourceKeeper, s.app.FeeMarketKeeper)
460+
posthandler := sdk.ChainPostDecorators(taxDecorator)
461+
462+
// get supply before tx
463+
supplyBefore, _, err := s.app.BankKeeper.GetPaginatedTotalSupply(s.ctx, &query.PageRequest{})
464+
Expect(err).To(BeNil())
465+
466+
// antehandler should not error since we make sure that the fee is sufficient in DeliverTx (simulate=false only, Posthandler will check it otherwise)
467+
newCtx, err := antehandler(s.ctx, tx, false)
468+
Expect(err).To(BeNil(), "Tx errored when non-taxable on deliverTx")
469+
_, _, proposer := testdata.KeyTestPubAddr()
470+
s.ctx = newCtx
471+
a := s.ctx.BlockHeader()
472+
a.ProposerAddress = proposer
473+
newCtx = s.ctx.WithBlockHeader(a)
474+
s.ctx = newCtx
475+
_, err = posthandler(s.ctx, tx, false, true)
476+
Expect(err).To(BeNil(), "Tx errored when non-taxable on deliverTx from posthandler")
477+
478+
// check balance of fee payer
479+
balance := s.app.BankKeeper.GetBalance(s.ctx, addr1, didtypes.BaseMinimalDenom)
480+
Expect(amount.Sub(sdk.NewInt(feeAmount.AmountOf(didtypes.BaseMinimalDenom).Int64()))).To(Equal(balance.Amount), "Fee amount subtracted was not equal to fee amount required for non-taxable tx")
481+
482+
// get supply after tx
483+
supplyAfter, _, err := s.app.BankKeeper.GetPaginatedTotalSupply(s.ctx, &query.PageRequest{})
484+
Expect(err).To(BeNil())
485+
486+
// check that supply was not deflated
487+
Expect(supplyBefore).To(Equal(supplyAfter), "Supply was deflated")
488+
489+
// check that reward has been sent to the fee collector
490+
feeCollector := s.app.AccountKeeper.GetModuleAddress(feemarkettypes.FeeCollectorName)
491+
feeCollectorBalance := s.app.BankKeeper.GetBalance(s.ctx, feeCollector, didtypes.BaseMinimalDenom)
492+
493+
Expect((feeCollectorBalance.Amount).GT(math.NewInt(0)))
494+
})
495+
402496
It("TaxableTx Lifecycle on Simulation", func() {
403497
// keys and addresses
404498
priv1, _, addr1 := testdata.KeyTestPubAddr()

app/app.go

+7
Original file line numberDiff line numberDiff line change
@@ -1176,27 +1176,34 @@ func (app *App) setupUpgradeStoreLoaders() {
11761176
}
11771177

11781178
func ConfigureFeeMarketModule(ctx sdk.Context, keeper *feemarketkeeper.Keeper) error {
1179+
// get feemarket params
11791180
params, err := keeper.GetParams(ctx)
11801181
if err != nil {
11811182
return err
11821183
}
11831184

1185+
// configure feemarket params
11841186
params.Enabled = true
11851187
params.FeeDenom = resourcetypes.BaseMinimalDenom
11861188
params.DistributeFees = false // burn fees
11871189
params.MinBaseGasPrice = sdk.MustNewDecFromStr("0.5")
11881190
params.MaxBlockUtilization = feemarkettypes.DefaultMaxBlockUtilization
1191+
1192+
// set feemarket params
11891193
if err := keeper.SetParams(ctx, params); err != nil {
11901194
return err
11911195
}
11921196

1197+
// get feemarket state
11931198
state, err := keeper.GetState(ctx)
11941199
if err != nil {
11951200
return err
11961201
}
11971202

1203+
// configure feemarket state
11981204
state.BaseGasPrice = sdk.MustNewDecFromStr("0.5")
11991205

1206+
// set feemarket state
12001207
return keeper.SetState(ctx, state)
12011208
}
12021209

app/upgrades/v3/const.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package v3
22

33
const (
44
UpgradeName = "v3"
5-
MinorUpgradeName = "v3.1-new"
5+
MinorUpgradeName = "v3.1.5"
66
)

tests/integration/cli/config.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ const (
1111
KeyringBackend = "test"
1212
OutputFormat = "json"
1313
Gas = "auto"
14-
GasAdjustment = "2.5"
15-
GasPrices = "60ncheq"
14+
GasAdjustment = "3.5"
15+
GasPrices = "10000ncheq"
1616
)
1717

1818
const (

tests/integration/cli/query.go

+30
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,36 @@ func QueryProposal(container, id string) (govtypesv1.Proposal, error) {
166166
return resp, nil
167167
}
168168

169+
func QueryFeemarketGasPrice(denom string) (feemarkettypes.GasPriceResponse, error) {
170+
res, err := Query("feemarket", "gas-price", denom)
171+
if err != nil {
172+
return feemarkettypes.GasPriceResponse{}, err
173+
}
174+
175+
var resp feemarkettypes.GasPriceResponse
176+
err = helpers.Codec.UnmarshalJSON([]byte(res), &resp)
177+
if err != nil {
178+
return feemarkettypes.GasPriceResponse{}, err
179+
}
180+
181+
return resp, nil
182+
}
183+
184+
func QueryFeemarketGasPrices() (feemarkettypes.GasPricesResponse, error) {
185+
res, err := Query("feemarket", "gas-prices")
186+
if err != nil {
187+
return feemarkettypes.GasPricesResponse{}, err
188+
}
189+
190+
var resp feemarkettypes.GasPricesResponse
191+
err = helpers.Codec.UnmarshalJSON([]byte(res), &resp)
192+
if err != nil {
193+
return feemarkettypes.GasPricesResponse{}, err
194+
}
195+
196+
return resp, nil
197+
}
198+
169199
func QueryFeemarketParams() (feemarkettypes.Params, error) {
170200
res, err := Query("feemarket", "params")
171201
if err != nil {

tests/integration/cli/tx.go

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"encoding/json"
5+
"fmt"
56

67
"github.com/cheqd/cheqd-node/tests/integration/helpers"
78
"github.com/cheqd/cheqd-node/tests/integration/network"
@@ -43,6 +44,8 @@ func Tx(module, tx, from string, feeParams []string, txArgs ...string) (sdk.TxRe
4344
// Other args
4445
args = append(args, txArgs...)
4546

47+
fmt.Println("args", args)
48+
4649
output, err := Exec(args...)
4750
if err != nil {
4851
return sdk.TxResponse{}, err
@@ -176,3 +179,7 @@ func SubmitProposalTx(from, pathToDir string, feeParams []string) (sdk.TxRespons
176179
func VoteProposalTx(from, option, id string, feeParams []string) (sdk.TxResponse, error) {
177180
return Tx("gov", "vote", from, feeParams, option, id)
178181
}
182+
183+
func SendTokensTx(from, to, amount string, feeParams []string) (sdk.TxResponse, error) {
184+
return Tx("bank", "send", from, feeParams, from, to, amount)
185+
}

tests/integration/cli_defi_test.go

+73-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
cli "github.com/cheqd/cheqd-node/tests/integration/cli"
77
helpers "github.com/cheqd/cheqd-node/tests/integration/helpers"
88

9+
sdkmath "cosmossdk.io/math"
910
"github.com/cheqd/cheqd-node/tests/integration/testdata"
1011
didtypes "github.com/cheqd/cheqd-node/x/did/types"
1112
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -24,8 +25,8 @@ var _ = Describe("Upgrade - Burn coins from relevant message signer", func() {
2425
// assert no error
2526
Expect(err).To(BeNil())
2627

27-
// generate fixed fees, in which case 500,000,000 ncheq or 0.5 cheq
28-
fees := helpers.GenerateFees("500000000ncheq")
28+
// generate fixed fees, in which case 3,500,000,000 ncheq or 3.5 cheq
29+
fees := helpers.GenerateFees("3500000000ncheq")
2930

3031
// burn the coins
3132
res, err := cli.BurnMsg(testdata.BASE_ACCOUNT_1, burnCoins.String(), fees)
@@ -46,13 +47,13 @@ var _ = Describe("Upgrade - Burn coins from relevant message signer", func() {
4647
diff := balanceBefore.Sub(balanceAfter)
4748

4849
// assert the difference is equal to the coins burnt
49-
total := burnCoins.Add(sdk.NewCoin(didtypes.BaseMinimalDenom, sdk.NewInt(500_000_000)))
50+
total := burnCoins.Add(sdk.NewCoin(didtypes.BaseMinimalDenom, sdk.NewInt(3_500_000_000)))
5051

5152
// assert the difference is equal to the coins burnt
5253
Expect(diff).To(Equal(total))
5354
})
5455

55-
It("shouldn't burn as their are insufficient funds in the sender", func() {
56+
It("shouldn't burn if sender has insufficient funds", func() {
5657
// define the coins to burn, in which case 1,000,000 ncheq or 0.01 cheq
5758
coins := sdk.NewCoin(didtypes.BaseMinimalDenom, sdk.NewInt(1_000_000))
5859

@@ -62,13 +63,13 @@ var _ = Describe("Upgrade - Burn coins from relevant message signer", func() {
6263
// assert no error
6364
Expect(err).To(BeNil())
6465

65-
// generate fixed fees, in which case 500,000,000 ncheq or 0.5 cheq
66-
fees := helpers.GenerateFees("500000000ncheq")
66+
// generate fixed fees, in which case 3,500,000,000 ncheq or 3.5 cheq
67+
fees := helpers.GenerateFees("3500000000ncheq")
6768

6869
// burn the coins
6970
res, err := cli.BurnMsg(testdata.BASE_ACCOUNT_3, coins.String(), fees)
7071

71-
// assert no error
72+
// assert error
7273
Expect(err).NotTo(BeNil())
7374

7475
// assert the response code is 0
@@ -84,3 +85,68 @@ var _ = Describe("Upgrade - Burn coins from relevant message signer", func() {
8485
Expect(balanceBefore).To(Equal(balanceAfter))
8586
})
8687
})
88+
89+
var _ = Describe("Upgrade - Feemarket fees (non-taxable transactions)", func() {
90+
It("should successfully submit a non-taxable transaction with sufficient fees (--gas-prices)", func() {
91+
// query feemarket gas price for the base minimal denom
92+
gasPrice, err := cli.QueryFeemarketGasPrice(didtypes.BaseMinimalDenom)
93+
94+
// print the gas price
95+
By("Gas Price: " + gasPrice.Price.String())
96+
97+
// assert no error
98+
Expect(err).To(BeNil())
99+
100+
// define the coins to send, in which case 1,000,000,000 ncheq or 1 cheq
101+
coins := sdk.NewCoin(didtypes.BaseMinimalDenom, sdk.NewInt(1_000_000_000))
102+
103+
// compute gas price, using offset
104+
gasPrice.Price.Amount = gasPrice.Price.Amount.Mul(sdkmath.LegacyNewDec(didtypes.FeeOffset))
105+
106+
// define feeParams
107+
feeParams := []string{
108+
"--gas", cli.Gas,
109+
"--gas-adjustment", cli.GasAdjustment,
110+
"--gas-prices", gasPrice.Price.String(),
111+
}
112+
113+
// send the coins, balance assertions are intentionally omitted or out of scope
114+
res, err := cli.SendTokensTx(testdata.BASE_ACCOUNT_1, testdata.BASE_ACCOUNT_2_ADDR, coins.String(), feeParams)
115+
116+
// assert no error
117+
Expect(err).To(BeNil())
118+
119+
// assert the response code is 0
120+
Expect(res.Code).To(BeEquivalentTo(0))
121+
})
122+
123+
It("should successfully submit a non-taxable transaction with sufficient fees (--fees)", func() {
124+
// query feemarket gas price for the base minimal denom
125+
gasPrice, err := cli.QueryFeemarketGasPrice(didtypes.BaseMinimalDenom)
126+
127+
// print the gas price
128+
By("Gas Price: " + gasPrice.Price.String())
129+
130+
// assert no error
131+
Expect(err).To(BeNil())
132+
133+
// define the coins to send, in which case 1,000,000,000 ncheq or 1 cheq
134+
coins := sdk.NewCoin(didtypes.BaseMinimalDenom, sdk.NewInt(1_000_000_000))
135+
136+
// define static fees, in which case gas price is multiplied by roughly 3 or greater, times the minimal base denom
137+
// consider multiplying in the range of [1.5, 3] times the gas price
138+
gasPrice.Price.Amount = gasPrice.Price.Amount.Mul(sdkmath.LegacyNewDec(3)).Mul(sdkmath.LegacyNewDec(didtypes.BaseFactor))
139+
140+
// define feeParams
141+
feeParams := helpers.GenerateFees(gasPrice.Price.String())
142+
143+
// send the coins, balance assertions are intentionally omitted or out of scope
144+
res, err := cli.SendTokensTx(testdata.BASE_ACCOUNT_1, testdata.BASE_ACCOUNT_2_ADDR, coins.String(), feeParams)
145+
146+
// assert no error
147+
Expect(err).To(BeNil())
148+
149+
// assert the response code is 0
150+
Expect(res.Code).To(BeEquivalentTo(0))
151+
})
152+
})

x/did/types/denom.go

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ package types
33
const (
44
BaseMinimalDenom = "ncheq"
55
BaseFactor = 1e9
6+
FeeOffset = 1e4
67
)

0 commit comments

Comments
 (0)