You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/core/RewardsCoordinator.md
+82-20Lines changed: 82 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@
7
7
8
8
<!-- The primary functions of the `RewardsCoordinator` contract are to (i) accept ERC20 rewards from AVSs (Actively Validated Services) to their Operators and delegated Stakers for a given time range; (ii) enable the protocol to provide ERC20 tokens to all stakers over a specified time range; and (iii) allow stakers and operators to claim their accumulated earnings. -->
9
9
10
-
The `RewardsCoordinator` accepts ERC20s from AVSs alongside rewards submission requests made out to Operators who, during a specified time range, were registered to the AVS in the core [`AVSDirectory`](./AVSDirectory.md) contract.
10
+
The `RewardsCoordinator` accepts ERC20s from AVSs alongside rewards submission requests made out to Operators who, during a specified time range, were registered to the AVS in the core [`AllocationManager`](./AllocationManager.md) contract.
11
11
12
12
There are two forms of rewards:
13
13
* Rewards v1, also known as rewards submissions.
@@ -46,21 +46,25 @@ This document is organized according to the following themes (click each to be t
46
46
* Mapping for earners(Stakers/Operators) to track their total claimed earnings per reward token. This mapping is used to calculate the difference between the cumulativeEarnings stored in the merkle tree and the previous total claimed amount. This difference is then transfered to the specified destination address.
47
47
*`uint16 public defaultOperatorSplitBips`: *Used off-chain* by the rewards updater to calculate an Operator's split for a specific reward.
48
48
* This is expected to be a flat 10% rate for the initial rewards release. Expressed in basis points, this is `1000`.
* Operators specify their custom split for a given AVS for each `OperatorDirectedRewardsSubmission`, where Stakers receive a relative proportion (by stake weight) of the remaining amount.
* Operators may also specify their custom split for [programmatic incentives](https://www.blog.eigenlayer.xyz/introducing-programmatic-incentives-v1/), where Stakers similarly receive a relative proportion (by stake weight) of the remaining amount.
* Checks the merkle inclusion of a claim against a `DistributionRoot`
58
-
* Reverts if any of the following are true:
58
+
***AVS** (Autonomous Verifiable Service) refers to the contract entity that is submitting rewards to the `RewardsCoordinator`.
59
+
* This is assumed to be a customized `ServiceManager` contract of some kind that is interfacing with the EigenLayer protocol. See the `ServiceManagerBase` docs here: [`eigenlayer-middleware/docs/ServiceManagerBase.md`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/docs/ServiceManagerBase.md).
60
+
* An **Operator Set** refers to a collection of registered operators and strategies. See [ELIP-002](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-002.md#operator-sets) for more details.
61
+
* An **Operator Set Key** descibes the tuple of an AVS address and an ID that uniquely identifies an Operator Set. See the [AllocationManager](./AllocationManager.md#operator-sets) for details.
62
+
* A **rewards submission** includes, unless specified otherwise, both the v1 `RewardsSubmission` and the v2 `OperatorDirectedRewardsSubmission` types.
63
+
* The internal function `_checkClaim(RewardsMerkleClaim calldata claim, DistributionRoot memory root)` checks the merkle inclusion of a claim against a `DistributionRoot`
* earner proof reverting from calling `_verifyEarnerClaimProof`
61
67
* any of the token proofs reverting from calling `_verifyTokenClaimProof`
62
-
* Wherever AVS (Actively Validated Service) is mentioned, it refers to the contract entity that is submitting rewards to the `RewardsCoordinator`. This is assumed to be a customized `ServiceManager` contract of some kind that is interfacing with the EigenLayer protocol. See the `ServiceManagerBase` docs here: [`eigenlayer-middleware/docs/ServiceManagerBase.md`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/dev/docs/ServiceManagerBase.md).
63
-
* A rewards submission includes, unless specified otherwise, both the v1 `RewardsSubmission` and the v2 `OperatorDirectedRewardsSubmission` types.
64
68
65
69
---
66
70
@@ -71,7 +75,8 @@ Rewards are initially submitted to the contract to be distributed to Operators a
@@ -169,7 +174,7 @@ This method is identical in function to [`createAVSRewardsSubmission`](#createav
169
174
*Effects*:
170
175
* See [`createAVSRewardsSubmission`](#createavsrewardssubmission) above. The only differences are that:
171
176
* Each rewards submission hash is stored in the `isRewardsSubmissionForAllHash` mapping
172
-
*Emits a `RewardsSubmissionForAllCreated` event
177
+
*A `RewardsSubmissionForAllCreated` event is emitted
173
178
174
179
*Requirements*:
175
180
* See [`createAVSRewardsSubmission`](#createavsrewardssubmission) above. The only difference is that each calculated rewards submission hash MUST NOT already exist in the `isRewardsSubmissionForAllHash` mapping.
@@ -207,21 +212,22 @@ function createOperatorDirectedAVSRewardsSubmission(
AVS may make Rewards v2 submissions by calling `createOperatorDirectedAVSRewardsSubmission()` with any custom on-chain or off-chain logic to determine their rewards distribution strategy. This can be custom to the work performed by Operators during a certain period of time, can be a flat reward rate, or some other structure based on the AVS’s economic model. This would enable AVSs' flexibility in rewarding different operators for performance and other variables while maintaining the same easily calculable reward rate for stakers delegating to the same operator and strategy. The AVS can submit multiple performance-based rewards denominated in different tokens for even more flexibility.
214
220
215
221
*Effects*:
216
222
* For each `OperatorDirectedRewardsSubmission` element
217
-
* Transfers `amount` of `token` from the `msg.sender` (`AVS`) to the `RewardsCoordinator`
218
-
* Hashes `msg.sender` (`AVS`), `nonce`, and `OperatorDirectedRewardsSubmission` struct to create a unique rewards hash and sets this value to `true` in the `isOperatorDirectedAVSRewardsSubmissionHash` mapping
219
-
* Increments `submissionNonce[msg.sender]`
223
+
* Transfers `amount` of `token` from `msg.sender` to the `RewardsCoordinator`
224
+
* Hashes `AVS`, `nonce`, and `OperatorDirectedRewardsSubmission` struct to create a unique rewards hash and sets this value to `true` in the `isOperatorDirectedAVSRewardsSubmissionHash` mapping
225
+
* Increments `submissionNonce[avs]`
220
226
* Emits an `OperatorDirectedAVSRewardsSubmissionCreated` event
221
227
222
228
*Requirements*:
223
229
* Pause status MUST NOT be set: `PAUSED_OPERATOR_DIRECTED_AVS_REWARDS_SUBMISSION`
224
-
* Caller MUST BE the AVS
230
+
* Caller MUST be authorized, either as the AVS itself or an admin/appointee (see [`PermissionController.md`](../permissions/PermissionController.md))
225
231
* Function call is not reentered
226
232
* For each `OperatorDirectedRewardsSubmission` element:
227
233
* Requirements from calling internal function `_validateOperatorDirectedRewardsSubmission()`
@@ -243,6 +249,33 @@ AVS may make Rewards v2 submissions by calling `createOperatorDirectedAVSRewards
This function allows AVSs to make rewards submissions to specific operator sets, allowing for more granularly targeted rewards based on tasks assigned to a specific operator set, or any other custom AVS logic. Its functionality is almost identical to [`createOperatorDirectedAVSRewardsSubmission`](#createoperatordirectedavsrewardssubmission), save for some operator-set specific requirements, state variables, and events.
266
+
267
+
Note that an AVS must specify an operator set registered to the AVS; in other words, an operator set belonging to a different AVS, or an unregistered operator set, will cause this function to revert.
268
+
269
+
*Effects*:
270
+
* See [`createOperatorDirectedAVSRewardsSubmission`](#createoperatordirectedavsrewardssubmission) above. The only differences are that:
271
+
* Each rewards submission is stored in the `isOperatorDirectedOperatorSetRewardsSubmissionHash` mapping
272
+
* An `OperatorDirectedOperatorSetRewardsSubmissionCreated` event is emitted
273
+
274
+
*Requirements*:
275
+
* See [`createOperatorDirectedAVSRewardsSubmission`](#createoperatordirectedavsrewardssubmission) above. The only differences are that:
276
+
*`operatorSet` MUST be a [registered operator set](./AllocationManager.md#createoperatorsets) for the given AVS as according to `allocationManager.isOperatorSet()`
277
+
* Pause status is instead: `PAUSED_OPERATOR_DIRECTED_OPERATOR_SET_REWARDS_SUBMISSION`
An Operator may, for a given AVS, set a split which will determine what percent of their attributed rewards are allocated to themselves. The remaining percentage will go to Stakers.
@@ -500,7 +535,7 @@ The split will take effect after an `activationDelay` set by the contract owner.
500
535
* Emits an `OperatorAVSSplitBipsSet` event
501
536
502
537
*Requirements*:
503
-
* Caller MUST BE the operator
538
+
* Caller MUST be authorized, either as the operator itself or an admin/appointee (see [`PermissionController.md`](../permissions/PermissionController.md))
504
539
* Split MUST BE <= 10,000 bips (100%)
505
540
* Current `block.timestamp` MUST BE greater than current `operatorSplit.activatedAt`.
506
541
* Any pending split must have already completed prior to setting a new split.
@@ -514,15 +549,42 @@ function setOperatorPISplit(
514
549
)
515
550
external
516
551
onlyWhenNotPaused(PAUSED_OPERATOR_PI_SPLIT)
552
+
checkCanCall(operator)
517
553
```
518
554
519
555
Similar to [`setOperatorAVSSplit`](#setoperatoravssplit), Operators may set their split for [programmatic incentives](https://www.blog.eigenlayer.xyz/introducing-programmatic-incentives-v1/), allowing them to specify what percent of these rewards they will maintain and what percent will go to their Stakers. The `allocationDelay` also applies here, as well as the inability to reinitiate a split update before the delay passes.
520
556
521
557
*Effects*:
522
-
* Same as [`setOperatorAVSSplit`](#setoperatoravssplit), but with `operatorPISplitBips` instead of `operatorAVSSplitBips`.
558
+
* See [`setOperatorAVSSplit`](#setoperatoravssplit) above. The only differences are that:
559
+
* The split is stored within `_operatorPISplitBips` instead of `_operatorAVSSplitBips`.
560
+
* An `OperatorPISplitBipsSet` event is emitted
561
+
562
+
*Requirements*:
563
+
* See [`setOperatorAVSSplit`](#setoperatoravssplit) above. The only difference is that:
564
+
* Pause status is instead: `PAUSED_OPERATOR_PI_SPLIT`
565
+
566
+
#### `setOperatorSetSplit`
567
+
568
+
```solidity
569
+
function setOperatorSetSplit(
570
+
address operator,
571
+
OperatorSet calldata operatorSet,
572
+
uint16 split
573
+
)
574
+
external
575
+
onlyWhenNotPaused(PAUSED_OPERATOR_SET_SPLIT)
576
+
checkCanCall(operator)
577
+
```
578
+
579
+
*Effects*:
580
+
* See [`setOperatorAVSSplit`](#setoperatoravssplit) above. The only difference is that:
581
+
* The split is stored within `_operatorSetSplitBips` instead of `_operatorAVSSplitBips`
582
+
* An `OperatorSetSplitBipsSet` event is emitted
523
583
524
584
*Requirements*:
525
-
* See [`setOperatorAVSSplit`](#setoperatoravssplit).
585
+
* See [`setOperatorAVSSplit`](#setoperatoravssplit) above. The only differences are that:
586
+
*`operatorSet` MUST be a [registered operator set](./AllocationManager.md#createoperatorsets) for the given AVS as according to `allocationManager.isOperatorSet()`
587
+
* Pause status is instead: `PAUSED_OPERATOR_SET_SPLIT`
0 commit comments