@@ -23,6 +23,7 @@ import {
2323 formatGRT ,
2424 Account ,
2525 advanceToNextEpoch ,
26+ provider ,
2627} from '../lib/testHelpers'
2728
2829const MAX_PPM = 1000000
@@ -50,12 +51,15 @@ describe('Rewards', () => {
5051 let rewardsManagerMock : RewardsManagerMock
5152
5253 // Derive some channel keys for each indexer used to sign attestations
53- const channelKey = deriveChannelKey ( )
54+ const channelKey1 = deriveChannelKey ( )
55+ const channelKey2 = deriveChannelKey ( )
5456
5557 const subgraphDeploymentID1 = randomHexBytes ( )
5658 const subgraphDeploymentID2 = randomHexBytes ( )
5759
58- const allocationID = channelKey . address
60+ const allocationID1 = channelKey1 . address
61+ const allocationID2 = channelKey2 . address
62+
5963 const metadata = HashZero
6064
6165 const ISSUANCE_RATE_PERIODS = 4 // blocks required to issue 5% rewards
@@ -97,6 +101,10 @@ describe('Rewards', () => {
97101
98102 async accrued ( ) {
99103 const nBlocks = await this . elapsedBlocks ( )
104+ return this . accruedByElapsed ( nBlocks )
105+ }
106+
107+ async accruedByElapsed ( nBlocks : BigNumber | number ) {
100108 const n = getRewardsPerSignal (
101109 new BN ( this . totalSupply . toString ( ) ) ,
102110 new BN ( ISSUANCE_RATE_PER_BLOCK . toString ( ) ) . div ( 1e18 ) ,
@@ -395,9 +403,9 @@ describe('Rewards', () => {
395403 indexer1 . address ,
396404 subgraphDeploymentID1 ,
397405 tokensToAllocate ,
398- allocationID ,
406+ allocationID1 ,
399407 metadata ,
400- await channelKey . generateProof ( indexer1 . address ) ,
408+ await channelKey1 . generateProof ( indexer1 . address ) ,
401409 )
402410
403411 // Jump
@@ -433,9 +441,9 @@ describe('Rewards', () => {
433441 indexer1 . address ,
434442 subgraphDeploymentID1 ,
435443 tokensToAllocate ,
436- allocationID ,
444+ allocationID1 ,
437445 metadata ,
438- await channelKey . generateProof ( indexer1 . address ) ,
446+ await channelKey1 . generateProof ( indexer1 . address ) ,
439447 )
440448
441449 // Jump
@@ -477,16 +485,16 @@ describe('Rewards', () => {
477485 indexer1 . address ,
478486 subgraphDeploymentID1 ,
479487 tokensToAllocate ,
480- allocationID ,
488+ allocationID1 ,
481489 metadata ,
482- await channelKey . generateProof ( indexer1 . address ) ,
490+ await channelKey1 . generateProof ( indexer1 . address ) ,
483491 )
484492
485493 // Jump
486494 await advanceBlocks ( ISSUANCE_RATE_PERIODS )
487495
488496 // Rewards
489- const contractRewards = await rewardsManager . getRewards ( allocationID )
497+ const contractRewards = await rewardsManager . getRewards ( allocationID1 )
490498
491499 // We trust using this function in the test because we tested it
492500 // standalone in a previous test
@@ -523,9 +531,9 @@ describe('Rewards', () => {
523531 indexer1 . address ,
524532 subgraphDeploymentID1 ,
525533 tokensToAllocate ,
526- allocationID ,
534+ allocationID1 ,
527535 metadata ,
528- await channelKey . generateProof ( indexer1 . address ) ,
536+ await channelKey1 . generateProof ( indexer1 . address ) ,
529537 )
530538 }
531539
@@ -566,9 +574,9 @@ describe('Rewards', () => {
566574 indexer1 . address ,
567575 subgraphDeploymentID1 ,
568576 tokensToAllocate ,
569- allocationID ,
577+ allocationID1 ,
570578 metadata ,
571- await channelKey . generateProof ( indexer1 . address ) ,
579+ await channelKey1 . generateProof ( indexer1 . address ) ,
572580 )
573581 }
574582
@@ -599,11 +607,11 @@ describe('Rewards', () => {
599607 // Close allocation. At this point rewards should be collected for that indexer
600608 const tx = await staking
601609 . connect ( indexer1 . signer )
602- . closeAllocation ( allocationID , randomHexBytes ( ) )
610+ . closeAllocation ( allocationID1 , randomHexBytes ( ) )
603611 const receipt = await tx . wait ( )
604612 const event = rewardsManager . interface . parseLog ( receipt . logs [ 1 ] ) . args
605613 expect ( event . indexer ) . eq ( indexer1 . address )
606- expect ( event . allocationID ) . eq ( allocationID )
614+ expect ( event . allocationID ) . eq ( allocationID1 )
607615 expect ( event . epoch ) . eq ( await epochManager . currentEpoch ( ) )
608616 expect ( toRound ( event . amount ) ) . eq ( toRound ( expectedIndexingRewards ) )
609617
@@ -658,11 +666,11 @@ describe('Rewards', () => {
658666 // Close allocation. At this point rewards should be collected for that indexer
659667 const tx = await staking
660668 . connect ( indexer1 . signer )
661- . closeAllocation ( allocationID , randomHexBytes ( ) )
669+ . closeAllocation ( allocationID1 , randomHexBytes ( ) )
662670 const receipt = await tx . wait ( )
663671 const event = rewardsManager . interface . parseLog ( receipt . logs [ 1 ] ) . args
664672 expect ( event . indexer ) . eq ( indexer1 . address )
665- expect ( event . allocationID ) . eq ( allocationID )
673+ expect ( event . allocationID ) . eq ( allocationID1 )
666674 expect ( event . epoch ) . eq ( await epochManager . currentEpoch ( ) )
667675 expect ( toRound ( event . amount ) ) . eq ( toRound ( expectedIndexingRewards ) )
668676
@@ -710,7 +718,7 @@ describe('Rewards', () => {
710718 const beforeIndexer1Stake = await staking . getIndexerStakedTokens ( indexer1 . address )
711719
712720 // 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 ( ) )
714722
715723 // After state
716724 const afterTokenSupply = await grt . totalSupply ( )
@@ -756,10 +764,10 @@ describe('Rewards', () => {
756764 await advanceToNextEpoch ( epochManager )
757765
758766 // 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 ( ) )
760768 await expect ( tx )
761769 . emit ( rewardsManager , 'RewardsDenied' )
762- . withArgs ( indexer1 . address , allocationID , await epochManager . currentEpoch ( ) )
770+ . withArgs ( indexer1 . address , allocationID1 , await epochManager . currentEpoch ( ) )
763771 } )
764772 } )
765773 } )
@@ -791,9 +799,9 @@ describe('Rewards', () => {
791799 indexer1 . address ,
792800 subgraphDeploymentID1 ,
793801 tokensToAllocate ,
794- allocationID ,
802+ allocationID1 ,
795803 metadata ,
796- await channelKey . generateProof ( indexer1 . address ) ,
804+ await channelKey1 . generateProof ( indexer1 . address ) ,
797805 )
798806
799807 // Jump
@@ -804,7 +812,107 @@ describe('Rewards', () => {
804812 await curation . connect ( curator1 . signer ) . burn ( subgraphDeploymentID1 , curatorShares , 0 )
805813
806814 // 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 )
808916 } )
809917 } )
810918} )
0 commit comments