Skip to content

Commit 4a3cf2c

Browse files
committed
feat: require poi metadata when collecting rewards
Signed-off-by: Tomás Migone <[email protected]>
1 parent 792302a commit 4a3cf2c

File tree

7 files changed

+44
-18
lines changed

7 files changed

+44
-18
lines changed

packages/subgraph-service/contracts/DisputeManager.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { IHorizonStaking } from "@graphprotocol/horizon/contracts/interfaces/IHo
66
import { IDisputeManager } from "./interfaces/IDisputeManager.sol";
77
import { ISubgraphService } from "./interfaces/ISubgraphService.sol";
88

9-
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
109
import { TokenUtils } from "@graphprotocol/contracts/contracts/utils/TokenUtils.sol";
1110
import { PPMMath } from "@graphprotocol/horizon/contracts/libraries/PPMMath.sol";
1211
import { MathUtils } from "@graphprotocol/horizon/contracts/libraries/MathUtils.sol";

packages/subgraph-service/contracts/SubgraphService.sol

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ contract SubgraphService is
249249
*
250250
* @param indexer The address of the indexer
251251
* @param paymentType The type of payment to collect as defined in {IGraphPayments}
252+
* @param data Encoded data:
253+
* - For query fees:
254+
* - IGraphTallyCollector.SignedRAV `signedRav`: The signed RAV
255+
* - For indexing rewards:
256+
* - address `allocationId`: The id of the allocation
257+
* - bytes32 `poi`: The POI being presented
258+
* - bytes `poiMetadata`: The metadata associated with the POI. See {AllocationManager-_collectIndexingRewards} for more details.
252259
*/
253260
/// @inheritdoc IDataService
254261
function collect(
@@ -277,12 +284,12 @@ contract SubgraphService is
277284
);
278285
paymentCollected = _collectQueryFees(signedRav, tokensToCollect);
279286
} else if (paymentType == IGraphPayments.PaymentTypes.IndexingRewards) {
280-
(address allocationId, bytes32 poi) = abi.decode(data, (address, bytes32));
287+
(address allocationId, bytes32 poi, bytes memory poiMetadata) = abi.decode(data, (address, bytes32, bytes));
281288
require(
282289
_allocations.get(allocationId).indexer == indexer,
283290
SubgraphServiceAllocationNotAuthorized(indexer, allocationId)
284291
);
285-
paymentCollected = _collectIndexingRewards(allocationId, poi, _delegationRatio);
292+
paymentCollected = _collectIndexingRewards(allocationId, poi, poiMetadata, _delegationRatio);
286293
} else {
287294
revert SubgraphServiceInvalidPaymentType(paymentType);
288295
}
@@ -477,13 +484,13 @@ contract SubgraphService is
477484
* Emits a {QueryFeesCollected} event.
478485
*
479486
* @param _signedRav Signed RAV
480-
* @param tokensToCollect The amount of tokens to collect. Allows partially collecting a RAV. If 0, the entire RAV will
487+
* @param _tokensToCollect The amount of tokens to collect. Allows partially collecting a RAV. If 0, the entire RAV will
481488
* be collected.
482489
* @return The amount of fees collected
483490
*/
484491
function _collectQueryFees(
485492
IGraphTallyCollector.SignedRAV memory _signedRav,
486-
uint256 tokensToCollect
493+
uint256 _tokensToCollect
487494
) private returns (uint256) {
488495
address indexer = _signedRav.rav.serviceProvider;
489496

@@ -510,7 +517,7 @@ contract SubgraphService is
510517
uint256 tokensCollected = _graphTallyCollector().collect(
511518
IGraphPayments.PaymentTypes.QueryFee,
512519
abi.encode(_signedRav, curationCut),
513-
tokensToCollect
520+
_tokensToCollect
514521
);
515522

516523
uint256 balanceAfter = _graphToken().balanceOf(address(this));

packages/subgraph-service/contracts/utilities/AllocationManager.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca
6262
* @param tokensDelegationRewards The amount of tokens collected for delegators
6363
* @param poi The POI presented
6464
* @param currentEpoch The current epoch
65+
* @param poiMetadata The metadata associated with the POI
6566
*/
6667
event IndexingRewardsCollected(
6768
address indexed indexer,
@@ -71,6 +72,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca
7172
uint256 tokensIndexerRewards,
7273
uint256 tokensDelegationRewards,
7374
bytes32 poi,
75+
bytes poiMetadata,
7476
uint256 currentEpoch
7577
);
7678

@@ -261,12 +263,14 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca
261263
*
262264
* @param _allocationId The id of the allocation to collect rewards for
263265
* @param _poi The POI being presented
266+
* @param _poiMetadata The metadata associated with the POI. The data and encoding format is for off-chain components to define, this function will only emit the value in an event as-is.
264267
* @param _delegationRatio The delegation ratio to consider when locking tokens
265268
* @return The amount of tokens collected
266269
*/
267270
function _collectIndexingRewards(
268271
address _allocationId,
269272
bytes32 _poi,
273+
bytes memory _poiMetadata,
270274
uint32 _delegationRatio
271275
) internal returns (uint256) {
272276
Allocation.State memory allocation = _allocations.get(_allocationId);
@@ -332,6 +336,7 @@ abstract contract AllocationManager is EIP712Upgradeable, GraphDirectory, Alloca
332336
tokensIndexerRewards,
333337
tokensDelegationRewards,
334338
_poi,
339+
_poiMetadata,
335340
currentEpoch
336341
);
337342

packages/subgraph-service/test/subgraphService/SubgraphService.t.sol

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
180180

181181
struct IndexingRewardsData {
182182
bytes32 poi;
183+
bytes poiMetadata;
183184
uint256 tokensIndexerRewards;
184185
uint256 tokensDelegationRewards;
185186
}
@@ -326,7 +327,10 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
326327
function _handleIndexingRewardsCollection(
327328
bytes memory _data
328329
) private returns (uint256 paymentCollected, address allocationId, IndexingRewardsData memory indexingRewardsData) {
329-
(allocationId, indexingRewardsData.poi) = abi.decode(_data, (address, bytes32));
330+
(allocationId, indexingRewardsData.poi, indexingRewardsData.poiMetadata) = abi.decode(
331+
_data,
332+
(address, bytes32, bytes)
333+
);
330334
Allocation.State memory allocation = subgraphService.getAllocation(allocationId);
331335

332336
// Calculate accumulated tokens, this depends on the rewards manager which we have mocked
@@ -360,6 +364,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
360364
indexingRewardsData.tokensIndexerRewards,
361365
indexingRewardsData.tokensDelegationRewards,
362366
indexingRewardsData.poi,
367+
indexingRewardsData.poiMetadata,
363368
epochManager.currentEpoch()
364369
);
365370

@@ -514,4 +519,14 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
514519
(uint256 tokens, uint256 createdAt, uint256 releasableAt, bytes32 nextClaim) = subgraphService.claims(_claimId);
515520
return IDataServiceFees.StakeClaim(tokens, createdAt, releasableAt, nextClaim);
516521
}
522+
523+
// This doesn't matter for testing because the metadata is not decoded onchain but it's expected to be of the form:
524+
// - uint256 blockNumber - the block number (indexed chain) the poi’s where computed at
525+
// - bytes32 publicPOI - the public POI matching the presenting poi
526+
// - uint8 indexingStatus - status (failed, syncing, etc). Mapping maintained by indexer agent.
527+
// - uint8 errorCode - Again up to indexer agent, but seems sensible to use 0 if no error, and error codes for anything else.
528+
// - uint256 errorBlockNumber - Block number (indexed chain) where the indexing error happens. 0 if no error.
529+
function _getHardcodedPOIMetadata() internal view returns (bytes memory) {
530+
return abi.encode(block.number, bytes32("PUBLIC_POI1"), uint8(0), uint8(0), uint256(0));
531+
}
517532
}

packages/subgraph-service/test/subgraphService/allocation/forceClose.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
3636
// Skip forward
3737
skip(timeBetweenPOIs);
3838

39-
bytes memory data = abi.encode(allocationID, bytes32("POI1"));
39+
bytes memory data = abi.encode(allocationID, bytes32("POI1"), _getHardcodedPOIMetadata());
4040
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
4141
}
4242

@@ -61,7 +61,7 @@ contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
6161

6262
resetPrank(users.indexer);
6363

64-
bytes memory data = abi.encode(allocationID, bytes32("POI1"));
64+
bytes memory data = abi.encode(allocationID, bytes32("POI1"), _getHardcodedPOIMetadata());
6565
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
6666

6767
resetPrank(permissionlessBob);

packages/subgraph-service/test/subgraphService/allocation/resize.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ contract SubgraphServiceAllocationResizeTest is SubgraphServiceTest {
3939
vm.roll(block.number + EPOCH_LENGTH);
4040

4141
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
42-
bytes memory data = abi.encode(allocationID, bytes32("POI1"));
42+
bytes memory data = abi.encode(allocationID, bytes32("POI1"), _getHardcodedPOIMetadata());
4343
_collect(users.indexer, paymentType, data);
4444
_addToProvision(users.indexer, resizeTokens);
4545
_resizeAllocation(users.indexer, allocationID, resizeTokens);

packages/subgraph-service/test/subgraphService/collect/indexing/indexing.t.sol

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
1515

1616
function test_SubgraphService_Collect_Indexing(uint256 tokens) public useIndexer useAllocation(tokens) {
1717
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
18-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
18+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
1919

2020
// skip time to ensure allocation gets rewards
2121
vm.roll(block.number + EPOCH_LENGTH);
@@ -40,7 +40,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
4040
vm.roll(block.number + EPOCH_LENGTH);
4141

4242
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
43-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
43+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
4444
_collect(users.indexer, paymentType, data);
4545
}
4646

@@ -65,7 +65,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
6565

6666
resetPrank(users.indexer);
6767
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
68-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
68+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
6969
_collect(users.indexer, paymentType, data);
7070
}
7171

@@ -76,7 +76,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
7676
vm.roll(block.number + EPOCH_LENGTH);
7777

7878
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
79-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
79+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
8080
_collect(users.indexer, paymentType, data);
8181
}
8282

@@ -92,7 +92,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
9292

9393
resetPrank(users.indexer);
9494

95-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
95+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
9696
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
9797
}
9898
}
@@ -118,7 +118,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
118118

119119
resetPrank(users.indexer);
120120

121-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
121+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
122122
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
123123
}
124124
}
@@ -145,7 +145,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
145145

146146
// this collection should close the allocation
147147
IGraphPayments.PaymentTypes paymentType = IGraphPayments.PaymentTypes.IndexingRewards;
148-
bytes memory collectData = abi.encode(allocationID, bytes32("POI"));
148+
bytes memory collectData = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
149149
_collect(users.indexer, paymentType, collectData);
150150
}
151151

@@ -156,7 +156,7 @@ contract SubgraphServiceCollectIndexingTest is SubgraphServiceTest {
156156
// Setup new indexer
157157
address newIndexer = makeAddr("newIndexer");
158158
_createAndStartAllocation(newIndexer, tokens);
159-
bytes memory data = abi.encode(allocationID, bytes32("POI"));
159+
bytes memory data = abi.encode(allocationID, bytes32("POI"), _getHardcodedPOIMetadata());
160160

161161
// skip time to ensure allocation gets rewards
162162
vm.roll(block.number + EPOCH_LENGTH);

0 commit comments

Comments
 (0)