@@ -11,10 +11,14 @@ import "./ICuration.sol";
11
11
/**
12
12
* @title Curation contract
13
13
* @dev Allows curators to signal on subgraph deployments that might be relevant to indexers by
14
- * staking Graph Tokens. Additionally, curators earn fees from the Query Market related to the
14
+ * staking Graph Tokens (GRT) . Additionally, curators earn fees from the Query Market related to the
15
15
* subgraph deployment they curate.
16
16
* A curators stake goes to a curation pool along with the stakes of other curators,
17
- * only one pool exists for each subgraph deployment.
17
+ * only one such pool exists for each subgraph deployment.
18
+ * The contract mints Graph Signal Tokens (GST) according to a bonding curve for each individual
19
+ * curation pool where GRT is deposited.
20
+ * Holders can burn GST tokens using this contract to get GRT tokens back according to the
21
+ * bonding curve.
18
22
*/
19
23
contract Curation is CurationV1Storage , ICuration , Governed {
20
24
using SafeMath for uint256 ;
@@ -204,19 +208,18 @@ contract Curation is CurationV1Storage, ICuration, Governed {
204
208
*/
205
209
function burn (bytes32 _subgraphDeploymentID , uint256 _signal ) external override {
206
210
address curator = msg .sender ;
207
- CurationPool storage curationPool = pools[_subgraphDeploymentID];
208
211
209
212
require (_signal > 0 , "Cannot burn zero signal " );
210
213
require (
211
- curationPool.curatorSignal[ curator] >= _signal,
214
+ getCuratorSignal ( curator, _subgraphDeploymentID) >= _signal,
212
215
"Cannot burn more signal than you own "
213
216
);
214
217
215
218
// Update balance and get the amount of tokens to refund based on returned signal
216
219
uint256 tokens = _burnSignal (curator, _subgraphDeploymentID, _signal);
217
220
218
221
// If all signal burnt delete the curation pool
219
- if (curationPool.signal == 0 ) {
222
+ if (getCurationPoolSignal (_subgraphDeploymentID) == 0 ) {
220
223
delete pools[_subgraphDeploymentID];
221
224
}
222
225
@@ -238,31 +241,43 @@ contract Curation is CurationV1Storage, ICuration, Governed {
238
241
* @param _subgraphDeploymentID SubgraphDeployment to check if curated
239
242
* @return True if curated
240
243
*/
241
- function isCurated (bytes32 _subgraphDeploymentID ) external override view returns (bool ) {
242
- return _isCurated ( _subgraphDeploymentID) ;
244
+ function isCurated (bytes32 _subgraphDeploymentID ) public override view returns (bool ) {
245
+ return pools[ _subgraphDeploymentID].tokens > 0 ;
243
246
}
244
247
245
248
/**
246
- * @dev Check if any Graph tokens are staked for a SubgraphDeployment.
247
- * @param _subgraphDeploymentID SubgraphDeployment to check if curated
248
- * @return True if curated
249
+ * @dev Get the amount of signal a curator has in a curation pool.
250
+ * @param _curator Curator owning the signal tokens
251
+ * @param _subgraphDeploymentID Subgraph deployment curation pool
252
+ * @return Amount of signal owned by a curator for the subgraph deployment
249
253
*/
250
- function _isCurated (bytes32 _subgraphDeploymentID ) private view returns (bool ) {
251
- return pools[_subgraphDeploymentID].tokens > 0 ;
254
+ function getCuratorSignal (address _curator , bytes32 _subgraphDeploymentID )
255
+ public
256
+ override
257
+ view
258
+ returns (uint256 )
259
+ {
260
+ if (address (pools[_subgraphDeploymentID].gst) == address (0 )) {
261
+ return 0 ;
262
+ }
263
+ return pools[_subgraphDeploymentID].gst.balanceOf (_curator);
252
264
}
253
265
254
266
/**
255
- * @dev Get the amount of signal a curator has on a curation pool.
256
- * @param _curator Curator owning signal
257
- * @param _subgraphDeploymentID SubgraphDeployment of issued signal
258
- * @return Amount of signal owned by a curator for the SubgraphDeployment
267
+ * @dev Get the amount of signal in a curation pool.
268
+ * @param _subgraphDeploymentID Subgraph deployment curation poool
269
+ * @return Amount of signal owned by a curator for the subgraph deployment
259
270
*/
260
- function getCuratorSignal ( address _curator , bytes32 _subgraphDeploymentID )
271
+ function getCurationPoolSignal ( bytes32 _subgraphDeploymentID )
261
272
public
273
+ override
262
274
view
263
275
returns (uint256 )
264
276
{
265
- return pools[_subgraphDeploymentID].curatorSignal[_curator];
277
+ if (address (pools[_subgraphDeploymentID].gst) == address (0 )) {
278
+ return 0 ;
279
+ }
280
+ return pools[_subgraphDeploymentID].gst.totalSupply ();
266
281
}
267
282
268
283
/**
@@ -273,30 +288,28 @@ contract Curation is CurationV1Storage, ICuration, Governed {
273
288
*/
274
289
function tokensToSignal (bytes32 _subgraphDeploymentID , uint256 _tokens )
275
290
public
291
+ override
276
292
view
277
293
returns (uint256 )
278
294
{
279
- // Handle initialization of bonding curve
280
- uint256 tokens = _tokens;
281
- uint256 signal = 0 ;
295
+ // Get current tokens and signal
282
296
CurationPool memory curationPool = pools[_subgraphDeploymentID];
297
+ uint256 newTokens = _tokens;
298
+ uint256 curTokens = curationPool.tokens;
299
+ uint256 curSignal = getCurationPoolSignal (_subgraphDeploymentID);
300
+ uint32 reserveRatio = curationPool.reserveRatio;
301
+
302
+ // Init curation pool
283
303
if (curationPool.tokens == 0 ) {
284
- curationPool = CurationPool (
285
- minimumCurationStake,
286
- SIGNAL_PER_MINIMUM_STAKE,
287
- defaultReserveRatio
288
- );
289
- tokens = tokens.sub (curationPool.tokens);
290
- signal = curationPool.signal;
304
+ newTokens = newTokens.sub (minimumCurationStake);
305
+ curTokens = minimumCurationStake;
306
+ curSignal = SIGNAL_PER_MINIMUM_STAKE;
307
+ reserveRatio = defaultReserveRatio;
291
308
}
292
309
293
- return
294
- calculatePurchaseReturn (
295
- curationPool.signal,
296
- curationPool.tokens,
297
- uint32 (curationPool.reserveRatio),
298
- tokens
299
- ) + signal;
310
+ // Calculate new signal
311
+ uint256 newSignal = calculatePurchaseReturn (curSignal, curTokens, reserveRatio, newTokens);
312
+ return newSignal.add (curSignal);
300
313
}
301
314
302
315
/**
@@ -307,21 +320,23 @@ contract Curation is CurationV1Storage, ICuration, Governed {
307
320
*/
308
321
function signalToTokens (bytes32 _subgraphDeploymentID , uint256 _signal )
309
322
public
323
+ override
310
324
view
311
325
returns (uint256 )
312
326
{
313
327
CurationPool memory curationPool = pools[_subgraphDeploymentID];
328
+ uint256 curationPoolSignal = getCurationPoolSignal (_subgraphDeploymentID);
314
329
require (
315
330
curationPool.tokens > 0 ,
316
331
"Subgraph deployment must be curated to perform calculations "
317
332
);
318
333
require (
319
- curationPool.signal >= _signal,
334
+ curationPoolSignal >= _signal,
320
335
"Signal must be above or equal to signal issued in the curation pool "
321
336
);
322
337
return
323
338
calculateSaleReturn (
324
- curationPool.signal ,
339
+ curationPoolSignal ,
325
340
curationPool.tokens,
326
341
uint32 (curationPool.reserveRatio),
327
342
_signal
@@ -332,8 +347,8 @@ contract Curation is CurationV1Storage, ICuration, Governed {
332
347
* @dev Update balances after mint of signal and deposit of tokens.
333
348
* @param _curator Curator address
334
349
* @param _subgraphDeploymentID Subgraph deployment from where to mint signal
335
- * @param _tokens Amount of tokens
336
- * @return Amount of signal bought
350
+ * @param _tokens Amount of tokens to deposit
351
+ * @return Amount of signal minted
337
352
*/
338
353
function _mintSignal (
339
354
address _curator ,
@@ -343,12 +358,11 @@ contract Curation is CurationV1Storage, ICuration, Governed {
343
358
CurationPool storage curationPool = pools[_subgraphDeploymentID];
344
359
uint256 signal = tokensToSignal (_subgraphDeploymentID, _tokens);
345
360
346
- // Update tokens
361
+ // Update GRT tokens held as reserves
347
362
curationPool.tokens = curationPool.tokens.add (_tokens);
348
363
349
- // Update signal
350
- curationPool.signal = curationPool.signal.add (signal);
351
- curationPool.curatorSignal[_curator] = curationPool.curatorSignal[_curator].add (signal);
364
+ // Mint signal to the curator
365
+ curationPool.gst.mint (_curator, signal);
352
366
353
367
return signal;
354
368
}
@@ -357,7 +371,7 @@ contract Curation is CurationV1Storage, ICuration, Governed {
357
371
* @dev Update balances after burn of signal and return of tokens.
358
372
* @param _curator Curator address
359
373
* @param _subgraphDeploymentID Subgraph deployment pool to burn signal
360
- * @param _signal Amount of signal
374
+ * @param _signal Amount of signal to burn
361
375
* @return Number of tokens received
362
376
*/
363
377
function _burnSignal (
@@ -368,12 +382,11 @@ contract Curation is CurationV1Storage, ICuration, Governed {
368
382
CurationPool storage curationPool = pools[_subgraphDeploymentID];
369
383
uint256 tokens = signalToTokens (_subgraphDeploymentID, _signal);
370
384
371
- // Update tokens
385
+ // Update GRT tokens held as reserves
372
386
curationPool.tokens = curationPool.tokens.sub (tokens);
373
387
374
- // Update signal
375
- curationPool.signal = curationPool.signal.sub (_signal);
376
- curationPool.curatorSignal[_curator] = curationPool.curatorSignal[_curator].sub (_signal);
388
+ // Burn signal from curator
389
+ curationPool.gst.burnFrom (_curator, _signal);
377
390
378
391
return tokens;
379
392
}
@@ -385,7 +398,7 @@ contract Curation is CurationV1Storage, ICuration, Governed {
385
398
*/
386
399
function _collect (bytes32 _subgraphDeploymentID , uint256 _tokens ) private {
387
400
require (
388
- _isCurated (_subgraphDeploymentID),
401
+ isCurated (_subgraphDeploymentID),
389
402
"Subgraph deployment must be curated to collect fees "
390
403
);
391
404
@@ -410,11 +423,17 @@ contract Curation is CurationV1Storage, ICuration, Governed {
410
423
CurationPool storage curationPool = pools[_subgraphDeploymentID];
411
424
412
425
// If it hasn't been curated before then initialize the curve
413
- if (! _isCurated (_subgraphDeploymentID)) {
426
+ if (! isCurated (_subgraphDeploymentID)) {
414
427
require (_tokens >= minimumCurationStake, "Curation stake is below minimum required " );
415
428
416
429
// Initialize
417
430
curationPool.reserveRatio = defaultReserveRatio;
431
+
432
+ // If no signal token for the pool - create one
433
+ if (address (curationPool.gst) == address (0 )) {
434
+ string memory symbol = string (abi.encodePacked ("GST- " , _subgraphDeploymentID));
435
+ curationPool.gst = new GraphSignalToken (symbol, address (this ));
436
+ }
418
437
}
419
438
420
439
// Update balances
0 commit comments