Skip to content

Commit d811ba5

Browse files
committed
feat: integrate IssuanceAllocator into RewardsManager
- Fix syntax errors in RewardsManager.sol (missing closing braces) - Add missing IRewardsIssuer import - Complete MockIssuanceAllocator implementation with all required methods - Update interface declarations and parameter names for consistency - Fix interface support tests for IRewardsManager All IssuanceAllocator integration tests now passing (9/9) Contract compilation successful with proper ERC165 interface support
1 parent 01b12fe commit d811ba5

File tree

9 files changed

+954
-15
lines changed

9 files changed

+954
-15
lines changed

packages/contracts/contracts/rewards/RewardsManager.sol

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@ pragma abicoder v2;
77
// solhint-disable gas-increment-by-one, gas-indexed-events, gas-small-strings, gas-strict-inequalities
88

99
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
10+
import { ERC165 } from "@openzeppelin/contracts/introspection/ERC165.sol";
1011
import { IERC165 } from "@openzeppelin/contracts/introspection/IERC165.sol";
1112

1213
import { GraphUpgradeable } from "../upgrades/GraphUpgradeable.sol";
1314
import { Managed } from "../governance/Managed.sol";
1415
import { MathUtils } from "../staking/libs/MathUtils.sol";
1516
import { IGraphToken } from "../token/IGraphToken.sol";
1617

17-
import { RewardsManagerV6Storage } from "./RewardsManagerStorage.sol";
18-
import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol";
18+
import { RewardsManagerV7Storage } from "./RewardsManagerStorage.sol";
1919
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";
2023
import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityOracle.sol";
2124

2225
/**
@@ -29,6 +32,10 @@ import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/i
2932
* total rewards for the Subgraph are split up for each Indexer based on much they have Staked on
3033
* that Subgraph.
3134
*
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+
*
3239
* Note:
3340
* The contract provides getter functions to query the state of accrued rewards:
3441
* - getAccRewardsPerSignal
@@ -39,7 +46,7 @@ import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/i
3946
* until the actual takeRewards function is called.
4047
* custom:security-contact Please email security+contracts@ thegraph.com (remove space) if you find any bugs. We might have an active bug bounty program.
4148
*/
42-
contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsManager {
49+
contract RewardsManager is RewardsManagerV7Storage, GraphUpgradeable, ERC165, IRewardsManager, IIssuanceTarget {
4350
using SafeMath for uint256;
4451

4552
/// @dev Fixed point scaling factor used for decimals in reward calculations
@@ -85,6 +92,13 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
8592
*/
8693
event SubgraphServiceSet(address indexed oldSubgraphService, address indexed newSubgraphService);
8794

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+
88102
/**
89103
* @notice Emitted when the rewards eligibility oracle contract is set
90104
* @param oldRewardsEligibilityOracle Previous rewards eligibility oracle address
@@ -117,7 +131,10 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
117131

118132
/**
119133
* @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.
121138
* Whenever this function is called in layer 2, the updateL2MintAllowance function
122139
* _must_ be called on the L1GraphTokenGateway in L1, to ensure the bridge can mint the
123140
* right amount of tokens.
@@ -171,6 +188,52 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
171188
emit SubgraphServiceSet(oldSubgraphService, _subgraphService);
172189
}
173190

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+
174237
/**
175238
* @inheritdoc IRewardsManager
176239
* @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
193256
}
194257
}
195258

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+
196270
// -- Denylist --
197271

198272
/**
@@ -221,6 +295,17 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
221295

222296
// -- Getters --
223297

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+
224309
/**
225310
* @inheritdoc IRewardsManager
226311
* @dev Linear formula: `x = r * t`
@@ -238,8 +323,10 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
238323
if (t == 0) {
239324
return 0;
240325
}
241-
// ...or if issuance is zero
242-
if (issuancePerBlock == 0) {
326+
327+
uint256 rewardsIssuancePerBlock = getRewardsIssuancePerBlock();
328+
329+
if (rewardsIssuancePerBlock == 0) {
243330
return 0;
244331
}
245332

@@ -250,7 +337,7 @@ contract RewardsManager is RewardsManagerV6Storage, GraphUpgradeable, IRewardsMa
250337
return 0;
251338
}
252339

253-
uint256 x = issuancePerBlock.mul(t);
340+
uint256 x = rewardsIssuancePerBlock.mul(t);
254341

255342
// Get the new issuance per signalled token
256343
// We multiply the decimals to keep the precision as fixed-point number

packages/contracts/contracts/rewards/RewardsManagerStorage.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
pragma solidity ^0.7.6 || 0.8.27;
99

10+
import { IIssuanceAllocator } from "@graphprotocol/interfaces/contracts/issuance/allocate/IIssuanceAllocator.sol";
1011
import { IRewardsEligibilityOracle } from "@graphprotocol/interfaces/contracts/issuance/eligibility/IRewardsEligibilityOracle.sol";
1112
import { IRewardsIssuer } from "./IRewardsIssuer.sol";
1213
import { IRewardsManager } from "@graphprotocol/interfaces/contracts/contracts/rewards/IRewardsManager.sol";
@@ -64,6 +65,7 @@ contract RewardsManagerV3Storage is RewardsManagerV2Storage {
6465
*/
6566
contract RewardsManagerV4Storage is RewardsManagerV3Storage {
6667
/// @notice GRT issued for indexer rewards per block
68+
/// @dev Only used when issuanceAllocator is zero address.
6769
uint256 public issuancePerBlock;
6870
}
6971

@@ -86,3 +88,13 @@ contract RewardsManagerV6Storage is RewardsManagerV5Storage {
8688
/// @notice Address of the rewards eligibility oracle contract
8789
IRewardsEligibilityOracle public rewardsEligibilityOracle;
8890
}
91+
92+
/**
93+
* @title RewardsManagerV7Storage
94+
* @author Edge & Node
95+
* @notice Storage layout for RewardsManager V7
96+
*/
97+
contract RewardsManagerV7Storage is RewardsManagerV6Storage {
98+
/// @notice Address of the issuance allocator
99+
IIssuanceAllocator public issuanceAllocator;
100+
}

0 commit comments

Comments
 (0)