Skip to content

Commit e071a75

Browse files
feat: adjust validateBurnedAmount params
1 parent b685484 commit e071a75

File tree

5 files changed

+89
-78
lines changed

5 files changed

+89
-78
lines changed

src/utils/validateAvaxBurnedAmountEtna.test.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,10 @@ import {
2424
} from '../vms/pvm';
2525
import { TransferableOutput } from '../serializable';
2626
import { nodeId } from '../fixtures/common';
27-
import { feeState as testFeeState } from '../fixtures/pvm';
2827
import { testSubnetId } from '../fixtures/transactions';
2928
import { blsPublicKeyBytes, blsSignatureBytes } from '../fixtures/primitives';
3029
import { validateAvaxBurnedAmountEtna } from './validateAvaxBurnedAmountEtna';
3130

32-
const incorrectBurnedAmount = 1n;
33-
const correctBurnedAmount = 1000000n;
34-
3531
const utxoMock = new Utxo(
3632
utxoId(),
3733
Id.fromString(testContext.avaxAssetID),
@@ -91,14 +87,12 @@ describe('validateAvaxBurnedAmountEtna', () => {
9187
try {
9288
validateAvaxBurnedAmountEtna({
9389
unsignedTx,
94-
context: testContext,
95-
burnedAmount: correctBurnedAmount,
96-
feeState: testFeeState(),
90+
burnedAmount: 1000000n,
91+
baseFee: 1n,
92+
feeTolerance: 20,
9793
});
9894
} catch (error) {
99-
expect((error as Error).message).toEqual(
100-
'Unsupported transaction type.',
101-
);
95+
expect((error as Error).message).toEqual('tx type is not supported');
10296
}
10397
});
10498
});
@@ -113,6 +107,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
113107
[utxoMock],
114108
[outputMock],
115109
),
110+
baseFee: 3830000n,
111+
burnedAmount: 3840000n,
116112
},
117113
{
118114
name: 'export from P',
@@ -123,6 +119,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
123119
[utxoMock],
124120
[outputMock],
125121
),
122+
baseFee: 4190000n,
123+
burnedAmount: 4390000n,
126124
},
127125
{
128126
name: 'import to P',
@@ -133,6 +131,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
133131
[testAddress2],
134132
[testAddress1],
135133
),
134+
baseFee: 3380000n,
135+
burnedAmount: 3980000n,
136136
},
137137
{
138138
name: 'create subnet',
@@ -142,6 +142,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
142142
[testAddress1],
143143
[testAddress1],
144144
),
145+
baseFee: 3430000n,
146+
burnedAmount: 3930000n,
145147
},
146148
{
147149
name: 'create blockchain',
@@ -156,6 +158,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
156158
{},
157159
[0],
158160
),
161+
baseFee: 5340000n,
162+
burnedAmount: 5660000n,
159163
},
160164
{
161165
name: 'add subnet validator',
@@ -170,6 +174,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
170174
'subnet',
171175
[0],
172176
),
177+
baseFee: 4660000n,
178+
burnedAmount: 4960000n,
173179
},
174180
{
175181
name: 'remove subnet validator',
@@ -181,6 +187,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
181187
Id.fromHex(testSubnetId).toString(),
182188
[0],
183189
),
190+
baseFee: 4420000n,
191+
burnedAmount: 4420000n,
184192
},
185193
{
186194
name: 'add permissionless validator (subnet)',
@@ -202,6 +210,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
202210
blsPublicKeyBytes(),
203211
blsSignatureBytes(),
204212
),
213+
baseFee: 6570000n,
214+
burnedAmount: 7570000n,
205215
},
206216
{
207217
name: 'add permissionless delegator (subnet)',
@@ -219,6 +229,8 @@ describe('validateAvaxBurnedAmountEtna', () => {
219229
1,
220230
0n,
221231
),
232+
baseFee: 4850000n,
233+
burnedAmount: 4900000n,
222234
},
223235
{
224236
name: 'transfer subnet ownership',
@@ -230,35 +242,37 @@ describe('validateAvaxBurnedAmountEtna', () => {
230242
[0, 2],
231243
[testAddress2],
232244
),
245+
baseFee: 5300000n,
246+
burnedAmount: 5900000n,
233247
},
234248
];
235249

236-
describe.each(testData)('$name', ({ unsignedTx }) => {
250+
describe.each(testData)('$name', ({ unsignedTx, baseFee, burnedAmount }) => {
237251
it('returns true if burned amount is correct', () => {
238252
const result = validateAvaxBurnedAmountEtna({
239253
unsignedTx,
240-
context: testContext,
241-
burnedAmount: correctBurnedAmount,
242-
feeState: testFeeState(),
254+
burnedAmount,
255+
baseFee,
256+
feeTolerance: 20,
243257
});
244258

245259
expect(result).toStrictEqual({
246260
isValid: true,
247-
txFee: correctBurnedAmount,
261+
txFee: burnedAmount,
248262
});
249263
});
250264

251265
it('returns false if burned amount is not correct', () => {
252266
const result = validateAvaxBurnedAmountEtna({
253267
unsignedTx,
254-
context: testContext,
255-
burnedAmount: incorrectBurnedAmount,
256-
feeState: { ...testFeeState(), price: 10_000n },
268+
burnedAmount: burnedAmount * 30n,
269+
feeTolerance: 20,
270+
baseFee,
257271
});
258272

259273
expect(result).toStrictEqual({
260274
isValid: false,
261-
txFee: incorrectBurnedAmount,
275+
txFee: burnedAmount * 30n,
262276
});
263277
});
264278
});

src/utils/validateAvaxBurnedAmountEtna.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { Context } from '../vms/context/model';
21
import {
32
isAddPermissionlessDelegatorTx,
43
isAddPermissionlessValidatorTx,
@@ -12,29 +11,28 @@ import {
1211
isTransferSubnetOwnershipTx,
1312
} from '../serializable/pvm';
1413
import type { UnsignedTx } from '../vms/common';
15-
import type { FeeState } from '../vms/pvm';
16-
import { calculateFee } from '../vms/pvm/txs/fee/calculator';
1714

1815
export const validateAvaxBurnedAmountEtna = ({
1916
unsignedTx,
20-
context,
2117
burnedAmount,
22-
feeState,
18+
baseFee,
19+
feeTolerance,
2320
}: {
2421
unsignedTx: UnsignedTx;
25-
context: Context;
2622
burnedAmount: bigint;
27-
feeState: FeeState;
23+
baseFee: bigint; // pvm dynamic fee caculator: @see https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/txs/fee/dynamic_calculator.go
24+
feeTolerance: number; // tolerance percentage range where the burned amount is considered valid. e.g.: with FeeTolerance = 20% -> (expectedFee <= burnedAmount <= expectedFee * 1.2)
2825
}): { isValid: boolean; txFee: bigint } => {
2926
const tx = unsignedTx.getTx();
3027

31-
const expectedFee = calculateFee(
32-
unsignedTx.getTx(),
33-
context.platformFeeConfig.weights,
34-
feeState.price < context.platformFeeConfig.minPrice
35-
? context.platformFeeConfig.minPrice
36-
: feeState.price,
37-
);
28+
const feeToleranceInt = Math.floor(feeTolerance);
29+
30+
if (feeToleranceInt < 1 || feeToleranceInt > 100) {
31+
throw new Error('feeTolerance must be [1,100]');
32+
}
33+
34+
const min = baseFee;
35+
const max = (baseFee * (100n + BigInt(feeToleranceInt))) / 100n;
3836

3937
if (
4038
isPvmBaseTx(tx) ||
@@ -49,7 +47,7 @@ export const validateAvaxBurnedAmountEtna = ({
4947
isTransferSubnetOwnershipTx(tx)
5048
) {
5149
return {
52-
isValid: burnedAmount >= expectedFee,
50+
isValid: burnedAmount >= min && burnedAmount <= max,
5351
txFee: burnedAmount,
5452
};
5553
}

src/utils/validateBurnedAmount.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { EVMTx } from '../serializable/evm';
44
import { isImportExportTx as isEvmImportExportTx } from '../serializable/evm';
55
import { getBurnedAmountByTx } from './getBurnedAmountByTx';
66
import type { AvaxTx } from '../serializable/avax';
7-
import type { FeeState } from '../vms/pvm';
87
import { validateEvmBurnedAmount } from './validateEvmBurnedAmount';
98
import type { GetUpgradesInfoResponse } from '../info/model';
109
import { isEtnaEnabled } from './isEtnaEnabled';
@@ -39,22 +38,25 @@ const isPreEtnaTx = (tx: Transaction) => {
3938
);
4039
};
4140

41+
/**
42+
* baseFee:
43+
* - evm fee: fetched from the network and converted into nAvax (https://docs.avax.network/quickstart/transaction-fees#c-chain-fees)
44+
* - pvm dynamic fee caculator: @see https://github.com/ava-labs/avalanchego/blob/master/vms/platformvm/txs/fee/dynamic_calculator.go
45+
*/
4246
export const validateBurnedAmount = ({
4347
unsignedTx,
4448
context,
45-
feeState,
4649
upgradesInfo,
4750
burnedAmount,
48-
evmBaseFee,
49-
evmFeeTolerance,
51+
baseFee,
52+
feeTolerance,
5053
}: {
5154
unsignedTx: UnsignedTx;
5255
context: Context;
53-
feeState: FeeState;
5456
upgradesInfo: GetUpgradesInfoResponse;
5557
burnedAmount?: bigint;
56-
evmBaseFee?: bigint; // fetched from the network and converted into nAvax (https://docs.avax.network/quickstart/transaction-fees#c-chain-fees)
57-
evmFeeTolerance?: number; // tolerance percentage range where the burned amount is considered valid. e.g.: with evmFeeTolerance = 20% -> (evmBaseFee * 0.8 <= burnedAmount <= evmBaseFee * 1.2)
58+
baseFee: bigint;
59+
feeTolerance: number; // tolerance percentage range where the burned amount is considered valid.
5860
}): { isValid: boolean; txFee: bigint } => {
5961
const tx = unsignedTx.getTx();
6062
const burned = burnedAmount ?? _getBurnedAmount(tx, context);
@@ -63,16 +65,16 @@ export const validateBurnedAmount = ({
6365
return validateEvmBurnedAmount({
6466
unsignedTx,
6567
burnedAmount: burned,
66-
evmBaseFee,
67-
evmFeeTolerance,
68+
baseFee,
69+
feeTolerance,
6870
});
6971
}
7072
if (isEtnaEnabled(upgradesInfo) || !isPreEtnaTx(tx)) {
7173
return validateAvaxBurnedAmountEtna({
7274
unsignedTx,
73-
context,
75+
baseFee,
7476
burnedAmount: burned,
75-
feeState,
77+
feeTolerance,
7678
});
7779
}
7880
return validateAvaxBurnedAmountPreEtna({

src/utils/validateEvmBurnedAmount.test.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,39 @@ describe('validateEvmBurnedAmount', () => {
3030
[testAddress1],
3131
1n,
3232
);
33-
it('throws if evmFeeTolerance is incorrect', () => {
33+
it('throws if feeTolerance is incorrect', () => {
3434
expect(() =>
3535
validateEvmBurnedAmount({
3636
unsignedTx,
3737
burnedAmount: (280750n * 75n) / 100n, // 25% lower,
38-
evmBaseFee: 25n,
39-
evmFeeTolerance: 0.5,
38+
baseFee: 25n,
39+
feeTolerance: 0.5,
4040
}),
41-
).toThrowError('evmFeeTolerance must be [1,100]');
41+
).toThrowError('feeTolerance must be [1,100]');
4242

4343
expect(() =>
4444
validateEvmBurnedAmount({
4545
unsignedTx,
4646
burnedAmount: (280750n * 75n) / 100n, // 25% lower,
47-
evmBaseFee: 25n,
48-
evmFeeTolerance: 101,
47+
baseFee: 25n,
48+
feeTolerance: 101,
4949
}),
50-
).toThrowError('evmFeeTolerance must be [1,100]');
50+
).toThrowError('feeTolerance must be [1,100]');
5151
});
5252

5353
it('returns true if burned amount is in the tolerance range', () => {
5454
const resultLower = validateEvmBurnedAmount({
5555
unsignedTx,
5656
burnedAmount: (280750n * 75n) / 100n, // 25% lower
57-
evmBaseFee: 25n,
58-
evmFeeTolerance: 50.9,
57+
baseFee: 25n,
58+
feeTolerance: 50.9,
5959
});
6060

6161
const resultHigher = validateEvmBurnedAmount({
6262
unsignedTx,
6363
burnedAmount: (280750n * 125n) / 100n, // 25% higher
64-
evmBaseFee: 25n,
65-
evmFeeTolerance: 50.9,
64+
baseFee: 25n,
65+
feeTolerance: 50.9,
6666
});
6767

6868
expect(resultLower).toStrictEqual({
@@ -79,15 +79,15 @@ describe('validateEvmBurnedAmount', () => {
7979
const resultLower = validateEvmBurnedAmount({
8080
unsignedTx,
8181
burnedAmount: (280750n * 49n) / 100n, // 51% lower
82-
evmBaseFee: 25n,
83-
evmFeeTolerance: 50.9,
82+
baseFee: 25n,
83+
feeTolerance: 50.9,
8484
});
8585

8686
const resultHigher = validateEvmBurnedAmount({
8787
unsignedTx,
8888
burnedAmount: (280750n * 151n) / 100n, // 51% higher
89-
evmBaseFee: 25n,
90-
evmFeeTolerance: 50.9,
89+
baseFee: 25n,
90+
feeTolerance: 50.9,
9191
});
9292

9393
expect(resultLower).toStrictEqual({
@@ -115,15 +115,15 @@ describe('validateEvmBurnedAmount', () => {
115115
const resultLower = validateEvmBurnedAmount({
116116
unsignedTx,
117117
burnedAmount: (280750n * 75n) / 100n, // 25% lower
118-
evmBaseFee: 25n,
119-
evmFeeTolerance: 50.9,
118+
baseFee: 25n,
119+
feeTolerance: 50.9,
120120
});
121121

122122
const resultHigher = validateEvmBurnedAmount({
123123
unsignedTx,
124124
burnedAmount: (280750n * 125n) / 100n, // 25% higher
125-
evmBaseFee: 25n,
126-
evmFeeTolerance: 50.9,
125+
baseFee: 25n,
126+
feeTolerance: 50.9,
127127
});
128128

129129
expect(resultLower).toStrictEqual({
@@ -140,15 +140,15 @@ describe('validateEvmBurnedAmount', () => {
140140
const resultLower = validateEvmBurnedAmount({
141141
unsignedTx,
142142
burnedAmount: (280750n * 49n) / 100n, // 51% lower
143-
evmBaseFee: 25n,
144-
evmFeeTolerance: 50.9,
143+
baseFee: 25n,
144+
feeTolerance: 50.9,
145145
});
146146

147147
const resultHigher = validateEvmBurnedAmount({
148148
unsignedTx,
149149
burnedAmount: (280750n * 151n) / 100n, // 51% higher
150-
evmBaseFee: 25n,
151-
evmFeeTolerance: 50.9,
150+
baseFee: 25n,
151+
feeTolerance: 50.9,
152152
});
153153

154154
expect(resultLower).toStrictEqual({

0 commit comments

Comments
 (0)