1
1
const { assert } = require ( '../../helpers/assert' )
2
- const { assertEvent } = require ( '@aragon/contract-helpers-test/src/asserts' )
3
2
const { e9, e18, e27 } = require ( '../../helpers/utils' )
4
3
5
4
const {
@@ -13,7 +12,8 @@ const {
13
12
EXTRA_DATA_FORMAT_LIST ,
14
13
SLOTS_PER_FRAME ,
15
14
SECONDS_PER_SLOT ,
16
- GENESIS_TIME
15
+ GENESIS_TIME ,
16
+ ZERO_HASH
17
17
} = require ( './accounting-oracle-deploy.test' )
18
18
19
19
contract ( 'AccountingOracle' , ( [ admin , account1 , account2 , member1 , member2 , stranger ] ) => {
@@ -94,7 +94,20 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
94
94
await consensus . advanceTimeToNextFrameStart ( )
95
95
await consensus . submitReport ( newReportFields . refSlot , reportHash , CONSENSUS_VERSION , { from : member1 } )
96
96
97
- return newReportItems
97
+ return {
98
+ newReportFields,
99
+ newReportItems,
100
+ reportHash
101
+ }
102
+ }
103
+
104
+ async function prepareNextReportInNextFrame ( newReportFields ) {
105
+ const { refSlot } = await consensus . getCurrentFrame ( )
106
+ const next = await prepareNextReport ( {
107
+ ...newReportFields ,
108
+ refSlot : + refSlot + SLOTS_PER_FRAME
109
+ } )
110
+ return next
98
111
}
99
112
100
113
context ( 'deploying' , ( ) => {
@@ -140,7 +153,7 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
140
153
await consensus . setTime ( deadline )
141
154
142
155
const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
143
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : reportFields . refSlot } } )
156
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : reportFields . refSlot } )
144
157
} )
145
158
} )
146
159
@@ -165,22 +178,9 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
165
178
166
179
it ( 'should should allow calling if correct ref slot' , async ( ) => {
167
180
await consensus . setTime ( deadline )
168
- const { refSlot } = await consensus . getCurrentFrame ( )
169
-
170
- const nextRefSlot = + refSlot + SLOTS_PER_FRAME
171
-
172
- const newReportFields = {
173
- ...reportFields ,
174
- refSlot : nextRefSlot
175
- }
176
- const reportItems = getReportDataItems ( newReportFields )
177
-
178
- const reportHash = calcReportDataHash ( reportItems )
179
- await consensus . advanceTimeToNextFrameStart ( )
180
- await consensus . submitReport ( nextRefSlot , reportHash , CONSENSUS_VERSION , { from : member1 } )
181
-
182
- const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
183
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : newReportFields . refSlot } } )
181
+ const { newReportFields, newReportItems } = await prepareNextReportInNextFrame ( { ...reportFields } )
182
+ const tx = await oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } )
183
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : newReportFields . refSlot } )
184
184
} )
185
185
} )
186
186
@@ -216,7 +216,7 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
216
216
const { refSlot } = await consensus . getCurrentFrame ( )
217
217
218
218
const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
219
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : reportFields . refSlot } } )
219
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : reportFields . refSlot } )
220
220
221
221
const newConsensusVersion = CONSENSUS_VERSION + 1
222
222
const nextRefSlot = + refSlot + SLOTS_PER_FRAME
@@ -233,46 +233,48 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
233
233
await consensus . submitReport ( newReportFields . refSlot , newReportHash , newConsensusVersion , { from : member1 } )
234
234
235
235
const txNewVersion = await oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } )
236
- assertEvent ( txNewVersion , 'ProcessingStarted' , { expectedArgs : { refSlot : newReportFields . refSlot } } )
236
+ assert . emits ( txNewVersion , 'ProcessingStarted' , { refSlot : newReportFields . refSlot } )
237
237
} )
238
238
} )
239
239
240
240
context ( 'enforces module ids sorting order' , ( ) => {
241
241
beforeEach ( deploy )
242
242
243
- it ( 'should revert if incorrect stakingModuleIdsWithNewlyExitedValidators order' , async ( ) => {
244
- const { refSlot } = await consensus . getCurrentFrame ( )
245
-
246
- const nextRefSlot = + refSlot + SLOTS_PER_FRAME
247
- const newReportFields = {
243
+ it ( 'should revert if incorrect stakingModuleIdsWithNewlyExitedValidators order (when next number in list is less than previous)' , async ( ) => {
244
+ const { newReportItems } = await prepareNextReportInNextFrame ( {
248
245
...reportFields ,
249
- refSlot : nextRefSlot ,
250
246
stakingModuleIdsWithNewlyExitedValidators : [ 2 , 1 ] ,
251
247
numExitedValidatorsByStakingModule : [ 3 , 4 ]
252
- }
253
- const newReportItems = await prepareNextReport ( newReportFields )
248
+ } )
254
249
255
250
await assert . reverts (
256
251
oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } ) ,
257
252
'InvalidExitedValidatorsData()'
258
253
)
259
254
} )
260
255
261
- it ( 'should should allow calling if correct extra data list moduleId' , async ( ) => {
262
- const { refSlot } = await consensus . getCurrentFrame ( )
256
+ it ( 'should revert if incorrect stakingModuleIdsWithNewlyExitedValidators order (when next number in list is less than previous)' , async ( ) => {
257
+ const { newReportItems } = await prepareNextReportInNextFrame ( {
258
+ ...reportFields ,
259
+ stakingModuleIdsWithNewlyExitedValidators : [ 1 , 1 ] ,
260
+ numExitedValidatorsByStakingModule : [ 3 , 4 ]
261
+ } )
263
262
264
- const nextRefSlot = + refSlot + SLOTS_PER_FRAME
263
+ await assert . reverts (
264
+ oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } ) ,
265
+ 'InvalidExitedValidatorsData()'
266
+ )
267
+ } )
265
268
266
- const newReportFields = {
269
+ it ( 'should should allow calling if correct extra data list moduleId' , async ( ) => {
270
+ const { newReportFields, newReportItems } = await prepareNextReportInNextFrame ( {
267
271
...reportFields ,
268
- refSlot : nextRefSlot ,
269
272
stakingModuleIdsWithNewlyExitedValidators : [ 1 , 2 ] ,
270
273
numExitedValidatorsByStakingModule : [ 3 , 4 ]
271
- }
272
- const newReportItems = await prepareNextReport ( newReportFields )
274
+ } )
273
275
274
276
const tx = await oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } )
275
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : newReportFields . refSlot } } )
277
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : newReportFields . refSlot } )
276
278
} )
277
279
} )
278
280
@@ -294,7 +296,7 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
294
296
295
297
it ( 'submits if data successfully pass hash validation' , async ( ) => {
296
298
const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
297
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : reportFields . refSlot } } )
299
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : reportFields . refSlot } )
298
300
} )
299
301
} )
300
302
@@ -330,14 +332,79 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
330
332
331
333
await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
332
334
} )
335
+
336
+ it ( 'reverts with InvalidExitedValidatorsData if counts of stakingModuleIds and numExitedValidatorsByStakingModule does not match' , async ( ) => {
337
+ const { newReportItems } = await prepareNextReportInNextFrame ( {
338
+ ...reportFields ,
339
+ stakingModuleIdsWithNewlyExitedValidators : [ 1 , 2 ] ,
340
+ numExitedValidatorsByStakingModule : [ 3 ]
341
+ } )
342
+ await assert . reverts (
343
+ oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } ) ,
344
+ 'InvalidExitedValidatorsData()'
345
+ )
346
+ } )
347
+
348
+ it ( 'reverts with InvalidExitedValidatorsData if any record for number of exited validators equals 0' , async ( ) => {
349
+ const { newReportItems } = await prepareNextReportInNextFrame ( {
350
+ ...reportFields ,
351
+ stakingModuleIdsWithNewlyExitedValidators : [ 1 , 2 ] ,
352
+ numExitedValidatorsByStakingModule : [ 3 , 0 ]
353
+ } )
354
+ await assert . reverts (
355
+ oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } ) ,
356
+ 'InvalidExitedValidatorsData()'
357
+ )
358
+ } )
359
+
360
+ it ( 'reverts with NumExitedValidatorsCannotDecrease if total count of exited validators less then previous exited number' , async ( ) => {
361
+ const totalExitedValidators = reportFields . numExitedValidatorsByStakingModule . reduce (
362
+ ( sum , curr ) => sum + curr ,
363
+ 0
364
+ )
365
+ await mockStakingRouter . setExitedKeysCountAcrossAllModules ( totalExitedValidators + 1 )
366
+ await assert . reverts (
367
+ oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } ) ,
368
+ 'NumExitedValidatorsCannotDecrease()'
369
+ )
370
+ } )
371
+
372
+ it ( 'does not reverts with NumExitedValidatorsCannotDecrease if total count of exited validators equals to previous exited number' , async ( ) => {
373
+ const totalExitedValidators = reportFields . numExitedValidatorsByStakingModule . reduce (
374
+ ( sum , curr ) => sum + curr ,
375
+ 0
376
+ )
377
+ await mockStakingRouter . setExitedKeysCountAcrossAllModules ( totalExitedValidators )
378
+ await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
379
+ } )
380
+
381
+ it ( 'reverts with ExitedValidatorsLimitExceeded if exited validators rate limit will be reached' , async ( ) => {
382
+ // Really simple test here for now
383
+ // TODO: Come up with more tests for better coverage of edge-case scenarios that can be accrued
384
+ // during calculation `exitedValidatorsPerDay` rate in AccountingOracle:612
385
+ const totalExitedValidators = reportFields . numExitedValidatorsByStakingModule . reduce (
386
+ ( sum , curr ) => sum + curr ,
387
+ 0
388
+ )
389
+ const exitingRateLimit = totalExitedValidators - 1
390
+ await oracleReportSanityChecker . setChurnValidatorsPerDayLimit ( exitingRateLimit )
391
+ assert . equals (
392
+ ( await oracleReportSanityChecker . getOracleReportLimits ( ) ) . churnValidatorsPerDayLimit ,
393
+ exitingRateLimit
394
+ )
395
+ await assert . reverts (
396
+ oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } ) ,
397
+ `ExitedValidatorsLimitExceeded(${ exitingRateLimit } , ${ totalExitedValidators } )`
398
+ )
399
+ } )
333
400
} )
334
401
335
402
context ( 'delivers the data to corresponded contracts' , ( ) => {
336
403
it ( 'should call handleOracleReport on Lido' , async ( ) => {
337
404
assert . equals ( ( await mockLido . getLastCall_handleOracleReport ( ) ) . callCount , 0 )
338
405
await consensus . setTime ( deadline )
339
406
const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
340
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : reportFields . refSlot } } )
407
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : reportFields . refSlot } )
341
408
342
409
const lastOracleReportToLido = await mockLido . getLastCall_handleOracleReport ( )
343
410
@@ -357,11 +424,11 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
357
424
assert . equals ( lastOracleReportToLido . finalizationShareRate , reportFields . finalizationShareRate )
358
425
} )
359
426
360
- it ( 'should call updateExitedValidatorsCountByStakingModule on stakingRouter ' , async ( ) => {
427
+ it ( 'should call updateExitedValidatorsCountByStakingModule on StakingRouter ' , async ( ) => {
361
428
assert . equals ( ( await mockStakingRouter . lastCall_updateExitedKeysByModule ( ) ) . callCount , 0 )
362
429
await consensus . setTime ( deadline )
363
430
const tx = await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
364
- assertEvent ( tx , 'ProcessingStarted' , { expectedArgs : { refSlot : reportFields . refSlot } } )
431
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : reportFields . refSlot } )
365
432
366
433
const lastOracleReportToStakingRouter = await mockStakingRouter . lastCall_updateExitedKeysByModule ( )
367
434
@@ -370,6 +437,18 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
370
437
assert . equals ( lastOracleReportToStakingRouter . exitedKeysCounts , reportFields . numExitedValidatorsByStakingModule )
371
438
} )
372
439
440
+ it ( 'does not calling StakingRouter.updateExitedKeysByModule if lists of exited validators is empty' , async ( ) => {
441
+ const { newReportItems, newReportFields } = await prepareNextReportInNextFrame ( {
442
+ ...reportFields ,
443
+ stakingModuleIdsWithNewlyExitedValidators : [ ] ,
444
+ numExitedValidatorsByStakingModule : [ ]
445
+ } )
446
+ const tx = await oracle . submitReportData ( newReportItems , oracleVersion , { from : member1 } )
447
+ assert . emits ( tx , 'ProcessingStarted' , { refSlot : newReportFields . refSlot } )
448
+ const lastOracleReportToStakingRouter = await mockStakingRouter . lastCall_updateExitedKeysByModule ( )
449
+ assert . equals ( lastOracleReportToStakingRouter . callCount , 0 )
450
+ } )
451
+
373
452
it ( 'should call handleConsensusLayerReport on legacyOracle' , async ( ) => {
374
453
await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
375
454
const lastCall = await mockLegacyOracle . lastCall__handleConsensusLayerReport ( )
@@ -413,5 +492,28 @@ contract('AccountingOracle', ([admin, account1, account2, member1, member2, stra
413
492
)
414
493
} )
415
494
} )
495
+
496
+ context ( 'ExtraDataProcessingState' , ( ) => {
497
+ it ( 'should be empty from start' , async ( ) => {
498
+ const data = await oracle . getExtraDataProcessingState ( )
499
+ assert . equals ( data . refSlot , '0' )
500
+ assert . equals ( data . dataFormat , '0' )
501
+ assert . equals ( data . itemsCount , '0' )
502
+ assert . equals ( data . itemsProcessed , '0' )
503
+ assert . equals ( data . lastSortingKey , '0' )
504
+ assert . equals ( data . dataHash , ZERO_HASH )
505
+ } )
506
+
507
+ it ( 'should be filled with report data after submitting' , async ( ) => {
508
+ await oracle . submitReportData ( reportItems , oracleVersion , { from : member1 } )
509
+ const data = await oracle . getExtraDataProcessingState ( )
510
+ assert . equals ( data . refSlot , reportFields . refSlot )
511
+ assert . equals ( data . dataFormat , reportFields . extraDataFormat )
512
+ assert . equals ( data . itemsCount , reportFields . extraDataItemsCount )
513
+ assert . equals ( data . itemsProcessed , '0' )
514
+ assert . equals ( data . lastSortingKey , '0' )
515
+ assert . equals ( data . dataHash , reportFields . extraDataHash )
516
+ } )
517
+ } )
416
518
} )
417
519
} )
0 commit comments