@@ -23,6 +23,7 @@ import {
23
23
formatGRT ,
24
24
Account ,
25
25
advanceToNextEpoch ,
26
+ provider ,
26
27
} from '../lib/testHelpers'
27
28
28
29
const MAX_PPM = 1000000
@@ -50,12 +51,15 @@ describe('Rewards', () => {
50
51
let rewardsManagerMock : RewardsManagerMock
51
52
52
53
// Derive some channel keys for each indexer used to sign attestations
53
- const channelKey = deriveChannelKey ( )
54
+ const channelKey1 = deriveChannelKey ( )
55
+ const channelKey2 = deriveChannelKey ( )
54
56
55
57
const subgraphDeploymentID1 = randomHexBytes ( )
56
58
const subgraphDeploymentID2 = randomHexBytes ( )
57
59
58
- const allocationID = channelKey . address
60
+ const allocationID1 = channelKey1 . address
61
+ const allocationID2 = channelKey2 . address
62
+
59
63
const metadata = HashZero
60
64
61
65
const ISSUANCE_RATE_PERIODS = 4 // blocks required to issue 5% rewards
@@ -97,6 +101,10 @@ describe('Rewards', () => {
97
101
98
102
async accrued ( ) {
99
103
const nBlocks = await this . elapsedBlocks ( )
104
+ return this . accruedByElapsed ( nBlocks )
105
+ }
106
+
107
+ async accruedByElapsed ( nBlocks : BigNumber | number ) {
100
108
const n = getRewardsPerSignal (
101
109
new BN ( this . totalSupply . toString ( ) ) ,
102
110
new BN ( ISSUANCE_RATE_PER_BLOCK . toString ( ) ) . div ( 1e18 ) ,
@@ -395,9 +403,9 @@ describe('Rewards', () => {
395
403
indexer1 . address ,
396
404
subgraphDeploymentID1 ,
397
405
tokensToAllocate ,
398
- allocationID ,
406
+ allocationID1 ,
399
407
metadata ,
400
- await channelKey . generateProof ( indexer1 . address ) ,
408
+ await channelKey1 . generateProof ( indexer1 . address ) ,
401
409
)
402
410
403
411
// Jump
@@ -433,9 +441,9 @@ describe('Rewards', () => {
433
441
indexer1 . address ,
434
442
subgraphDeploymentID1 ,
435
443
tokensToAllocate ,
436
- allocationID ,
444
+ allocationID1 ,
437
445
metadata ,
438
- await channelKey . generateProof ( indexer1 . address ) ,
446
+ await channelKey1 . generateProof ( indexer1 . address ) ,
439
447
)
440
448
441
449
// Jump
@@ -477,16 +485,16 @@ describe('Rewards', () => {
477
485
indexer1 . address ,
478
486
subgraphDeploymentID1 ,
479
487
tokensToAllocate ,
480
- allocationID ,
488
+ allocationID1 ,
481
489
metadata ,
482
- await channelKey . generateProof ( indexer1 . address ) ,
490
+ await channelKey1 . generateProof ( indexer1 . address ) ,
483
491
)
484
492
485
493
// Jump
486
494
await advanceBlocks ( ISSUANCE_RATE_PERIODS )
487
495
488
496
// Rewards
489
- const contractRewards = await rewardsManager . getRewards ( allocationID )
497
+ const contractRewards = await rewardsManager . getRewards ( allocationID1 )
490
498
491
499
// We trust using this function in the test because we tested it
492
500
// standalone in a previous test
@@ -523,9 +531,9 @@ describe('Rewards', () => {
523
531
indexer1 . address ,
524
532
subgraphDeploymentID1 ,
525
533
tokensToAllocate ,
526
- allocationID ,
534
+ allocationID1 ,
527
535
metadata ,
528
- await channelKey . generateProof ( indexer1 . address ) ,
536
+ await channelKey1 . generateProof ( indexer1 . address ) ,
529
537
)
530
538
}
531
539
@@ -566,9 +574,9 @@ describe('Rewards', () => {
566
574
indexer1 . address ,
567
575
subgraphDeploymentID1 ,
568
576
tokensToAllocate ,
569
- allocationID ,
577
+ allocationID1 ,
570
578
metadata ,
571
- await channelKey . generateProof ( indexer1 . address ) ,
579
+ await channelKey1 . generateProof ( indexer1 . address ) ,
572
580
)
573
581
}
574
582
@@ -599,11 +607,11 @@ describe('Rewards', () => {
599
607
// Close allocation. At this point rewards should be collected for that indexer
600
608
const tx = await staking
601
609
. connect ( indexer1 . signer )
602
- . closeAllocation ( allocationID , randomHexBytes ( ) )
610
+ . closeAllocation ( allocationID1 , randomHexBytes ( ) )
603
611
const receipt = await tx . wait ( )
604
612
const event = rewardsManager . interface . parseLog ( receipt . logs [ 1 ] ) . args
605
613
expect ( event . indexer ) . eq ( indexer1 . address )
606
- expect ( event . allocationID ) . eq ( allocationID )
614
+ expect ( event . allocationID ) . eq ( allocationID1 )
607
615
expect ( event . epoch ) . eq ( await epochManager . currentEpoch ( ) )
608
616
expect ( toRound ( event . amount ) ) . eq ( toRound ( expectedIndexingRewards ) )
609
617
@@ -658,11 +666,11 @@ describe('Rewards', () => {
658
666
// Close allocation. At this point rewards should be collected for that indexer
659
667
const tx = await staking
660
668
. connect ( indexer1 . signer )
661
- . closeAllocation ( allocationID , randomHexBytes ( ) )
669
+ . closeAllocation ( allocationID1 , randomHexBytes ( ) )
662
670
const receipt = await tx . wait ( )
663
671
const event = rewardsManager . interface . parseLog ( receipt . logs [ 1 ] ) . args
664
672
expect ( event . indexer ) . eq ( indexer1 . address )
665
- expect ( event . allocationID ) . eq ( allocationID )
673
+ expect ( event . allocationID ) . eq ( allocationID1 )
666
674
expect ( event . epoch ) . eq ( await epochManager . currentEpoch ( ) )
667
675
expect ( toRound ( event . amount ) ) . eq ( toRound ( expectedIndexingRewards ) )
668
676
@@ -710,7 +718,7 @@ describe('Rewards', () => {
710
718
const beforeIndexer1Stake = await staking . getIndexerStakedTokens ( indexer1 . address )
711
719
712
720
// Close allocation. At this point rewards should be collected for that indexer
713
- await staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID , randomHexBytes ( ) )
721
+ await staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID1 , randomHexBytes ( ) )
714
722
715
723
// After state
716
724
const afterTokenSupply = await grt . totalSupply ( )
@@ -756,10 +764,10 @@ describe('Rewards', () => {
756
764
await advanceToNextEpoch ( epochManager )
757
765
758
766
// Close allocation. At this point rewards should be collected for that indexer
759
- const tx = staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID , randomHexBytes ( ) )
767
+ const tx = staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID1 , randomHexBytes ( ) )
760
768
await expect ( tx )
761
769
. emit ( rewardsManager , 'RewardsDenied' )
762
- . withArgs ( indexer1 . address , allocationID , await epochManager . currentEpoch ( ) )
770
+ . withArgs ( indexer1 . address , allocationID1 , await epochManager . currentEpoch ( ) )
763
771
} )
764
772
} )
765
773
} )
@@ -791,9 +799,9 @@ describe('Rewards', () => {
791
799
indexer1 . address ,
792
800
subgraphDeploymentID1 ,
793
801
tokensToAllocate ,
794
- allocationID ,
802
+ allocationID1 ,
795
803
metadata ,
796
- await channelKey . generateProof ( indexer1 . address ) ,
804
+ await channelKey1 . generateProof ( indexer1 . address ) ,
797
805
)
798
806
799
807
// Jump
@@ -804,7 +812,107 @@ describe('Rewards', () => {
804
812
await curation . connect ( curator1 . signer ) . burn ( subgraphDeploymentID1 , curatorShares , 0 )
805
813
806
814
// Close allocation. At this point rewards should be collected for that indexer
807
- await staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID , randomHexBytes ( ) )
815
+ await staking . connect ( indexer1 . signer ) . closeAllocation ( allocationID1 , randomHexBytes ( ) )
816
+ } )
817
+ } )
818
+
819
+ describe ( 'multiple allocations' , function ( ) {
820
+ it ( 'two allocations in the same block with a GRT burn in the middle should succeed' , async function ( ) {
821
+ // If rewards are not monotonically increasing, this can trigger
822
+ // a subtraction overflow error as seen in mainnet tx:
823
+ // 0xb6bf7bbc446720a7409c482d714aebac239dd62e671c3c94f7e93dd3a61835ab
824
+ await advanceToNextEpoch ( epochManager )
825
+
826
+ // Setup
827
+ await epochManager . setEpochLength ( 10 )
828
+
829
+ // Update total signalled
830
+ const signalled1 = toGRT ( '1500' )
831
+ await curation . connect ( curator1 . signer ) . mint ( subgraphDeploymentID1 , signalled1 , 0 )
832
+
833
+ // Stake
834
+ const tokensToStake = toGRT ( '12500' )
835
+ await staking . connect ( indexer1 . signer ) . stake ( tokensToStake )
836
+
837
+ // Allocate simultaneously, burning in the middle
838
+ const tokensToAlloc = toGRT ( '5000' )
839
+ await provider ( ) . send ( 'evm_setAutomine' , [ false ] )
840
+ const tx1 = await staking
841
+ . connect ( indexer1 . signer )
842
+ . allocateFrom (
843
+ indexer1 . address ,
844
+ subgraphDeploymentID1 ,
845
+ tokensToAlloc ,
846
+ allocationID1 ,
847
+ metadata ,
848
+ await channelKey1 . generateProof ( indexer1 . address ) ,
849
+ )
850
+ const tx2 = await grt . connect ( indexer1 . signer ) . burn ( toGRT ( 1 ) )
851
+ const tx3 = await staking
852
+ . connect ( indexer1 . signer )
853
+ . allocateFrom (
854
+ indexer1 . address ,
855
+ subgraphDeploymentID1 ,
856
+ tokensToAlloc ,
857
+ allocationID2 ,
858
+ metadata ,
859
+ await channelKey2 . generateProof ( indexer1 . address ) ,
860
+ )
861
+
862
+ await provider ( ) . send ( 'evm_mine' , [ ] )
863
+ await provider ( ) . send ( 'evm_setAutomine' , [ true ] )
864
+
865
+ await expect ( tx1 ) . emit ( staking , 'AllocationCreated' )
866
+ await expect ( tx2 ) . emit ( grt , 'Transfer' )
867
+ await expect ( tx3 ) . emit ( staking , 'AllocationCreated' )
868
+ } )
869
+ it ( 'two simultanous-similar allocations should get same amount of rewards' , async function ( ) {
870
+ await advanceToNextEpoch ( epochManager )
871
+
872
+ // Setup
873
+ await epochManager . setEpochLength ( 10 )
874
+
875
+ // Update total signalled
876
+ const signalled1 = toGRT ( '1500' )
877
+ await curation . connect ( curator1 . signer ) . mint ( subgraphDeploymentID1 , signalled1 , 0 )
878
+
879
+ // Stake
880
+ const tokensToStake = toGRT ( '12500' )
881
+ await staking . connect ( indexer1 . signer ) . stake ( tokensToStake )
882
+
883
+ // Allocate simultaneously
884
+ const tokensToAlloc = toGRT ( '5000' )
885
+ const tx1 = await staking . populateTransaction . allocateFrom (
886
+ indexer1 . address ,
887
+ subgraphDeploymentID1 ,
888
+ tokensToAlloc ,
889
+ allocationID1 ,
890
+ metadata ,
891
+ await channelKey1 . generateProof ( indexer1 . address ) ,
892
+ )
893
+ const tx2 = await staking . populateTransaction . allocateFrom (
894
+ indexer1 . address ,
895
+ subgraphDeploymentID1 ,
896
+ tokensToAlloc ,
897
+ allocationID2 ,
898
+ metadata ,
899
+ await channelKey2 . generateProof ( indexer1 . address ) ,
900
+ )
901
+ await staking . connect ( indexer1 . signer ) . multicall ( [ tx1 . data , tx2 . data ] )
902
+
903
+ // Jump
904
+ await advanceToNextEpoch ( epochManager )
905
+
906
+ // Close allocations simultaneously
907
+ const tx3 = await staking . populateTransaction . closeAllocation ( allocationID1 , randomHexBytes ( ) )
908
+ const tx4 = await staking . populateTransaction . closeAllocation ( allocationID2 , randomHexBytes ( ) )
909
+ const tx5 = await staking . connect ( indexer1 . signer ) . multicall ( [ tx3 . data , tx4 . data ] )
910
+
911
+ // Both allocations should receive the same amount of rewards
912
+ const receipt = await tx5 . wait ( )
913
+ const event1 = rewardsManager . interface . parseLog ( receipt . logs [ 1 ] ) . args
914
+ const event2 = rewardsManager . interface . parseLog ( receipt . logs [ 5 ] ) . args
915
+ expect ( event1 . amount ) . eq ( event2 . amount )
808
916
} )
809
917
} )
810
918
} )
0 commit comments