@@ -18,6 +18,13 @@ contract SubgraphServiceIndexingAgreementIntegrationTest is SubgraphServiceIndex
18
18
uint256 indexerTokensLocked;
19
19
}
20
20
21
+ struct ExpectedTokens {
22
+ uint256 expectedTotalTokensCollected;
23
+ uint256 expectedTokensLocked;
24
+ uint256 expectedProtocolTokensBurnt;
25
+ uint256 expectedIndexerTokensCollected;
26
+ }
27
+
21
28
/*
22
29
* TESTS
23
30
*/
@@ -27,81 +34,164 @@ contract SubgraphServiceIndexingAgreementIntegrationTest is SubgraphServiceIndex
27
34
Seed memory seed ,
28
35
uint256 fuzzyTokensCollected
29
36
) public {
30
- uint256 expectedTotalTokensCollected = bound (fuzzyTokensCollected, 1000 , 1_000_000 );
31
- uint256 expectedTokensLocked = stakeToFeesRatio * expectedTotalTokensCollected;
32
- uint256 expectedProtocolTokensBurnt = expectedTotalTokensCollected.mulPPMRoundUp (
33
- graphPayments.PROTOCOL_PAYMENT_CUT ()
34
- );
35
- uint256 expectedIndexerTokensCollected = expectedTotalTokensCollected - expectedProtocolTokensBurnt;
36
-
37
+ // Setup
38
+ ExpectedTokens memory expectedTokens = _newExptectedTokens (fuzzyTokensCollected);
37
39
Context storage ctx = _newCtx (seed);
38
40
IndexerState memory indexerState = _withIndexer (ctx);
39
- _addTokensToProvision (indexerState, expectedTokensLocked);
41
+ _addTokensToProvision (indexerState, expectedTokens. expectedTokensLocked);
40
42
IRecurringCollector.RecurringCollectionAgreement memory rca = _recurringCollectorHelper.sensibleRCA (
41
43
ctx.ctxInternal.seed.rca
42
44
);
43
- uint256 agreementTokensPerSecond = 1 ;
44
- rca.deadline = uint64 (block .timestamp ); // accept now
45
- rca.endsAt = type (uint64 ).max; // no expiration
46
- rca.maxInitialTokens = 0 ; // no initial payment
47
- rca.maxOngoingTokensPerSecond = type (uint32 ).max; // unlimited tokens per second
48
- rca.minSecondsPerCollection = 1 ; // 1 second between collections
49
- rca.maxSecondsPerCollection = type (uint32 ).max; // no maximum time between collections
50
- rca.serviceProvider = indexerState.addr; // service provider is the indexer
51
- rca.dataService = address (subgraphService); // data service is the subgraph service
52
- rca.metadata = _encodeAcceptIndexingAgreementMetadataV1 (
53
- indexerState.subgraphDeploymentId,
54
- IndexingAgreement.IndexingAgreementTermsV1 ({
55
- tokensPerSecond: agreementTokensPerSecond,
56
- tokensPerEntityPerSecond: 0 // no payment for entities
57
- })
58
- );
45
+ _sharedSetup (ctx, rca, indexerState, expectedTokens);
59
46
60
- _setupPayerWithEscrow (rca.payer, ctx.payer.signerPrivateKey, indexerState.addr, expectedTotalTokensCollected );
47
+ TestState memory beforeCollect = _getState (rca.payer, indexerState.addr);
61
48
49
+ // Collect
62
50
resetPrank (indexerState.addr);
63
- // Set the payments destination to the indexer address
64
- subgraphService.setPaymentsDestination (indexerState.addr);
65
- // Accept the Indexing Agreement
66
- subgraphService.acceptIndexingAgreement (
67
- indexerState.allocationId,
68
- _recurringCollectorHelper.generateSignedRCA (rca, ctx.payer.signerPrivateKey)
51
+ uint256 tokensCollected = subgraphService.collect (
52
+ indexerState.addr,
53
+ IGraphPayments.PaymentTypes.IndexingFee,
54
+ _encodeCollectDataV1 (
55
+ rca.agreementId,
56
+ 1 ,
57
+ keccak256 (abi.encodePacked ("poi " )),
58
+ epochManager.currentEpochBlock (),
59
+ bytes ("" )
60
+ )
69
61
);
70
- // Skip ahead to collection point
71
- skip (expectedTotalTokensCollected / agreementTokensPerSecond);
72
- // vm.assume(block.timestamp < type(uint64).max);
62
+
63
+ TestState memory afterCollect = _getState (rca.payer, indexerState.addr);
64
+ _sharedAssert (beforeCollect, afterCollect, expectedTokens, tokensCollected);
65
+ }
66
+
67
+ function test_SubgraphService_CollectIndexingFee_WhenCanceledByPayer_Integration (
68
+ Seed memory seed ,
69
+ uint256 fuzzyTokensCollected
70
+ ) public {
71
+ // Setup
72
+ ExpectedTokens memory expectedTokens = _newExptectedTokens (fuzzyTokensCollected);
73
+ Context storage ctx = _newCtx (seed);
74
+ IndexerState memory indexerState = _withIndexer (ctx);
75
+ IRecurringCollector.RecurringCollectionAgreement memory rca = _recurringCollectorHelper.sensibleRCA (
76
+ ctx.ctxInternal.seed.rca
77
+ );
78
+ _sharedSetup (ctx, rca, indexerState, expectedTokens);
79
+
80
+ // Cancel the indexing agreement by the payer
81
+ resetPrank (ctx.payer.signer);
82
+ subgraphService.cancelIndexingAgreementByPayer (rca.agreementId);
83
+
73
84
TestState memory beforeCollect = _getState (rca.payer, indexerState.addr);
74
- bytes16 agreementId = rca.agreementId;
85
+
86
+ // Collect
87
+ resetPrank (indexerState.addr);
75
88
uint256 tokensCollected = subgraphService.collect (
76
89
indexerState.addr,
77
90
IGraphPayments.PaymentTypes.IndexingFee,
78
91
_encodeCollectDataV1 (
79
- agreementId,
92
+ rca. agreementId,
80
93
1 ,
81
94
keccak256 (abi.encodePacked ("poi " )),
82
95
epochManager.currentEpochBlock (),
83
96
bytes ("" )
84
97
)
85
98
);
99
+
86
100
TestState memory afterCollect = _getState (rca.payer, indexerState.addr);
87
- uint256 indexerTokensCollected = afterCollect.indexerBalance - beforeCollect.indexerBalance;
88
- uint256 protocolTokensBurnt = tokensCollected - indexerTokensCollected;
101
+ _sharedAssert (beforeCollect, afterCollect, expectedTokens, tokensCollected);
102
+ }
103
+
104
+ /* solhint-enable graph/func-name-mixedcase */
105
+
106
+ function _sharedSetup (
107
+ Context storage _ctx ,
108
+ IRecurringCollector.RecurringCollectionAgreement memory _rca ,
109
+ IndexerState memory _indexerState ,
110
+ ExpectedTokens memory _expectedTokens
111
+ ) internal {
112
+ _addTokensToProvision (_indexerState, _expectedTokens.expectedTokensLocked);
113
+
114
+ IndexingAgreement.IndexingAgreementTermsV1 memory terms = IndexingAgreement.IndexingAgreementTermsV1 ({
115
+ tokensPerSecond: 1 ,
116
+ tokensPerEntityPerSecond: 0 // no payment for entities
117
+ });
118
+ _rca.deadline = uint64 (block .timestamp ); // accept now
119
+ _rca.endsAt = type (uint64 ).max; // no expiration
120
+ _rca.maxInitialTokens = 0 ; // no initial payment
121
+ _rca.maxOngoingTokensPerSecond = type (uint32 ).max; // unlimited tokens per second
122
+ _rca.minSecondsPerCollection = 1 ; // 1 second between collections
123
+ _rca.maxSecondsPerCollection = type (uint32 ).max; // no maximum time between collections
124
+ _rca.serviceProvider = _indexerState.addr; // service provider is the indexer
125
+ _rca.dataService = address (subgraphService); // data service is the subgraph service
126
+ _rca.metadata = _encodeAcceptIndexingAgreementMetadataV1 (_indexerState.subgraphDeploymentId, terms);
127
+
128
+ _setupPayerWithEscrow (
129
+ _rca.payer,
130
+ _ctx.payer.signerPrivateKey,
131
+ _indexerState.addr,
132
+ _expectedTokens.expectedTotalTokensCollected
133
+ );
134
+
135
+ resetPrank (_indexerState.addr);
136
+ // Set the payments destination to the indexer address
137
+ subgraphService.setPaymentsDestination (_indexerState.addr);
138
+
139
+ // Accept the Indexing Agreement
140
+ subgraphService.acceptIndexingAgreement (
141
+ _indexerState.allocationId,
142
+ _recurringCollectorHelper.generateSignedRCA (_rca, _ctx.payer.signerPrivateKey)
143
+ );
144
+
145
+ // Skip ahead to collection point
146
+ skip (_expectedTokens.expectedTotalTokensCollected / terms.tokensPerSecond);
147
+ }
148
+
149
+ function _newExptectedTokens (uint256 _fuzzyTokensCollected ) internal view returns (ExpectedTokens memory ) {
150
+ uint256 expectedTotalTokensCollected = bound (_fuzzyTokensCollected, 1000 , 1_000_000 );
151
+ uint256 expectedTokensLocked = stakeToFeesRatio * expectedTotalTokensCollected;
152
+ uint256 expectedProtocolTokensBurnt = expectedTotalTokensCollected.mulPPMRoundUp (
153
+ graphPayments.PROTOCOL_PAYMENT_CUT ()
154
+ );
155
+ uint256 expectedIndexerTokensCollected = expectedTotalTokensCollected - expectedProtocolTokensBurnt;
156
+ return
157
+ ExpectedTokens ({
158
+ expectedTotalTokensCollected: expectedTotalTokensCollected,
159
+ expectedTokensLocked: expectedTokensLocked,
160
+ expectedProtocolTokensBurnt: expectedProtocolTokensBurnt,
161
+ expectedIndexerTokensCollected: expectedIndexerTokensCollected
162
+ });
163
+ }
164
+
165
+ function _sharedAssert (
166
+ TestState memory _beforeCollect ,
167
+ TestState memory _afterCollect ,
168
+ ExpectedTokens memory _expectedTokens ,
169
+ uint256 _tokensCollected
170
+ ) internal pure {
171
+ uint256 indexerTokensCollected = _afterCollect.indexerBalance - _beforeCollect.indexerBalance;
172
+ assertEq (_expectedTokens.expectedTotalTokensCollected, _tokensCollected, "Total tokens collected should match " );
89
173
assertEq (
90
- afterCollect.escrowBalance ,
91
- beforeCollect.escrowBalance - tokensCollected ,
92
- "Escrow balance should be reduced by the amount collected "
174
+ _expectedTokens.expectedProtocolTokensBurnt ,
175
+ _tokensCollected - indexerTokensCollected ,
176
+ "Protocol tokens burnt should match "
93
177
);
94
- assertEq (tokensCollected, expectedTotalTokensCollected, "Total tokens collected should match " );
95
- assertEq (expectedProtocolTokensBurnt, protocolTokensBurnt, "Protocol tokens burnt should match " );
96
- assertEq (indexerTokensCollected, expectedIndexerTokensCollected, "Indexer tokens collected should match " );
97
178
assertEq (
98
- afterCollect.indexerTokensLocked,
99
- beforeCollect.indexerTokensLocked + expectedTokensLocked,
100
- "Locked tokens should match "
179
+ _expectedTokens.expectedIndexerTokensCollected,
180
+ indexerTokensCollected,
181
+ "Indexer tokens collected should match "
182
+ );
183
+ assertEq (
184
+ _afterCollect.escrowBalance,
185
+ _beforeCollect.escrowBalance - _expectedTokens.expectedTotalTokensCollected,
186
+ "_Escrow balance should be reduced by the amount collected "
101
187
);
102
- }
103
188
104
- /* solhint-enable graph/func-name-mixedcase */
189
+ assertEq (
190
+ _afterCollect.indexerTokensLocked,
191
+ _beforeCollect.indexerTokensLocked + _expectedTokens.expectedTokensLocked,
192
+ "_Locked tokens should match "
193
+ );
194
+ }
105
195
106
196
function _addTokensToProvision (IndexerState memory _indexerState , uint256 _tokensToAddToProvision ) private {
107
197
deal ({ token: address (token), to: _indexerState.addr, give: _tokensToAddToProvision });
0 commit comments