Skip to content

Commit ee7950e

Browse files
committed
rewards: implement a rewards contract that assigns GRT tokens to indexer based on participation (allocations) and subgraph popularity (curation)
1 parent 57c2d63 commit ee7950e

23 files changed

+871
-153
lines changed

contracts/curation/Curation.sol

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
114114
emit ParameterUpdated("staking");
115115
}
116116

117+
/**
118+
* @dev Set the rewards manager contract.
119+
* @param _rewardsManager Address of the rewards manager contract
120+
*/
121+
function setRewardsManager(address _rewardsManager) external override onlyGovernor {
122+
rewardsManager = IRewardsManager(_rewardsManager);
123+
emit ParameterUpdated("rewardsManager");
124+
}
125+
117126
/**
118127
* @dev Set the default reserve ratio percentage for a curation pool.
119128
* @notice Update the default reserver ratio to `_defaultReserveRatio`
@@ -224,6 +233,9 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
224233
"Cannot burn more signal than you own"
225234
);
226235

236+
// Trigger update rewards calculation
237+
_updateRewards(_subgraphDeploymentID);
238+
227239
// Update balance and get the amount of tokens to refund based on returned signal
228240
(uint256 tokens, uint256 withdrawalFees) = _burnSignal(
229241
curator,
@@ -278,7 +290,7 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
278290
/**
279291
* @dev Get the amount of signal in a curation pool.
280292
* @param _subgraphDeploymentID Subgraph deployment curation poool
281-
* @return Amount of signal owned by a curator for the subgraph deployment
293+
* @return Amount of signal minted for the subgraph deployment
282294
*/
283295
function getCurationPoolSignal(bytes32 _subgraphDeploymentID)
284296
public
@@ -292,6 +304,20 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
292304
return pools[_subgraphDeploymentID].gst.totalSupply();
293305
}
294306

307+
/**
308+
* @dev Get the amount of token reserves in a curation pool.
309+
* @param _subgraphDeploymentID Subgraph deployment curation poool
310+
* @return Amount of token reserves in the curation pool
311+
*/
312+
function getCurationPoolTokens(bytes32 _subgraphDeploymentID)
313+
public
314+
override
315+
view
316+
returns (uint256)
317+
{
318+
return pools[_subgraphDeploymentID].tokens;
319+
}
320+
295321
/**
296322
* @dev Calculate amount of signal that can be bought with tokens in a curation pool.
297323
* @param _subgraphDeploymentID Subgraph deployment to mint signal
@@ -374,15 +400,18 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
374400
bytes32 _subgraphDeploymentID,
375401
uint256 _tokens
376402
) private returns (uint256) {
377-
CurationPool storage curationPool = pools[_subgraphDeploymentID];
378403
uint256 signal = tokensToSignal(_subgraphDeploymentID, _tokens);
379404

405+
// Update curation pool
406+
CurationPool storage curationPool = pools[_subgraphDeploymentID];
380407
// Update GRT tokens held as reserves
381408
curationPool.tokens = curationPool.tokens.add(_tokens);
382-
383409
// Mint signal to the curator
384410
curationPool.gst.mint(_curator, signal);
385411

412+
// Update the global reserve
413+
totalTokens = totalTokens.add(_tokens);
414+
386415
return signal;
387416
}
388417

@@ -398,15 +427,19 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
398427
bytes32 _subgraphDeploymentID,
399428
uint256 _signal
400429
) private returns (uint256, uint256) {
401-
CurationPool storage curationPool = pools[_subgraphDeploymentID];
402430
(uint256 tokens, uint256 withdrawalFees) = signalToTokens(_subgraphDeploymentID, _signal);
431+
uint256 outTokens = tokens.add(withdrawalFees);
403432

433+
// Update curation pool
434+
CurationPool storage curationPool = pools[_subgraphDeploymentID];
404435
// Update GRT tokens held as reserves
405-
curationPool.tokens = curationPool.tokens.sub(tokens.add(withdrawalFees));
406-
436+
curationPool.tokens = curationPool.tokens.sub(outTokens);
407437
// Burn signal from curator
408438
curationPool.gst.burnFrom(_curator, _signal);
409439

440+
// Update the global reserve
441+
totalTokens = totalTokens.sub(outTokens);
442+
410443
return (tokens, withdrawalFees);
411444
}
412445

@@ -458,10 +491,24 @@ contract Curation is CurationV1Storage, GraphUpgradeable, ICuration, Governed {
458491
}
459492
}
460493

461-
// Update balances
494+
// Trigger update rewards calculation
495+
_updateRewards(_subgraphDeploymentID);
496+
497+
// Exchange GRT tokens for GST of the subgraph pool
462498
uint256 signal = _mintSignal(_curator, _subgraphDeploymentID, _tokens);
463499

464500
emit Signalled(_curator, _subgraphDeploymentID, _tokens, signal);
465501
return signal;
466502
}
503+
504+
/**
505+
* @dev Triggers an update of rewards due to a change in signal.
506+
* @param _subgraphDeploymentID Subgrapy deployment updated
507+
*/
508+
function _updateRewards(bytes32 _subgraphDeploymentID) internal returns (uint256) {
509+
if (address(rewardsManager) != address(0)) {
510+
return rewardsManager.onSubgraphSignalUpdate(_subgraphDeploymentID);
511+
}
512+
return 0;
513+
}
467514
}
Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,37 @@
11
pragma solidity ^0.6.4;
22

33
import "../bancor/BancorFormula.sol";
4+
import "../rewards/IRewardsManager.sol";
45
import "../staking/IStaking.sol";
56
import "../token/IGraphToken.sol";
67

7-
import "./GraphSignalToken.sol";
8+
import "./ICuration.sol";
89

910
contract CurationV1Storage is BancorFormula {
10-
// -- Pool --
11-
12-
struct CurationPool {
13-
uint256 tokens; // GRT Tokens stored as reserves for the subgraph deployment
14-
uint32 reserveRatio; // Ratio for the bonding curve
15-
GraphSignalToken gst; // Signal token contract for this curation pool
16-
}
17-
1811
// -- State --
1912

20-
// Fee charged when curator withdraw deposit
13+
// Fee charged when curator withdraw a deposit
2114
// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
2215
uint32 public withdrawalFeePercentage;
2316

2417
// Default reserve ratio to configure curator shares bonding curve
2518
// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
2619
uint32 public defaultReserveRatio;
2720

28-
// Minimum amount allowed to be deposit by curators
21+
// Minimum amount allowed to be deposited by curators to initialize a pool
2922
// This is the `startPoolBalance` for the bonding curve
3023
uint256 public minimumCurationDeposit;
3124

25+
// Total tokens in held as reserves received from curators deposits
26+
uint256 public totalTokens;
27+
3228
// Mapping of subgraphDeploymentID => CurationPool
3329
// There is only one CurationPool per SubgraphDeploymentID
34-
mapping(bytes32 => CurationPool) public pools;
30+
mapping(bytes32 => ICuration.CurationPool) public pools;
3531

3632
// -- Related contracts --
3733

38-
// Address of the staking contract that will distribute fees to reserves
39-
IStaking public staking;
40-
41-
// Token used for staking
4234
IGraphToken public token;
35+
IStaking public staking;
36+
IRewardsManager public rewardsManager;
4337
}

contracts/curation/ICuration.sol

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
pragma solidity ^0.6.4;
22

3+
import "./GraphSignalToken.sol";
4+
35
interface ICuration {
4-
// -- Configuration --
6+
// -- Pool --
57

6-
function setDefaultReserveRatio(uint32 _defaultReserveRatio) external;
8+
struct CurationPool {
9+
uint256 tokens; // GRT Tokens stored as reserves for the subgraph deployment
10+
uint32 reserveRatio; // Ratio for the bonding curve
11+
GraphSignalToken gst; // Signal token contract for this curation pool
12+
}
13+
14+
// -- Configuration --
715

816
function setStaking(address _staking) external;
917

18+
function setRewardsManager(address _rewardsManager) external;
19+
20+
function setDefaultReserveRatio(uint32 _defaultReserveRatio) external;
21+
1022
function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external;
1123

1224
function setWithdrawalFeePercentage(uint32 _percentage) external;
@@ -32,6 +44,8 @@ interface ICuration {
3244

3345
function getCurationPoolSignal(bytes32 _subgraphDeploymentID) external view returns (uint256);
3446

47+
function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view returns (uint256);
48+
3549
function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokens)
3650
external
3751
view

contracts/discovery/ServiceRegistry.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
pragma solidity ^0.6.4;
22
pragma experimental ABIEncoderV2;
33

4-
54
/**
65
* @title ServiceRegistry contract
76
* @dev This contract supports the service discovery process by allowing indexers to

contracts/epochs/EpochManager.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import "./IEpochManager.sol";
1111

1212
/**
1313
* @title EpochManager contract
14-
* @dev Tracks epochs based on its block duration to sync contracts in the protocol.
14+
* @dev Produce epochs based on a number of blocks to coordinate contracts in the protocol.
1515
*/
1616
contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager, Governed {
1717
using SafeMath for uint256;

contracts/rewards/IRewardsManager.sol

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
pragma solidity ^0.6.4;
2+
3+
interface IRewardsManager {
4+
// -- Params --
5+
6+
function setIssuanceRate(uint256 _issuanceRate) external;
7+
8+
// -- Denylist --
9+
10+
function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external;
11+
12+
function isDenied(bytes32 _subgraphDeploymentID) external returns (bool);
13+
14+
// -- Getters --
15+
16+
function getNewRewardsPerSignal() external view returns (uint256);
17+
18+
function getAccRewardsPerSignal() external view returns (uint256);
19+
20+
function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID)
21+
external
22+
view
23+
returns (uint256);
24+
25+
function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID)
26+
external
27+
view
28+
returns (uint256, uint256);
29+
30+
function getRewards(address _allocationID) external view returns (uint256);
31+
32+
// -- Updates --
33+
34+
function updateAccRewardsPerSignal() external returns (uint256);
35+
36+
function assignRewards(address _allocationID) external returns (uint256);
37+
38+
function claim(bool _restake) external returns (uint256);
39+
40+
// -- Hooks --
41+
42+
function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external returns (uint256);
43+
44+
function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) external returns (uint256);
45+
}

0 commit comments

Comments
 (0)