@@ -129,6 +129,7 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
129
129
* An amount of `tokens` get unallocated from `subgraphDeploymentID`.
130
130
* The `effectiveAllocation` are the tokens allocated from creation to closing.
131
131
* This event also emits the POI (proof of indexing) submitted by the indexer.
132
+ * `isDelegator` is true if the sender was one of the indexer's delegators.
132
133
*/
133
134
event AllocationClosed (
134
135
address indexed indexer ,
@@ -138,7 +139,8 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
138
139
address indexed allocationID ,
139
140
uint256 effectiveAllocation ,
140
141
address sender ,
141
- bytes32 poi
142
+ bytes32 poi ,
143
+ bool isDelegator
142
144
);
143
145
144
146
/**
@@ -189,13 +191,6 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
189
191
return msg .sender == _indexer || isOperator (msg .sender , _indexer) == true ;
190
192
}
191
193
192
- /**
193
- * @dev Check if the caller is authorized (indexer, operator or delegator)
194
- */
195
- function _isAuthOrDelegator (address _indexer ) private view returns (bool ) {
196
- return _isAuth (_indexer) || delegationPools[_indexer].delegators[msg .sender ].shares > 0 ;
197
- }
198
-
199
194
/**
200
195
* @dev Initialize this contract.
201
196
*/
@@ -584,6 +579,16 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
584
579
return delegationPools[_indexer].delegators[_delegator];
585
580
}
586
581
582
+ /**
583
+ * @dev Return whether the delegator has delegated to the indexer.
584
+ * @param _indexer Address of the indexer where funds have been delegated
585
+ * @param _delegator Address of the delegator
586
+ * @return True if delegator of indexer
587
+ */
588
+ function isDelegator (address _indexer , address _delegator ) public view returns (bool ) {
589
+ return delegationPools[_indexer].delegators[_delegator].shares > 0 ;
590
+ }
591
+
587
592
/**
588
593
* @dev Get the total amount of tokens staked by the indexer.
589
594
* @param _indexer Address of the indexer
@@ -1118,15 +1123,12 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1118
1123
* @param _poi Proof of indexing submitted for the allocated period
1119
1124
*/
1120
1125
function _closeAllocation (address _allocationID , bytes32 _poi ) private {
1121
- // Get allocation
1122
- Allocation storage alloc = allocations[_allocationID];
1123
- AllocationState allocState = _getAllocationState (_allocationID);
1124
-
1125
1126
// Allocation must exist and be active
1127
+ AllocationState allocState = _getAllocationState (_allocationID);
1126
1128
require (allocState == AllocationState.Active, "!active " );
1127
1129
1128
- // Get indexer stakes
1129
- Stakes.Indexer storage indexerStake = stakes[alloc.indexer ];
1130
+ // Get allocation
1131
+ Allocation storage alloc = allocations[_allocationID ];
1130
1132
1131
1133
// Validate that an allocation cannot be closed before one epoch
1132
1134
uint256 currentEpoch = epochManager ().currentEpoch ();
@@ -1135,13 +1137,13 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1135
1137
: 0 ;
1136
1138
require (epochs > 0 , "<epochs " );
1137
1139
1138
- // Validate ownership
1140
+ // Indexer or operator can close an allocation
1141
+ // Delegators are also allowed but only after maxAllocationEpochs passed
1142
+ bool isIndexer = _isAuth (alloc.indexer);
1139
1143
if (epochs > maxAllocationEpochs) {
1140
- // Verify that the allocation owner or delegator is closing
1141
- require (_isAuthOrDelegator (alloc.indexer), "!auth-or-del " );
1144
+ require (isIndexer || isDelegator (alloc.indexer, msg .sender ), "!auth-or-del " );
1142
1145
} else {
1143
- // Verify that the allocation owner is closing
1144
- require (_isAuth (alloc.indexer), "!auth " );
1146
+ require (isIndexer, "!auth " );
1145
1147
}
1146
1148
1147
1149
// Close the allocation and start counting a period to settle remaining payments from
@@ -1157,12 +1159,12 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1157
1159
rebatePool.addToPool (alloc.collectedFees, alloc.effectiveAllocation);
1158
1160
1159
1161
// Distribute rewards if proof of indexing was presented by the indexer or operator
1160
- if (_isAuth ( msg . sender ) && _poi != 0 ) {
1162
+ if (isIndexer && _poi != 0 ) {
1161
1163
_distributeRewards (_allocationID, alloc.indexer);
1162
1164
}
1163
1165
1164
1166
// Free allocated tokens from use
1165
- indexerStake .unallocate (alloc.tokens);
1167
+ stakes[alloc.indexer] .unallocate (alloc.tokens);
1166
1168
1167
1169
// Track total allocations per subgraph
1168
1170
// Used for rewards calculations
@@ -1178,7 +1180,8 @@ contract Staking is StakingV1Storage, GraphUpgradeable, IStaking {
1178
1180
_allocationID,
1179
1181
alloc.effectiveAllocation,
1180
1182
msg .sender ,
1181
- _poi
1183
+ _poi,
1184
+ ! isIndexer
1182
1185
);
1183
1186
}
1184
1187
0 commit comments