Skip to content

Commit 6f250de

Browse files
committed
feat: add initial provision management, without thawing tracking
1 parent fe09148 commit 6f250de

File tree

4 files changed

+256
-50
lines changed

4 files changed

+256
-50
lines changed

schema.graphql

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ type GraphNetwork @entity {
8888
totalUnstakedTokensLocked: BigInt!
8989
"Total GRT currently in provisions"
9090
totalTokensProvisioned: BigInt!
91+
"Total GRT currently thawing from provisions"
92+
totalTokensThawing: BigInt!
9193
"Total GRT currently in allocation"
9294
totalTokensAllocated: BigInt!
9395
"Total delegated tokens in the protocol"
@@ -239,8 +241,12 @@ type DataService @entity {
239241

240242
"Total GRT currently in provisions for this DataService"
241243
totalTokensProvisioned: BigInt!
244+
"Total GRT currently thawing from provisions for this DataService"
245+
totalTokensThawing: BigInt!
242246
"Total GRT currently in allocations for this DataService"
243247
totalTokensAllocated: BigInt!
248+
249+
provisions: [Provision!]! @derivedFrom(field: "service")
244250
}
245251

246252
"""
@@ -689,6 +695,8 @@ type Indexer @entity {
689695
stakedTokens: BigInt!
690696
"CURRENT tokens provisioned to data services in the protocol. In the V1 protocol, all staked tokens were always provisioned since there was only one data service"
691697
provisionedTokens: BigInt!
698+
"CURRENT tokens thawing from provisions to data services in the protocol. Only for Horizon"
699+
thawingTokens: BigInt!
692700
"CURRENT tokens allocated on all subgraphs"
693701
allocatedTokens: BigInt!
694702
"NOT IMPLEMENTED - Tokens that have been unstaked and withdrawn"
@@ -838,6 +846,27 @@ type Provision @entity {
838846
service: DataService!
839847

840848
tokensProvisioned: BigInt!
849+
850+
"Service provider tokens that are being thawed (and will stop being slashable soon)"
851+
tokensThawing: BigInt!
852+
853+
"Shares representing the thawing tokens"
854+
sharesThawing: BigInt!
855+
856+
"Max amount that can be taken by the verifier when slashing, expressed in parts-per-million of the amount slashed"
857+
maxVerifierCut: Int!
858+
859+
"Time, in seconds, tokens must thaw before being withdrawn"
860+
thawingPeriod: BigInt!
861+
862+
"Timestamp when the provision was created"
863+
createdAt: BigInt!
864+
865+
"Pending value for maxVerifierCut. Verifier needs to accept it before it becomes active"
866+
maxVerifierCutPending: Int!
867+
868+
"Pending value for thawingPeriod. Verifier needs to accept it before it becomes active"
869+
thawingPeriodPending: BigInt!
841870
}
842871

843872
"""

src/mappings/helpers/helpers.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626
CurrentSubgraphDeploymentRelation,
2727
PaymentSource,
2828
IndexerQueryFeePaymentAggregation,
29+
Provision,
30+
DataService,
2931
} from '../../types/schema'
3032
import {
3133
SubgraphDeploymentManifest as SubgraphDeploymentManifestTemplate
@@ -137,6 +139,7 @@ export function createOrLoadIndexer(indexerAddress: Bytes, timestamp: BigInt): I
137139
indexer.transferredToL2 = false
138140
indexer.stakedTokensTransferredToL2 = BigInt.fromI32(0)
139141
indexer.provisionedTokens = BigInt.fromI32(0)
142+
indexer.thawingTokens = BigInt.fromI32(0)
140143
indexer.allocatedTokens = BigInt.fromI32(0)
141144
indexer.lockedTokens = BigInt.fromI32(0)
142145
indexer.unstakedTokens = BigInt.fromI32(0)
@@ -188,6 +191,41 @@ export function createOrLoadIndexer(indexerAddress: Bytes, timestamp: BigInt): I
188191
return indexer as Indexer
189192
}
190193

194+
export function createOrLoadProvision(indexerAddress: Bytes, verifierAddress: Bytes, timestamp: BigInt): Provision {
195+
let id = joinID([indexerAddress.toHexString(), verifierAddress.toHexString()])
196+
let provision = Provision.load(id)
197+
if (provision == null) {
198+
provision = new Provision(id)
199+
provision.indexer = indexerAddress.toHexString()
200+
provision.service = verifierAddress.toHexString()
201+
provision.tokensProvisioned = BigInt.fromI32(0)
202+
provision.tokensThawing = BigInt.fromI32(0)
203+
provision.sharesThawing = BigInt.fromI32(0)
204+
provision.createdAt = timestamp
205+
provision.maxVerifierCut = 0
206+
provision.maxVerifierCutPending = 0
207+
provision.thawingPeriod = BigInt.fromI32(0)
208+
provision.thawingPeriodPending = BigInt.fromI32(0)
209+
provision.save()
210+
}
211+
212+
return provision as Provision
213+
}
214+
215+
export function createOrLoadDataService(verifierAddress: Bytes): DataService {
216+
let id = verifierAddress.toHexString()
217+
let service = DataService.load(id)
218+
if (service == null) {
219+
service = new DataService(id)
220+
service.totalTokensAllocated = BigInt.fromI32(0)
221+
service.totalTokensProvisioned = BigInt.fromI32(0)
222+
service.totalTokensThawing = BigInt.fromI32(0)
223+
service.save()
224+
}
225+
226+
return service as DataService
227+
}
228+
191229
export function createOrLoadPaymentSource(paymentAddress: Bytes): PaymentSource {
192230
let id = paymentAddress.toHexString()
193231
let paymentSource = PaymentSource.load(id)
@@ -554,6 +592,7 @@ export function createOrLoadGraphNetwork(
554592
graphNetwork.totalTokensClaimable = BigInt.fromI32(0)
555593
graphNetwork.totalUnstakedTokensLocked = BigInt.fromI32(0)
556594
graphNetwork.totalTokensProvisioned = BigInt.fromI32(0)
595+
graphNetwork.totalTokensThawing = BigInt.fromI32(0)
557596
graphNetwork.totalTokensAllocated = BigInt.fromI32(0)
558597
graphNetwork.totalDelegatedTokens = BigInt.fromI32(0)
559598
graphNetwork.totalTokensSignalled = BigInt.fromI32(0)

src/mappings/horizonStaking.ts

Lines changed: 166 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
import { BigInt } from '@graphprotocol/graph-ts'
1+
import { BigInt, log } from '@graphprotocol/graph-ts'
22
import { addresses } from '../../config/addresses.template'
3-
import { HorizonStakeDeposited, HorizonStakeLocked, HorizonStakeWithdrawn} from '../types/HorizonStaking/HorizonStaking'
4-
import { Indexer } from '../types/schema'
5-
import { calculateCapacities, createOrLoadEpoch, createOrLoadGraphNetwork, createOrLoadIndexer, updateAdvancedIndexerMetrics } from './helpers/helpers'
6-
3+
import { HorizonStakeDeposited, HorizonStakeLocked, HorizonStakeWithdrawn, TokensDeprovisioned } from '../types/HorizonStaking/HorizonStaking'
4+
import { Indexer, GraphNetwork } from '../types/schema'
5+
import { calculateCapacities, createOrLoadDataService, createOrLoadEpoch, createOrLoadGraphNetwork, createOrLoadIndexer, createOrLoadProvision, updateAdvancedIndexerMetrics } from './helpers/helpers'
6+
import {
7+
ProvisionCreated,
8+
ProvisionIncreased,
9+
ProvisionParametersSet,
10+
ProvisionParametersStaged,
11+
ProvisionSlashed,
12+
ProvisionThawed,
13+
ThawRequestCreated,
14+
ThawRequestFulfilled,
15+
ThawRequestsFulfilled,
16+
ThawingPeriodCleared
17+
} from '../types/HorizonStaking/HorizonStaking'
718

819
export function handleHorizonStakeDeposited(event: HorizonStakeDeposited): void {
9-
// To Do
1020
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
1121
// update indexer
1222
let indexer = createOrLoadIndexer(event.params.serviceProvider, event.block.timestamp)
@@ -15,64 +25,170 @@ export function handleHorizonStakeDeposited(event: HorizonStakeDeposited): void
1525
indexer = updateAdvancedIndexerMetrics(indexer as Indexer)
1626
indexer = calculateCapacities(indexer as Indexer)
1727
indexer.save()
18-
28+
1929
// Update graph network
2030
graphNetwork.totalTokensStaked = graphNetwork.totalTokensStaked.plus(event.params.tokens)
2131
if (previousStake == BigInt.fromI32(0)) {
22-
graphNetwork.stakedIndexersCount = graphNetwork.stakedIndexersCount + 1
32+
graphNetwork.stakedIndexersCount = graphNetwork.stakedIndexersCount + 1
2333
}
2434
graphNetwork.save()
25-
35+
2636
// Update epoch
2737
let epoch = createOrLoadEpoch(
28-
addresses.isL1 ? event.block.number : graphNetwork.currentL1BlockNumber!,
38+
addresses.isL1 ? event.block.number : graphNetwork.currentL1BlockNumber!,
2939
)
3040
epoch.stakeDeposited = epoch.stakeDeposited.plus(event.params.tokens)
3141
epoch.save()
3242
}
3343

3444
export function handleHorizonStakeLocked(event: HorizonStakeLocked): void {
35-
// To Do
36-
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
37-
// update indexer
38-
let id = event.params.serviceProvider.toHexString()
39-
let indexer = Indexer.load(id)!
40-
let oldLockedTokens = indexer.lockedTokens
41-
indexer.lockedTokens = event.params.tokens
42-
indexer.tokensLockedUntil = event.params.until.toI32()
43-
indexer = updateAdvancedIndexerMetrics(indexer as Indexer)
44-
indexer = calculateCapacities(indexer as Indexer)
45-
indexer.save()
46-
47-
// update graph network
48-
// the tokens from the event replace the previously locked tokens
49-
// from this indexer
50-
graphNetwork.totalUnstakedTokensLocked = graphNetwork.totalUnstakedTokensLocked.plus(
51-
event.params.tokens,
52-
).minus(oldLockedTokens)
53-
if (indexer.stakedTokens == indexer.lockedTokens) {
54-
graphNetwork.stakedIndexersCount = graphNetwork.stakedIndexersCount - 1
55-
}
56-
graphNetwork.save()
45+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
46+
// update indexer
47+
let id = event.params.serviceProvider.toHexString()
48+
let indexer = Indexer.load(id)!
49+
let oldLockedTokens = indexer.lockedTokens
50+
indexer.lockedTokens = event.params.tokens
51+
indexer.tokensLockedUntil = event.params.until.toI32()
52+
indexer = updateAdvancedIndexerMetrics(indexer as Indexer)
53+
indexer = calculateCapacities(indexer as Indexer)
54+
indexer.save()
55+
56+
// update graph network
57+
// the tokens from the event replace the previously locked tokens
58+
// from this indexer
59+
graphNetwork.totalUnstakedTokensLocked = graphNetwork.totalUnstakedTokensLocked.plus(
60+
event.params.tokens,
61+
).minus(oldLockedTokens)
62+
if (indexer.stakedTokens == indexer.lockedTokens) {
63+
graphNetwork.stakedIndexersCount = graphNetwork.stakedIndexersCount - 1
64+
}
65+
graphNetwork.save()
5766
}
5867

5968
export function handleHorizonStakeWithdrawn(event: HorizonStakeWithdrawn): void {
60-
// To Do
61-
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
62-
// update indexer
63-
let id = event.params.serviceProvider.toHexString()
64-
let indexer = Indexer.load(id)!
65-
indexer.stakedTokens = indexer.stakedTokens.minus(event.params.tokens)
66-
indexer.lockedTokens = BigInt.fromI32(0) // set to 0 to prevent issues when Stage 2 comes
67-
indexer.tokensLockedUntil = 0 // always set to 0 when withdrawn
68-
indexer = updateAdvancedIndexerMetrics(indexer as Indexer)
69-
indexer = calculateCapacities(indexer as Indexer)
70-
indexer.save()
71-
72-
// Update graph network
73-
graphNetwork.totalTokensStaked = graphNetwork.totalTokensStaked.minus(event.params.tokens)
74-
graphNetwork.totalUnstakedTokensLocked = graphNetwork.totalUnstakedTokensLocked.minus(
75-
event.params.tokens,
76-
)
77-
graphNetwork.save()
69+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
70+
// update indexer
71+
let id = event.params.serviceProvider.toHexString()
72+
let indexer = Indexer.load(id)!
73+
indexer.stakedTokens = indexer.stakedTokens.minus(event.params.tokens)
74+
indexer.lockedTokens = BigInt.fromI32(0) // set to 0 to prevent issues when Stage 2 comes
75+
indexer.tokensLockedUntil = 0 // always set to 0 when withdrawn
76+
indexer = updateAdvancedIndexerMetrics(indexer as Indexer)
77+
indexer = calculateCapacities(indexer as Indexer)
78+
indexer.save()
79+
80+
// Update graph network
81+
graphNetwork.totalTokensStaked = graphNetwork.totalTokensStaked.minus(event.params.tokens)
82+
graphNetwork.totalUnstakedTokensLocked = graphNetwork.totalUnstakedTokensLocked.minus(
83+
event.params.tokens,
84+
)
85+
graphNetwork.save()
86+
}
87+
88+
export function handleProvisionCreated(event: ProvisionCreated): void {
89+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
90+
let dataService = createOrLoadDataService(event.params.verifier)
91+
let indexer = Indexer.load(event.params.serviceProvider.toHexString())!
92+
let provision = createOrLoadProvision(event.params.serviceProvider, event.params.verifier, event.block.timestamp)
93+
94+
indexer.provisionedTokens = indexer.provisionedTokens.plus(event.params.tokens)
95+
indexer.save()
96+
97+
dataService.totalTokensProvisioned = dataService.totalTokensProvisioned.plus(event.params.tokens)
98+
dataService.save()
99+
100+
graphNetwork.totalTokensProvisioned = graphNetwork.totalTokensProvisioned.plus(event.params.tokens)
101+
graphNetwork.save()
102+
103+
provision.tokensProvisioned = provision.tokensProvisioned.plus(event.params.tokens)
104+
provision.maxVerifierCut = event.params.maxVerifierCut
105+
provision.maxVerifierCutPending = event.params.maxVerifierCut
106+
provision.thawingPeriod = event.params.thawingPeriod
107+
provision.thawingPeriodPending = event.params.thawingPeriod
108+
provision.save()
109+
}
110+
111+
export function handleProvisionIncreased(event: ProvisionIncreased): void {
112+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
113+
let dataService = createOrLoadDataService(event.params.verifier)
114+
let indexer = Indexer.load(event.params.serviceProvider.toHexString())!
115+
let provision = createOrLoadProvision(event.params.serviceProvider, event.params.verifier, event.block.timestamp)
116+
117+
indexer.provisionedTokens = indexer.provisionedTokens.plus(event.params.tokens)
118+
indexer.save()
119+
120+
dataService.totalTokensProvisioned = dataService.totalTokensProvisioned.plus(event.params.tokens)
121+
dataService.save()
122+
123+
graphNetwork.totalTokensProvisioned = graphNetwork.totalTokensProvisioned.plus(event.params.tokens)
124+
graphNetwork.save()
125+
126+
provision.tokensProvisioned = provision.tokensProvisioned.plus(event.params.tokens)
127+
provision.save()
128+
}
129+
130+
export function handleProvisionThawed(event: ProvisionThawed): void {
131+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
132+
let dataService = createOrLoadDataService(event.params.verifier)
133+
let indexer = Indexer.load(event.params.serviceProvider.toHexString())!
134+
let provision = createOrLoadProvision(event.params.serviceProvider, event.params.verifier, event.block.timestamp)
135+
136+
indexer.thawingTokens = indexer.thawingTokens.plus(event.params.tokens)
137+
indexer.save()
138+
139+
dataService.totalTokensThawing = dataService.totalTokensThawing.plus(event.params.tokens)
140+
dataService.save()
141+
142+
graphNetwork.totalTokensThawing = graphNetwork.totalTokensThawing.plus(event.params.tokens)
143+
graphNetwork.save()
144+
145+
provision.tokensThawing = provision.tokensThawing.plus(event.params.tokens)
146+
provision.save()
147+
}
148+
149+
export function handleTokensDeprovisioned(event: TokensDeprovisioned): void {
150+
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
151+
let dataService = createOrLoadDataService(event.params.verifier)
152+
let indexer = Indexer.load(event.params.serviceProvider.toHexString())!
153+
let provision = createOrLoadProvision(event.params.serviceProvider, event.params.verifier, event.block.timestamp)
154+
155+
indexer.provisionedTokens = indexer.provisionedTokens.minus(event.params.tokens)
156+
indexer.save()
157+
158+
dataService.totalTokensProvisioned = dataService.totalTokensProvisioned.minus(event.params.tokens)
159+
dataService.save()
160+
161+
graphNetwork.totalTokensProvisioned = graphNetwork.totalTokensProvisioned.minus(event.params.tokens)
162+
graphNetwork.save()
163+
164+
provision.tokensProvisioned = provision.tokensProvisioned.minus(event.params.tokens)
165+
provision.save()
166+
}
167+
168+
export function handleProvisionParametersSet(event: ProvisionParametersSet): void {
169+
// To Do
170+
}
171+
172+
export function handleProvisionParametersStaged(event: ProvisionParametersStaged): void {
173+
// To Do
174+
}
175+
176+
export function handleProvisionSlashed(event: ProvisionSlashed): void {
177+
// To Do
178+
}
179+
180+
export function handleThawRequestCreated(event: ThawRequestCreated): void {
181+
// To Do
182+
}
183+
184+
export function handleThawRequestFulfilled(event: ThawRequestFulfilled): void {
185+
// To Do
186+
}
187+
188+
export function handleThawRequestsFulfilled(event: ThawRequestsFulfilled): void {
189+
// To Do
190+
}
191+
192+
export function handleThawingPeriodCleared(event: ThawingPeriodCleared): void {
193+
// To Do
78194
}

subgraph.template.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,28 @@ dataSources:
405405
handler: handleHorizonStakeLocked
406406
- event: HorizonStakeWithdrawn(indexed address,uint256)
407407
handler: handleHorizonStakeWithdrawn
408+
- event: ProvisionCreated(indexed address,indexed address,uint256,uint32,uint64)
409+
handler: handleProvisionCreated
410+
- event: ProvisionIncreased(indexed address,indexed address,uint256)
411+
handler: handleProvisionIncreased
412+
- event: TokensDeprovisioned(indexed address,indexed address,uint256)
413+
handler: handleTokensDeprovisioned
414+
- event: ProvisionParametersSet(indexed address,indexed address,uint32,uint64)
415+
handler: handleProvisionParametersSet
416+
- event: ProvisionParametersStaged(indexed address,indexed address,uint32,uint64)
417+
handler: handleProvisionParametersStaged
418+
- event: ProvisionSlashed(indexed address,indexed address,uint256)
419+
handler: handleProvisionSlashed
420+
- event: ProvisionThawed(indexed address,indexed address,uint256)
421+
handler: handleProvisionThawed
422+
- event: ThawRequestCreated(indexed address,indexed address,indexed address,uint256,uint64,bytes32)
423+
handler: handleThawRequestCreated
424+
- event: ThawRequestFulfilled(indexed bytes32,uint256,uint256,uint64,bool)
425+
handler: handleThawRequestFulfilled
426+
- event: ThawRequestsFulfilled(indexed address,indexed address,indexed address,uint256,uint256,uint8)
427+
handler: handleThawRequestsFulfilled
428+
- event: ThawingPeriodCleared()
429+
handler: handleThawingPeriodCleared
408430
- kind: ethereum/contract
409431
name: Curation
410432
network: {{network}}

0 commit comments

Comments
 (0)