Skip to content

Commit 7efedcc

Browse files
committed
fix: overallocated condition no longer allows force closing (TRST-H05)
Signed-off-by: Tomás Migone <[email protected]>
1 parent 0c0d090 commit 7efedcc

File tree

4 files changed

+20
-70
lines changed

4 files changed

+20
-70
lines changed

packages/subgraph-service/contracts/SubgraphService.sol

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,9 @@ contract SubgraphService is
312312
/**
313313
* @notice See {ISubgraphService.closeStaleAllocation}
314314
*/
315-
function forceCloseAllocation(address allocationId) external override {
315+
function closeStaleAllocation(address allocationId) external override {
316316
Allocation.State memory allocation = allocations.get(allocationId);
317-
bool isStale = allocation.isStale(maxPOIStaleness);
318-
bool isOverAllocated_ = _isOverAllocated(allocation.indexer, delegationRatio);
319-
require(isStale || isOverAllocated_, SubgraphServiceCannotForceCloseAllocation(allocationId));
317+
require(allocation.isStale(maxPOIStaleness), SubgraphServiceCannotForceCloseAllocation(allocationId));
320318
require(!allocation.isAltruistic(), SubgraphServiceAllocationIsAltruistic(allocationId));
321319
_closeAllocation(allocationId);
322320
}

packages/subgraph-service/contracts/interfaces/ISubgraphService.sol

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,20 @@ interface ISubgraphService is IDataServiceFees {
127127
error SubgraphServiceInvalidZeroStakeToFeesRatio();
128128

129129
/**
130-
* @notice Force close an allocation
131-
* @dev This function can be permissionlessly called when the allocation is stale or
132-
* if the indexer is over-allocated. This ensures that rewards for other allocations are
133-
* not diluted by an inactive allocation, and that over-allocated indexers stop accumulating
134-
* rewards with tokens they no longer have allocated.
130+
* @notice Force close a stale allocation
131+
* @dev This function can be permissionlessly called when the allocation is stale. This
132+
* ensures that rewards for other allocations are not diluted by an inactive allocation.
135133
*
136134
* Requirements:
137135
* - Allocation must exist and be open
138-
* - Allocation must be stale or indexer must be over-allocated
136+
* - Allocation must be stale
139137
* - Allocation cannot be altruistic
140138
*
141139
* Emits a {AllocationClosed} event.
142140
*
143141
* @param allocationId The id of the allocation
144142
*/
145-
function forceCloseAllocation(address allocationId) external;
143+
function closeStaleAllocation(address allocationId) external;
146144

147145
/**
148146
* @notice Change the amount of tokens in an allocation

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
151151
assertEq(afterSubgraphAllocatedTokens, _tokens);
152152
}
153153

154-
function _forceCloseAllocation(address _allocationId) internal {
154+
function _closeStaleAllocation(address _allocationId) internal {
155155
assertTrue(subgraphService.isActiveAllocation(_allocationId));
156156

157157
Allocation.State memory allocation = subgraphService.getAllocation(_allocationId);
@@ -168,7 +168,7 @@ contract SubgraphServiceTest is SubgraphServiceSharedTest {
168168
);
169169

170170
// close stale allocation
171-
subgraphService.forceCloseAllocation(_allocationId);
171+
subgraphService.closeStaleAllocation(_allocationId);
172172

173173
// update allocation
174174
allocation = subgraphService.getAllocation(_allocationId);

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

Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,30 @@ pragma solidity 0.8.27;
33

44
import "forge-std/Test.sol";
55

6-
import { IDataService } from "@graphprotocol/horizon/contracts/data-service/interfaces/IDataService.sol";
76
import { IGraphPayments } from "@graphprotocol/horizon/contracts/interfaces/IGraphPayments.sol";
8-
import { ProvisionManager } from "@graphprotocol/horizon/contracts/data-service/utilities/ProvisionManager.sol";
9-
import { ProvisionTracker } from "@graphprotocol/horizon/contracts/data-service/libraries/ProvisionTracker.sol";
107

118
import { Allocation } from "../../../contracts/libraries/Allocation.sol";
12-
import { AllocationManager } from "../../../contracts/utilities/AllocationManager.sol";
139
import { ISubgraphService } from "../../../contracts/interfaces/ISubgraphService.sol";
14-
import { LegacyAllocation } from "../../../contracts/libraries/LegacyAllocation.sol";
1510
import { SubgraphServiceTest } from "../SubgraphService.t.sol";
1611

1712
contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
18-
1913
address private permissionlessBob = makeAddr("permissionlessBob");
2014

2115
/*
2216
* TESTS
2317
*/
2418

25-
function test_SubgraphService_Allocation_ForceClose_Stale(
26-
uint256 tokens
27-
) public useIndexer useAllocation(tokens) {
19+
function test_SubgraphService_Allocation_ForceClose_Stale(uint256 tokens) public useIndexer useAllocation(tokens) {
2820
// Skip forward
2921
skip(maxPOIStaleness + 1);
3022

3123
resetPrank(permissionlessBob);
32-
_forceCloseAllocation(allocationID);
24+
_closeStaleAllocation(allocationID);
3325
}
3426

3527
function test_SubgraphService_Allocation_ForceClose_Stale_AfterCollecting(
3628
uint256 tokens
37-
) public useIndexer useAllocation(tokens) {
29+
) public useIndexer useAllocation(tokens) {
3830
// Simulate POIs being submitted
3931
uint8 numberOfPOIs = 5;
4032
uint256 timeBetweenPOIs = 5 days;
@@ -52,43 +44,10 @@ contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
5244

5345
// Close the stale allocation
5446
resetPrank(permissionlessBob);
55-
_forceCloseAllocation(allocationID);
56-
}
57-
58-
function test_SubgraphService_Allocation_ForceClose_OverAllocated(
59-
uint256 tokens
60-
) public useIndexer useAllocation(tokens) {
61-
// thaw some tokens to become over allocated
62-
staking.thaw(users.indexer, address(subgraphService), tokens / 2);
63-
64-
resetPrank(permissionlessBob);
65-
_forceCloseAllocation(allocationID);
66-
}
67-
68-
function test_SubgraphService_Allocation_ForceClose_OverAllocated_AfterCollecting(
69-
uint256 tokens
70-
) public useIndexer useAllocation(tokens) {
71-
// Simulate POIs being submitted
72-
uint8 numberOfPOIs = 5;
73-
uint256 timeBetweenPOIs = 5 days;
74-
75-
for (uint8 i = 0; i < numberOfPOIs; i++) {
76-
// Skip forward
77-
skip(timeBetweenPOIs);
78-
79-
bytes memory data = abi.encode(allocationID, bytes32("POI1"));
80-
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
81-
}
82-
83-
// thaw some tokens to become over allocated
84-
staking.thaw(users.indexer, address(subgraphService), tokens / 2);
85-
86-
// Close the over allocated allocation
87-
resetPrank(permissionlessBob);
88-
_forceCloseAllocation(allocationID);
47+
_closeStaleAllocation(allocationID);
8948
}
9049

91-
function test_SubgraphService_Allocation_ForceClose_RevertIf_NotStaleOrOverAllocated(
50+
function test_SubgraphService_Allocation_ForceClose_RevertIf_NotStale(
9251
uint256 tokens
9352
) public useIndexer useAllocation(tokens) {
9453
// Simulate POIs being submitted
@@ -98,26 +57,24 @@ contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
9857
for (uint8 i = 0; i < numberOfPOIs; i++) {
9958
// Skip forward
10059
skip(timeBetweenPOIs);
101-
60+
10261
resetPrank(users.indexer);
10362

10463
bytes memory data = abi.encode(allocationID, bytes32("POI1"));
10564
_collect(users.indexer, IGraphPayments.PaymentTypes.IndexingRewards, data);
106-
65+
10766
resetPrank(permissionlessBob);
10867
vm.expectRevert(
10968
abi.encodeWithSelector(
11069
ISubgraphService.SubgraphServiceCannotForceCloseAllocation.selector,
11170
allocationID
11271
)
11372
);
114-
subgraphService.forceCloseAllocation(allocationID);
73+
subgraphService.closeStaleAllocation(allocationID);
11574
}
11675
}
11776

118-
function test_SubgraphService_Allocation_ForceClose_RevertIf_Altruistic(
119-
uint256 tokens
120-
) public useIndexer {
77+
function test_SubgraphService_Allocation_ForceClose_RevertIf_Altruistic(uint256 tokens) public useIndexer {
12178
tokens = bound(tokens, minimumProvisionTokens, MAX_TOKENS);
12279

12380
_createProvision(users.indexer, tokens, maxSlashingPercentage, disputePeriod);
@@ -130,11 +87,8 @@ contract SubgraphServiceAllocationForceCloseTest is SubgraphServiceTest {
13087

13188
resetPrank(permissionlessBob);
13289
vm.expectRevert(
133-
abi.encodeWithSelector(
134-
ISubgraphService.SubgraphServiceAllocationIsAltruistic.selector,
135-
allocationID
136-
)
90+
abi.encodeWithSelector(ISubgraphService.SubgraphServiceAllocationIsAltruistic.selector, allocationID)
13791
);
138-
subgraphService.forceCloseAllocation(allocationID);
92+
subgraphService.closeStaleAllocation(allocationID);
13993
}
14094
}

0 commit comments

Comments
 (0)