@@ -13,6 +13,8 @@ import {
13
13
updateTokenfactoryParamsProposal ,
14
14
AddSchedule ,
15
15
RemoveSchedule ,
16
+ updateGlobalFeeParamsProposal ,
17
+ updateConsumerParamsProposal ,
16
18
} from '@neutron-org/neutronjsplus/dist/proposal' ;
17
19
import { LocalState } from '../../helpers/local_state' ;
18
20
import { RunnerTestSuite , inject } from 'vitest' ;
@@ -23,10 +25,14 @@ import { QueryClientImpl as AdminQueryClient } from '@neutron-org/neutronjs/cosm
23
25
import { QueryClientImpl as TokenfactoryQueryClient } from '@neutron-org/neutronjs/osmosis/tokenfactory/v1beta1/query.rpc.Query' ;
24
26
import { QueryClientImpl as UpgradeQueryClient } from '@neutron-org/neutronjs/cosmos/upgrade/v1beta1/query.rpc.Query' ;
25
27
import { QueryClientImpl as DexQueryClient } from '@neutron-org/neutronjs/neutron/dex/query.rpc.Query' ;
28
+ import { QueryClientImpl as DynamicfeesQueryClient } from '@neutron-org/neutronjs/neutron/dynamicfees/v1/query.rpc.Query' ;
29
+ import { QueryClientImpl as GlobalfeeQueryClient } from '@neutron-org/neutronjs/gaia/globalfee/v1beta1/query.rpc.Query' ;
30
+ import { QueryClientImpl as CCVQueryClient } from '@neutron-org/neutronjs/interchain_security/ccv/consumer/v1/query.rpc.Query' ;
26
31
import { SigningNeutronClient } from '../../helpers/signing_neutron_client' ;
27
32
import config from '../../config.json' ;
28
33
import { Wallet } from '../../helpers/wallet' ;
29
34
import { ADMIN_MODULE_ADDRESS } from '@neutron-org/neutronjsplus/dist/constants' ;
35
+ import { Duration } from '@neutron-org/neutronjs/google/protobuf/duration' ;
30
36
31
37
describe ( 'Neutron / Chain Manager' , ( ) => {
32
38
let testState : LocalState ;
@@ -39,6 +45,9 @@ describe('Neutron / Chain Manager', () => {
39
45
let cronQuerier : CronQueryClient ;
40
46
let tokenfactoryQuerier : TokenfactoryQueryClient ;
41
47
let dexQuerier : DexQueryClient ;
48
+ let dynamicfeesQuerier : DynamicfeesQueryClient ;
49
+ let globalfeeQuerier : GlobalfeeQueryClient ;
50
+ let ccvQuerier : CCVQueryClient ;
42
51
let upgradeQuerier : UpgradeQueryClient ;
43
52
let chainManagerAddress : string ;
44
53
@@ -97,6 +106,9 @@ describe('Neutron / Chain Manager', () => {
97
106
cronQuerier = new CronQueryClient ( neutronRpcClient ) ;
98
107
dexQuerier = new DexQueryClient ( neutronRpcClient ) ;
99
108
upgradeQuerier = new UpgradeQueryClient ( neutronRpcClient ) ;
109
+ dynamicfeesQuerier = new DynamicfeesQueryClient ( neutronRpcClient ) ;
110
+ globalfeeQuerier = new GlobalfeeQueryClient ( neutronRpcClient ) ;
111
+ ccvQuerier = new CCVQueryClient ( neutronRpcClient ) ;
100
112
} ) ;
101
113
102
114
// We need to do this because the real main dao has a super long voting period.
@@ -205,6 +217,34 @@ describe('Neutron / Chain Manager', () => {
205
217
good_til_purge_allowance : true ,
206
218
} ,
207
219
} ,
220
+ {
221
+ update_ccv_params_permission : {
222
+ blocks_per_distribution_transmission : true ,
223
+ distribution_transmission_channel : true ,
224
+ provider_fee_pool_addr_str : true ,
225
+ ccv_timeout_period : true ,
226
+ transfer_timeout_period : true ,
227
+ consumer_redistribution_fraction : true ,
228
+ historical_entries : true ,
229
+ unbonding_period : true ,
230
+ soft_opt_out_threshold : true ,
231
+ reward_denoms : true ,
232
+ provider_reward_denoms : true ,
233
+ retry_delay_period : true ,
234
+ } ,
235
+ } ,
236
+ {
237
+ update_globalfee_params_permission : {
238
+ minimum_gas_prices : true ,
239
+ bypass_min_fee_msg_types : true ,
240
+ max_total_bypass_min_fee_msg_gas_usage : true ,
241
+ } ,
242
+ } ,
243
+ {
244
+ update_dynamicfees_params_permission : {
245
+ ntrn_prices : true ,
246
+ } ,
247
+ } ,
208
248
] ,
209
249
} ,
210
250
} ,
@@ -252,6 +292,7 @@ describe('Neutron / Chain Manager', () => {
252
292
} ) ;
253
293
254
294
test ( 'execute timelocked: success' , async ( ) => {
295
+ const cronParamsBefore = await cronQuerier . params ( ) ;
255
296
await waitSeconds ( 10 ) ;
256
297
257
298
await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
@@ -262,6 +303,12 @@ describe('Neutron / Chain Manager', () => {
262
303
263
304
const cronParams = await cronQuerier . params ( ) ;
264
305
expect ( cronParams . params . limit ) . toEqual ( 42n ) ;
306
+ // check that every params field before proposal execution differs from the field after proposal execution
307
+ expect (
308
+ Object . keys ( cronParamsBefore ) . every (
309
+ ( key ) => cronParamsBefore [ key ] !== cronParams [ key ] ,
310
+ ) ,
311
+ ) . toBeTrue ( ) ;
265
312
} ) ;
266
313
} ) ;
267
314
@@ -290,13 +337,13 @@ describe('Neutron / Chain Manager', () => {
290
337
const timelockedProp = await subdaoMember1 . supportAndExecuteProposal (
291
338
proposalId ,
292
339
) ;
293
-
294
340
expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
295
341
expect ( timelockedProp . status ) . toEqual ( 'timelocked' ) ;
296
342
expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
297
343
} ) ;
298
344
299
345
test ( 'execute timelocked: success' , async ( ) => {
346
+ const tokenfactoryParamsBefore = await tokenfactoryQuerier . params ( ) ;
300
347
await waitSeconds ( 10 ) ;
301
348
302
349
await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
@@ -319,13 +366,21 @@ describe('Neutron / Chain Manager', () => {
319
366
denomCreator : 'neutron1m9l358xunhhwds0568za49mzhvuxx9ux8xafx2' ,
320
367
} ,
321
368
] ) ;
369
+ // check that every params field before proposal execution differs from the field after proposal execution
370
+ expect (
371
+ Object . keys ( tokenfactoryParamsBefore ) . every (
372
+ ( key ) => tokenfactoryParamsBefore [ key ] !== tokenfactoryParams [ key ] ,
373
+ ) ,
374
+ ) . toBeTrue ( ) ;
322
375
} ) ;
323
376
} ) ;
324
377
325
378
describe ( 'ALLOW_ONLY: change DEX parameters' , ( ) => {
326
379
let proposalId : number ;
327
380
const newParams = {
328
- fee_tiers : [ 1 , 2 , 99 ] ,
381
+ // types mixed on purpose, to check contract parser.
382
+ // Numeric types in neutron-std can be deserialized from both number and string
383
+ fee_tiers : [ '1' , '2' , 99 ] ,
329
384
paused : true ,
330
385
max_jits_per_block : 11 ,
331
386
good_til_purge_allowance : 50000 ,
@@ -349,6 +404,7 @@ describe('Neutron / Chain Manager', () => {
349
404
} ) ;
350
405
351
406
test ( 'execute timelocked: success' , async ( ) => {
407
+ const dexParamsBefore = await dexQuerier . params ( ) ;
352
408
await waitSeconds ( 10 ) ;
353
409
354
410
await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
@@ -362,6 +418,200 @@ describe('Neutron / Chain Manager', () => {
362
418
expect ( dexParams . params . paused ) . toEqual ( true ) ;
363
419
expect ( dexParams . params . maxJitsPerBlock ) . toEqual ( 11n ) ;
364
420
expect ( dexParams . params . goodTilPurgeAllowance ) . toEqual ( 50000n ) ;
421
+ // check that every params field before proposal execution differs from the field after proposal execution
422
+ expect (
423
+ Object . keys ( dexParamsBefore ) . every (
424
+ ( key ) => dexParamsBefore [ key ] !== dexParams [ key ] ,
425
+ ) ,
426
+ ) . toBeTrue ( ) ;
427
+ } ) ;
428
+ } ) ;
429
+
430
+ describe ( 'ALLOW_ONLY: change Dynamicfees parameters' , ( ) => {
431
+ let proposalId : number ;
432
+ beforeAll ( async ( ) => {
433
+ proposalId = await subdaoMember1 . submitDynamicfeesChangeParamsProposal (
434
+ chainManagerAddress ,
435
+ 'Proposal #2' ,
436
+ 'Dynamicfees update params proposal. Will pass' ,
437
+ '1000' ,
438
+ {
439
+ ntrn_prices : [ { denom : 'newdenom' , amount : '0.5' } ] ,
440
+ } ,
441
+ ) ;
442
+
443
+ const timelockedProp = await subdaoMember1 . supportAndExecuteProposal (
444
+ proposalId ,
445
+ ) ;
446
+
447
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
448
+ expect ( timelockedProp . status ) . toEqual ( 'timelocked' ) ;
449
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
450
+ } ) ;
451
+
452
+ test ( 'execute timelocked: success' , async ( ) => {
453
+ const dynamicfeesParamsBefore = await dynamicfeesQuerier . params ( ) ;
454
+ await waitSeconds ( 10 ) ;
455
+
456
+ await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
457
+ const timelockedProp = await subDao . getTimelockedProposal ( proposalId ) ;
458
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
459
+ expect ( timelockedProp . status ) . toEqual ( 'executed' ) ;
460
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
461
+
462
+ const dynamicfeesParams = await dynamicfeesQuerier . params ( ) ;
463
+ expect ( dynamicfeesParams . params . ntrnPrices ) . toEqual ( [
464
+ { denom : 'newdenom' , amount : '0.5' } ,
465
+ ] ) ;
466
+ // check that every params field before proposal execution differs from the field after proposal execution
467
+ expect (
468
+ Object . keys ( dynamicfeesParamsBefore ) . every (
469
+ ( key ) => dynamicfeesParamsBefore [ key ] !== dynamicfeesParams [ key ] ,
470
+ ) ,
471
+ ) . toBeTrue ( ) ;
472
+ } ) ;
473
+ } ) ;
474
+
475
+ describe ( 'ALLOW_ONLY: change Globalfee parameters' , ( ) => {
476
+ let proposalId : number ;
477
+ beforeAll ( async ( ) => {
478
+ proposalId = await subdaoMember1 . submitUpdateParamsGlobalfeeProposal (
479
+ chainManagerAddress ,
480
+ 'Proposal #3' ,
481
+ 'Globalfee update params proposal. Will pass' ,
482
+ updateGlobalFeeParamsProposal ( {
483
+ minimum_gas_prices : [ { denom : 'untrn' , amount : '0.00111' } ] ,
484
+ bypass_min_fee_msg_types : [ '/gaia.globalfee.v1beta1.MsgUpdateParams' ] ,
485
+ max_total_bypass_min_fee_msg_gas_usage : '12345' ,
486
+ } ) ,
487
+ '1000' ,
488
+ ) ;
489
+
490
+ const timelockedProp = await subdaoMember1 . supportAndExecuteProposal (
491
+ proposalId ,
492
+ ) ;
493
+
494
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
495
+ expect ( timelockedProp . status ) . toEqual ( 'timelocked' ) ;
496
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
497
+ } ) ;
498
+
499
+ test ( 'execute timelocked: success' , async ( ) => {
500
+ const globalfeeParamsBefore = await globalfeeQuerier . params ( ) ;
501
+ await waitSeconds ( 10 ) ;
502
+
503
+ await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
504
+ const timelockedProp = await subDao . getTimelockedProposal ( proposalId ) ;
505
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
506
+ expect ( timelockedProp . status ) . toEqual ( 'executed' ) ;
507
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
508
+
509
+ const globalfeeParams = await globalfeeQuerier . params ( ) ;
510
+ expect ( globalfeeParams . params . minimumGasPrices ) . toEqual ( [
511
+ { denom : 'untrn' , amount : '0.00111' } ,
512
+ ] ) ;
513
+ expect ( globalfeeParams . params . bypassMinFeeMsgTypes ) . toEqual ( [
514
+ '/gaia.globalfee.v1beta1.MsgUpdateParams' ,
515
+ ] ) ;
516
+ expect ( globalfeeParams . params . maxTotalBypassMinFeeMsgGasUsage ) . toEqual (
517
+ 12345n ,
518
+ ) ;
519
+ // check that every params field before proposal execution differs from the field after proposal execution
520
+ expect (
521
+ Object . keys ( globalfeeParamsBefore ) . every (
522
+ ( key ) => globalfeeParamsBefore [ key ] !== globalfeeParams [ key ] ,
523
+ ) ,
524
+ ) . toBeTrue ( ) ;
525
+ } ) ;
526
+ } ) ;
527
+
528
+ describe ( 'ALLOW_ONLY: change ccv consumer parameters' , ( ) => {
529
+ let proposalId : number ;
530
+ beforeAll ( async ( ) => {
531
+ proposalId = await subdaoMember1 . submitUpdateParamsConsumerProposal (
532
+ chainManagerAddress ,
533
+ 'Proposal #4' ,
534
+ 'Consumer update params proposal. Will pass' ,
535
+ updateConsumerParamsProposal ( {
536
+ enabled : true ,
537
+ blocksPerDistributionTransmission : 321n ,
538
+ distributionTransmissionChannel : 'channel-23' ,
539
+ providerFeePoolAddrStr : chainManagerAddress ,
540
+ ccvTimeoutPeriod : Duration . fromPartial ( { seconds : 32n } ) ,
541
+ transferTimeoutPeriod : Duration . fromPartial ( { seconds : 23n } ) ,
542
+ consumerRedistributionFraction : '0.33' ,
543
+ historicalEntries : 123n ,
544
+ unbondingPeriod : Duration . fromPartial ( { seconds : 43n } ) ,
545
+ softOptOutThreshold : '0.55' ,
546
+ rewardDenoms : [ 'tia' ] ,
547
+ providerRewardDenoms : [ 'tia' ] ,
548
+ retryDelayPeriod : Duration . fromPartial ( { seconds : 43n } ) ,
549
+ } ) ,
550
+ '1000' ,
551
+ ) ;
552
+
553
+ const timelockedProp = await subdaoMember1 . supportAndExecuteProposal (
554
+ proposalId ,
555
+ ) ;
556
+
557
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
558
+ expect ( timelockedProp . status ) . toEqual ( 'timelocked' ) ;
559
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
560
+ } ) ;
561
+
562
+ test ( 'execute timelocked: success' , async ( ) => {
563
+ const ccvParamsBefore = await ccvQuerier . queryParams ( ) ;
564
+ await waitSeconds ( 10 ) ;
565
+
566
+ await subdaoMember1 . executeTimelockedProposal ( proposalId ) ;
567
+ console . log (
568
+ 'subdao' ,
569
+ subdaoMember1 . dao . contracts . proposals [ 'single' ] . pre_propose . timelock
570
+ . address ,
571
+ ) ;
572
+ const timelockedProp = await subDao . getTimelockedProposal ( proposalId ) ;
573
+ expect ( timelockedProp . id ) . toEqual ( proposalId ) ;
574
+ expect ( timelockedProp . status ) . toEqual ( 'executed' ) ;
575
+ expect ( timelockedProp . msgs ) . toHaveLength ( 1 ) ;
576
+
577
+ const ccvParams = await ccvQuerier . queryParams ( ) ;
578
+ expect ( ccvParams . params . enabled ) . toEqual ( true ) ;
579
+ expect ( ccvParams . params . blocksPerDistributionTransmission ) . toEqual ( 321n ) ;
580
+ expect ( ccvParams . params . distributionTransmissionChannel ) . toEqual (
581
+ 'channel-23' ,
582
+ ) ;
583
+ expect ( ccvParams . params . providerFeePoolAddrStr ) . toEqual (
584
+ chainManagerAddress ,
585
+ ) ;
586
+ expect ( ccvParams . params . ccvTimeoutPeriod ) . toEqual ( {
587
+ nanos : 0 ,
588
+ seconds : 32n ,
589
+ } ) ;
590
+ expect ( ccvParams . params . transferTimeoutPeriod ) . toEqual ( {
591
+ nanos : 0 ,
592
+ seconds : 23n ,
593
+ } ) ;
594
+ expect ( ccvParams . params . consumerRedistributionFraction ) . toEqual ( '0.33' ) ;
595
+ expect ( ccvParams . params . historicalEntries ) . toEqual ( 123n ) ;
596
+ expect ( ccvParams . params . unbondingPeriod ) . toEqual ( {
597
+ nanos : 0 ,
598
+ seconds : 43n ,
599
+ } ) ;
600
+ expect ( ccvParams . params . softOptOutThreshold ) . toEqual ( '0.55' ) ;
601
+ expect ( ccvParams . params . rewardDenoms ) . toEqual ( [ 'tia' ] ) ;
602
+ expect ( ccvParams . params . providerRewardDenoms ) . toEqual ( [ 'tia' ] ) ;
603
+ expect ( ccvParams . params . retryDelayPeriod ) . toEqual ( {
604
+ nanos : 0 ,
605
+ seconds : 43n ,
606
+ } ) ;
607
+ // field 'enabled' is readonly, and should not be changed, always equals true
608
+ delete ccvParamsBefore [ 'enabled' ] ;
609
+ // check that every params field before proposal execution differs from the field after proposal execution
610
+ expect (
611
+ Object . keys ( ccvParamsBefore ) . every (
612
+ ( key ) => ccvParamsBefore [ key ] !== ccvParams [ key ] ,
613
+ ) ,
614
+ ) . toBeTrue ( ) ;
365
615
} ) ;
366
616
} ) ;
367
617
0 commit comments