Skip to content

Commit e8e6b14

Browse files
committed
fix: handle over allocated condition correctly
Signed-off-by: Tomás Migone <[email protected]>
1 parent 9ca151a commit e8e6b14

File tree

2 files changed

+109
-46
lines changed

2 files changed

+109
-46
lines changed

packages/indexer-common/src/indexer-management/allocations.ts

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,16 @@ export class AllocationManager {
11231123
...tx,
11241124
}
11251125
} else {
1126-
// Horizon: Need to multicall collect and stopService
1126+
// Horizon: Need to collect indexing rewards and stop service
1127+
// Check if indexer is over-allocated - if so, collect() will auto-close the allocation
1128+
// and we should NOT call stopService to avoid "AllocationClosed" revert
1129+
const isOverAllocated =
1130+
await this.network.contracts.SubgraphService.isOverAllocated(params.indexer)
1131+
1132+
logger.debug('Checking over-allocation status for unallocate', {
1133+
allocationID: params.allocationID,
1134+
isOverAllocated,
1135+
})
11271136

11281137
// collect
11291138
const collectIndexingRewardsData = encodeCollectIndexingRewardsData(
@@ -1137,29 +1146,48 @@ export class AllocationManager {
11371146
0,
11381147
),
11391148
)
1140-
const collectCallData =
1141-
this.network.contracts.SubgraphService.interface.encodeFunctionData('collect', [
1142-
params.indexer,
1143-
PaymentTypes.IndexingRewards,
1144-
collectIndexingRewardsData,
1145-
])
11461149

1147-
// stopService
1148-
const stopServiceCallData =
1149-
this.network.contracts.SubgraphService.interface.encodeFunctionData(
1150-
'stopService',
1151-
[params.indexer, encodeStopServiceData(params.allocationID)],
1150+
if (isOverAllocated) {
1151+
logger.info(
1152+
'Indexer is over-allocated, using collect-only transaction (allocation will auto-close)',
1153+
{ allocationID: params.allocationID },
11521154
)
1155+
const tx =
1156+
await this.network.contracts.SubgraphService.collect.populateTransaction(
1157+
params.indexer,
1158+
PaymentTypes.IndexingRewards,
1159+
collectIndexingRewardsData,
1160+
)
1161+
return {
1162+
protocolNetwork: params.protocolNetwork,
1163+
actionID: params.actionID,
1164+
...tx,
1165+
}
1166+
} else {
1167+
// Normal path: multicall collect + stopService
1168+
const collectCallData =
1169+
this.network.contracts.SubgraphService.interface.encodeFunctionData('collect', [
1170+
params.indexer,
1171+
PaymentTypes.IndexingRewards,
1172+
collectIndexingRewardsData,
1173+
])
1174+
1175+
const stopServiceCallData =
1176+
this.network.contracts.SubgraphService.interface.encodeFunctionData(
1177+
'stopService',
1178+
[params.indexer, encodeStopServiceData(params.allocationID)],
1179+
)
11531180

1154-
const tx =
1155-
await this.network.contracts.SubgraphService.multicall.populateTransaction([
1156-
collectCallData,
1157-
stopServiceCallData,
1158-
])
1159-
return {
1160-
protocolNetwork: params.protocolNetwork,
1161-
actionID: params.actionID,
1162-
...tx,
1181+
const tx =
1182+
await this.network.contracts.SubgraphService.multicall.populateTransaction([
1183+
collectCallData,
1184+
stopServiceCallData,
1185+
])
1186+
return {
1187+
protocolNetwork: params.protocolNetwork,
1188+
actionID: params.actionID,
1189+
...tx,
1190+
}
11631191
}
11641192
}
11651193
}

packages/indexer-common/src/indexer-management/resolvers/allocations.ts

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pMap from 'p-map'
55
import gql from 'graphql-tag'
6-
import { ethers, hexlify, ZeroAddress } from 'ethers'
6+
import { ethers, hexlify, TransactionReceipt, ZeroAddress } from 'ethers'
77

88
import {
99
Address,
@@ -735,6 +735,15 @@ async function closeHorizonAllocation(
735735
throw indexerError(IndexerErrorCode.IE065, 'Allocation has already been closed')
736736
}
737737

738+
// Check if indexer is over-allocated - if so, collect() will auto-close the allocation
739+
// and we should NOT call stopService to avoid "AllocationClosed" revert
740+
const isOverAllocated = await contracts.SubgraphService.isOverAllocated(address)
741+
742+
logger.debug('Checking over-allocation status for close allocation', {
743+
allocationId: allocation.id,
744+
isOverAllocated,
745+
})
746+
738747
const encodedPOIMetadata = encodePOIMetadata(
739748
poiData.blockNumber,
740749
poiData.publicPOI,
@@ -748,28 +757,54 @@ async function closeHorizonAllocation(
748757
encodedPOIMetadata,
749758
)
750759

751-
const collectCallData = contracts.SubgraphService.interface.encodeFunctionData(
752-
'collect',
753-
[address, PaymentTypes.IndexingRewards, collectIndexingRewardsData],
754-
)
755-
const closeAllocationData = encodeStopServiceData(allocation.id)
756-
const stopServiceCallData = contracts.SubgraphService.interface.encodeFunctionData(
757-
'stopService',
758-
[address, closeAllocationData],
759-
)
760+
let receipt: TransactionReceipt | 'paused' | 'unauthorized'
760761

761-
const receipt = await transactionManager.executeTransaction(
762-
async () =>
763-
contracts.SubgraphService.multicall.estimateGas([
764-
collectCallData,
765-
stopServiceCallData,
766-
]),
767-
async (gasLimit) =>
768-
contracts.SubgraphService.multicall([collectCallData, stopServiceCallData], {
769-
gasLimit,
770-
}),
771-
logger,
772-
)
762+
if (isOverAllocated) {
763+
logger.info(
764+
'Indexer is over-allocated, using collect-only transaction (allocation will auto-close)',
765+
{ allocationId: allocation.id },
766+
)
767+
receipt = await transactionManager.executeTransaction(
768+
async () =>
769+
contracts.SubgraphService.collect.estimateGas(
770+
address,
771+
PaymentTypes.IndexingRewards,
772+
collectIndexingRewardsData,
773+
),
774+
async (gasLimit) =>
775+
contracts.SubgraphService.collect(
776+
address,
777+
PaymentTypes.IndexingRewards,
778+
collectIndexingRewardsData,
779+
{ gasLimit },
780+
),
781+
logger,
782+
)
783+
} else {
784+
// Normal path: multicall collect + stopService
785+
const collectCallData = contracts.SubgraphService.interface.encodeFunctionData(
786+
'collect',
787+
[address, PaymentTypes.IndexingRewards, collectIndexingRewardsData],
788+
)
789+
const closeAllocationData = encodeStopServiceData(allocation.id)
790+
const stopServiceCallData = contracts.SubgraphService.interface.encodeFunctionData(
791+
'stopService',
792+
[address, closeAllocationData],
793+
)
794+
795+
receipt = await transactionManager.executeTransaction(
796+
async () =>
797+
contracts.SubgraphService.multicall.estimateGas([
798+
collectCallData,
799+
stopServiceCallData,
800+
]),
801+
async (gasLimit) =>
802+
contracts.SubgraphService.multicall([collectCallData, stopServiceCallData], {
803+
gasLimit,
804+
}),
805+
logger,
806+
)
807+
}
773808

774809
if (receipt === 'paused' || receipt === 'unauthorized') {
775810
throw indexerError(
@@ -802,10 +837,10 @@ async function closeHorizonAllocation(
802837
}
803838

804839
const closeAllocationEventLogs = transactionManager.findEvent(
805-
'ServiceStopped',
840+
'AllocationClosed',
806841
contracts.SubgraphService.interface,
807-
'serviceProvider',
808-
address,
842+
'allocationId',
843+
allocation.id,
809844
receipt,
810845
logger,
811846
)

0 commit comments

Comments
 (0)