@@ -7,16 +7,19 @@ pragma abicoder v2;
7
7
// solhint-disable gas-increment-by-one, gas-indexed-events, gas-small-strings, gas-strict-inequalities
8
8
9
9
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol " ;
10
+ import { ERC165 } from "@openzeppelin/contracts/introspection/ERC165.sol " ;
10
11
import { IERC165 } from "@openzeppelin/contracts/introspection/IERC165.sol " ;
11
12
12
13
import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol " ;
13
14
import { Managed } from "../governance/Managed.sol " ;
14
15
import { MathUtils } from "../staking/libs/MathUtils.sol " ;
15
16
import { IGraphToken } from "../token/IGraphToken.sol " ;
16
17
17
- import { RewardsManagerV6Storage } from "./RewardsManagerStorage.sol " ;
18
- import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol " ;
18
+ import { RewardsManagerV7Storage } from "./RewardsManagerStorage.sol " ;
19
19
import { IRewardsIssuer } from "./IRewardsIssuer.sol " ;
20
+ import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol " ;
21
+ import { IIssuanceAllocator } from "@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocator.sol " ;
22
+ import { IIssuanceTarget } from "@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceTarget.sol " ;
20
23
import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityOracle.sol " ;
21
24
22
25
/**
@@ -29,6 +32,10 @@ import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/i
29
32
* total rewards for the Subgraph are split up for each Indexer based on much they have Staked on
30
33
* that Subgraph.
31
34
*
35
+ * @dev If an `issuanceAllocator` is set, it is used to determine the amount of GRT to be issued per block.
36
+ * Otherwise, the `issuancePerBlock` variable is used. In relation to the IssuanceAllocator, this contract
37
+ * is a self-minting target responsible for directly minting allocated GRT.
38
+ *
32
39
* Note:
33
40
* The contract provides getter functions to query the state of accrued rewards:
34
41
* - getAccRewardsPerSignal
@@ -39,7 +46,7 @@ import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/i
39
46
* until the actual takeRewards function is called.
40
47
* custom:security-contact Please email security+contracts@ thegraph.com (remove space) if you find any bugs. We might have an active bug bounty program.
41
48
*/
42
- contract RewardsManager is RewardsManagerV6Storage , GraphUpgradeable , IRewardsManager {
49
+ contract RewardsManager is RewardsManagerV7Storage , GraphUpgradeable , ERC165 , IRewardsManager , IIssuanceTarget {
43
50
using SafeMath for uint256 ;
44
51
45
52
/// @dev Fixed point scaling factor used for decimals in reward calculations
@@ -85,6 +92,13 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
85
92
*/
86
93
event SubgraphServiceSet (address indexed oldSubgraphService , address indexed newSubgraphService );
87
94
95
+ /**
96
+ * @notice Emitted when the issuance allocator is set
97
+ * @param oldIssuanceAllocator Previous issuance allocator address
98
+ * @param newIssuanceAllocator New issuance allocator address
99
+ */
100
+ event IssuanceAllocatorSet (address indexed oldIssuanceAllocator , address indexed newIssuanceAllocator );
101
+
88
102
/**
89
103
* @notice Emitted when the rewards eligibility oracle contract is set
90
104
* @param oldRewardsEligibilityOracle Previous rewards eligibility oracle address
@@ -117,7 +131,10 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
117
131
118
132
/**
119
133
* @inheritdoc IRewardsManager
120
- * @dev The issuance is defined as a fixed amount of rewards per block in GRT.
134
+ * @dev When an IssuanceAllocator is set, the effective issuance will be determined by the allocator,
135
+ * but this local value can still be updated for cases when the allocator is later removed.
136
+ *
137
+ * The issuance is defined as a fixed amount of rewards per block in GRT.
121
138
* Whenever this function is called in layer 2, the updateL2MintAllowance function
122
139
* _must_ be called on the L1GraphTokenGateway in L1, to ensure the bridge can mint the
123
140
* right amount of tokens.
@@ -171,6 +188,52 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
171
188
emit SubgraphServiceSet (oldSubgraphService, _subgraphService);
172
189
}
173
190
191
+ /**
192
+ * @inheritdoc IIssuanceTarget
193
+ * @dev This function facilitates upgrades by providing a standard way for targets
194
+ * to change their allocator. Only the governor can call this function.
195
+ * Note that the IssuanceAllocator can be set to the zero address to disable use of an allocator, and
196
+ * use the local `issuancePerBlock` variable instead to control issuance.
197
+ */
198
+ function setIssuanceAllocator (address newIssuanceAllocator ) external override onlyGovernor {
199
+ if (address (issuanceAllocator) != newIssuanceAllocator) {
200
+ // Update rewards calculation before changing the issuance allocator
201
+ updateAccRewardsPerSignal ();
202
+
203
+ // Check that the contract supports the IIssuanceAllocator interface
204
+ // Allow zero address to disable the allocator
205
+ if (newIssuanceAllocator != address (0 )) {
206
+ require (
207
+ IERC165 (newIssuanceAllocator).supportsInterface (type (IIssuanceAllocator).interfaceId),
208
+ "Contract does not support IIssuanceAllocator interface "
209
+ );
210
+ }
211
+
212
+ address oldIssuanceAllocator = address (issuanceAllocator);
213
+ issuanceAllocator = IIssuanceAllocator (newIssuanceAllocator);
214
+ emit IssuanceAllocatorSet (oldIssuanceAllocator, newIssuanceAllocator);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * @inheritdoc IIssuanceTarget
220
+ * @dev Ensures that all reward calculations are up-to-date with the current block
221
+ * before any allocation changes take effect.
222
+ *
223
+ * The IssuanceAllocator calls this function before changing a target's allocation to ensure
224
+ * all issuance is properly accounted for with the current issuance rate before applying an
225
+ * issuance allocation change.
226
+ *
227
+ * Only the IssuanceAllocator can call this function to ensure proper access control
228
+ * for any future changes that might require this level of restriction.
229
+ */
230
+ function beforeIssuanceAllocationChange () external override {
231
+ require (msg .sender == address (issuanceAllocator), "Caller must be IssuanceAllocator " );
232
+
233
+ // Update rewards calculation with the current issuance rate
234
+ updateAccRewardsPerSignal ();
235
+ }
236
+
174
237
/**
175
238
* @inheritdoc IRewardsManager
176
239
* @dev Note that the rewards eligibility oracle can be set to the zero address to disable use of an oracle, in
@@ -193,6 +256,17 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
193
256
}
194
257
}
195
258
259
+ /**
260
+ * @inheritdoc ERC165
261
+ */
262
+ function supportsInterface (bytes4 interfaceId ) public view virtual override returns (bool ) {
263
+ return
264
+ interfaceId == type (IIssuanceTarget).interfaceId ||
265
+ interfaceId == type (IRewardsManager).interfaceId ||
266
+ interfaceId == type (IERC165 ).interfaceId ||
267
+ super .supportsInterface (interfaceId);
268
+ }
269
+
196
270
// -- Denylist --
197
271
198
272
/**
@@ -221,6 +295,17 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
221
295
222
296
// -- Getters --
223
297
298
+ /**
299
+ * @inheritdoc IRewardsManager
300
+ * @dev Gets the effective issuance per block, taking into account the IssuanceAllocator if set
301
+ */
302
+ function getRewardsIssuancePerBlock () public view override returns (uint256 ) {
303
+ if (address (issuanceAllocator) != address (0 )) {
304
+ return issuanceAllocator.getTargetIssuancePerBlock (address (this )).selfIssuancePerBlock;
305
+ }
306
+ return issuancePerBlock;
307
+ }
308
+
224
309
/**
225
310
* @inheritdoc IRewardsManager
226
311
* @dev Linear formula: `x = r * t`
@@ -238,8 +323,10 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
238
323
if (t == 0 ) {
239
324
return 0 ;
240
325
}
241
- // ...or if issuance is zero
242
- if (issuancePerBlock == 0 ) {
326
+
327
+ uint256 rewardsIssuancePerBlock = getRewardsIssuancePerBlock ();
328
+
329
+ if (rewardsIssuancePerBlock == 0 ) {
243
330
return 0 ;
244
331
}
245
332
@@ -250,7 +337,7 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
250
337
return 0 ;
251
338
}
252
339
253
- uint256 x = issuancePerBlock .mul (t);
340
+ uint256 x = rewardsIssuancePerBlock .mul (t);
254
341
255
342
// Get the new issuance per signalled token
256
343
// We multiply the decimals to keep the precision as fixed-point number
0 commit comments