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
Every `OperatorSet` corresponds to a single AVS, as indicated by the `avs` parameter. On creation, the AVS provides an `id` (unique to that AVS), as well as a list of `strategies` the `OperatorSet` includes. Together, the `avs` and `id` form the `key` that uniquely identifies a given `OperatorSet`. Operators can register to and deregister from operator sets. In combination with allocating slashable magnitude, operator set registration forms the basis of operator slashability (discussed further in [Allocations and Slashing](#allocations-and-slashing)).
174
+
Every `OperatorSet` corresponds to a single AVS, as indicated by the `avs` parameter. On creation, the AVS provides an `id` (unique to that AVS), as well as a list of `strategies` the `OperatorSet` includes. Together, the `avs` and `id` form the `key` that uniquely identifies a given `OperatorSet`. Operators can register to and deregister from operator sets. In combination with allocating slashable magnitude, operator set registration forms the basis of operator slashability (discussed further in [Allocations and Slashing](#allocations-and-slashing)). There are two types of operatorSets, redistributing and non-redistributing.
_Note: this method can be called directly by an AVS, or by a caller authorized by the AVS. See [`PermissionController.md`](../permissions/PermissionController.md) for details._
239
241
240
-
AVSs use this method to create new operator sets. An AVS can create as many operator sets as they desire, depending on their needs. Once created, operators can [allocate slashable stake to](#modifyallocations) and [register for](#registerforoperatorsets) these operator sets.
242
+
AVSs use this method to create new operator sets. An AVS can create as many operator sets as they desire, depending on their needs. Once created, operators can [allocate slashable stake to](#modifyallocations) and [register for](#registerforoperatorsets) these operator sets. The `redistributionRecipient` is the `DEFAULT_BURN_ADDRESS`, where slashed funds are sent.
241
243
242
244
On creation, the `avs` specifies an `operatorSetId` unique to the AVS. Together, the `avs` address and `operatorSetId` create a `key` that uniquely identifies this operator set throughout the `AllocationManager`.
243
245
@@ -254,6 +256,38 @@ Optionally, the `avs` can provide a list of `strategies`, specifying which strat
254
256
* AVS MUST have registered metadata via calling `updateAVSMetadataURI`
255
257
* For each `CreateSetParams` element:
256
258
* Each `params.operatorSetId` MUST NOT already exist in `_operatorSets[avs]`
259
+
260
+
#### `createRedistributingOperatorSets`
261
+
262
+
```solidity
263
+
/**
264
+
* @notice Allows an AVS to create new redistributing operator sets, defining strategies and the redistribution recipient the operator set uses
265
+
*/
266
+
function createRedistributingOperatorSets(
267
+
address avs,
268
+
CreateSetParams[] calldata params,
269
+
address[] calldata redistributionRecipients
270
+
)
271
+
external
272
+
checkCanCall(avs)
273
+
```
274
+
275
+
AVSs use this method to create new redistributing operatorSets. Unlike the previous function, slashed funds for this operatorSet are sent to a `redistributionRecipient`. This value is set only once, upon creation. Note that redistributing operatorSets may not have Native ETH, as the protocol does not support native eth redistribution. See [ELIP-006](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-006.md) for additional context.
276
+
277
+
*Effects*:
278
+
* For each `CreateSetParams` element:
279
+
* For each `params.strategies` element:
280
+
* Add `strategy` to `_operatorSetStrategies[operatorSetKey]`
281
+
* Emits `StrategyAddedToOperatorSet` event
282
+
* Sets the `redistributionRecipient` of the operatorSet
283
+
* Emits the `RedistributionAddressSet`
284
+
285
+
*Requirements*:
286
+
* Caller MUST be authorized, either as the AVS itself or an admin/appointee (see [`PermissionController.md`](../permissions/PermissionController.md))
287
+
* AVS MUST have registered metadata via calling `updateAVSMetadataURI`
288
+
* The `redistributionRecipient` MUST NOT be the 0 address
289
+
* For each `CreateSetParams` element:
290
+
* Each `params.operatorSetId` MUST NOT already exist in `_operatorSets[avs]`
257
291
258
292
#### `addStrategiesToOperatorSet`
259
293
@@ -287,6 +321,7 @@ This function allows an AVS to add slashable strategies to a given operator set.
287
321
* Caller MUST be authorized, either as the AVS itself or an admin/appointee (see [`PermissionController.md`](../permissions/PermissionController.md))
288
322
* The operator set MUST be registered for the AVS
289
323
* Each proposed strategy MUST NOT be registered for the operator set
324
+
* If the operatorSet is redistributing, the `BEACONCHAIN_ETH_STRAT` may not be added, since redistribution is not supported for native eth
290
325
291
326
#### `removeStrategiesFromOperatorSet`
292
327
@@ -717,6 +752,9 @@ struct SlashingParams {
717
752
* - wadsToSlash: Array of proportions to slash from each strategy (must be between 0 and 1e18).
718
753
* - description: Description of why the operator was slashed.
719
754
*
755
+
* @return slashId The ID of the slash.
756
+
* @return shares The amount of shares that were slashed for each strategy.
757
+
*
720
758
* @dev For each strategy:
721
759
* 1. Reduces the operator's current allocation magnitude by wadToSlash proportion.
722
760
* 2. Reduces the strategy's max and encumbered magnitudes proportionally.
@@ -734,6 +772,7 @@ function slashOperator(
734
772
external
735
773
onlyWhenNotPaused(PAUSED_OPERATOR_SLASHING)
736
774
checkCanCall(avs)
775
+
returns (uint256, uint256[] memory)
737
776
```
738
777
739
778
_Note: this method can be called directly by an AVS, or by a caller authorized by the AVS. See [`PermissionController.md`](../permissions/PermissionController.md) for details._
@@ -748,7 +787,7 @@ There are two edge cases to note for this method:
748
787
1. In the process of slashing an `operator` for a given `strategy`, if the `Allocation` being slashed has a `currentMagnitude` of 0, the call will NOT revert. Instead, the `strategy` is skipped and slashing continues with the next `strategy` listed. This is to prevent an edge case where slashing occurs on or around a deallocation's `effectBlock` -- if the call reverted, the entire slash would fail. Skipping allows any valid slashes to be processed without requiring resubmission.
749
788
2. If the `operator` has a pending, non-completable deallocation, the deallocation's `pendingDiff` is reduced proportional to the slash. This ensures that when the deallocation is completed, less `encumberedMagnitude` is freed.
750
789
751
-
Once slashing is processed for a strategy, [slashed stake is burned via the `DelegationManager`](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-002.md#burning-of-slashed-funds).
790
+
Once slashing is processed for a strategy, [slashed stake is burned or redistributed via the `DelegationManager`](https://github.com/eigenfoundation/ELIPs/blob/main/ELIPs/ELIP-002.md#burning-of-slashed-funds).
752
791
753
792
*Effects*:
754
793
* Given an `operator` and `operatorSet`, then for each `params.strategies` element and its corresponding `allocation`:
@@ -765,6 +804,8 @@ Once slashing is processed for a strategy, [slashed stake is burned via the `Del
765
804
* If this list now has a length of 0, remove `operatorSetKey` from `allocatedSets[operator]`
Copy file name to clipboardExpand all lines: docs/core/DelegationManager.md
+17-11Lines changed: 17 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,7 +25,7 @@ Libraries and Mixins:
25
25
26
26
The `DelegationManager` is the intersection between the two sides of the protocol. It (i) allows stakers to delegate/undelegate to/from operators, (ii) handles withdrawals and withdrawal processing for assets in both the `StrategyManager` and `EigenPodManager`, and (iii) manages accounting around slashing for stakers and operators.
27
27
28
-
When operators are slashed by AVSs, it receives share burning directives from the `AllocationManager`. When stakers deposit assets using the `StrategyManager/EigenPodManager`, it tracks share/delegation accounting changes. The `DelegationManager` combines inputs from both sides of the protocol into a staker's "deposit scaling factor," which serves as the primary conversion vehicle between a staker's _raw deposited assets_ and the _amount they can withdraw_.
28
+
When operators are slashed by AVSs, it receives share slashing directives from the `AllocationManager`. When stakers deposit assets using the `StrategyManager/EigenPodManager`, it tracks share/delegation accounting changes. The `DelegationManager` combines inputs from both sides of the protocol into a staker's "deposit scaling factor," which serves as the primary conversion vehicle between a staker's _raw deposited assets_ and the _amount they can withdraw_.
29
29
30
30
The `DelegationManager's` responsibilities can be broken down into the following concepts:
@@ -396,7 +396,7 @@ Just as with a normal queued withdrawal, these withdrawals can be completed by t
396
396
* See [`StrategyManager.removeDepositShares`](./StrategyManager.md#removedepositshares)
397
397
*_Deposit shares_ are converted to _withdrawable shares_ (See [Slashing Factors and Scaling Shares](#slashing-factors-and-scaling-shares)). These are decremented from the operator's delegated shares.
398
398
*_Deposit shares_ are converted to _scaled shares_ (See [Shares Accounting - Queue Withdrawals](./accounting/SharesAccounting.md#queue-withdrawal)), which are stored in the `Withdrawal` struct
399
-
*_Scaled shares_ are pushed to `_cumulativeScaledSharesHistory`, which is used for burning slashed shares
399
+
*_Scaled shares_ are pushed to `_cumulativeScaledSharesHistory`, which is used for burning or redistributing slashed shares
400
400
* The `Withdrawal` is saved to storage
401
401
* The hash of the `Withdrawal` is marked as "pending"
402
402
* The hash of the `Withdrawal` is set in a mapping to the `Withdrawal` struct itself
@@ -487,7 +487,7 @@ For each `QueuedWithdrawalParams` passed as input, a `Withdrawal` is created in
487
487
* The raw _deposit shares_ are removed from the staker's deposit share balance in the corresponding share manager (`EigenPodManager` or `StrategyManager`).
488
488
*_Scaled shares_ are calculated by applying the staker's _deposit scaling factor_ to their _deposit shares_. Scaled shares:
489
489
* are stored in the `Withdrawal` itself and used during withdrawal completion
490
-
* are added to the operator's `cumulativeScaledSharesHistory`, where they can be burned if slashing occurs while the withdrawal is in the queue
490
+
* are added to the operator's `cumulativeScaledSharesHistory`, where they can be burned or redistributed if slashing occurs while the withdrawal is in the queue
491
491
*_Withdrawable shares_ are calculated by applying both the staker's _deposit scaling factor_ AND any appropriate _slashing factor_ to the staker's _deposit shares_. These "currently withdrawable shares" are removed from the operator's delegated shares (if applicable).
492
492
493
493
Note that the `QueuedWithdrawalParams.__deprecated_withdrawer` field is ignored. Originally, this was used to create withdrawals that could be completed by a third party. This functionality was removed during the M2 release due to growing concerns over the phish risk this presented. Until the slashing release, this field was explicitly checked for equivalence with `msg.sender`; however, at present it is ignored. All `Withdrawals` are created with `withdrawer == staker` regardless of this field's value.
@@ -499,7 +499,7 @@ Note that the `QueuedWithdrawalParams.__deprecated_withdrawer` field is ignored.
499
499
* See [`StrategyManager.removeDepositShares`](./StrategyManager.md#removedepositshares)
500
500
*_Deposit shares_ are converted to _withdrawable shares_ (See [Slashing Factors and Scaling Deposits](#slashing-factors-and-scaling-shares)). These are decremented from their operator's delegated shares (if applicable)
501
501
*_Deposit shares_ are converted to _scaled shares_ (See [Shares Accounting - Queue Withdrawals](./accounting/SharesAccounting.md#queue-withdrawal)), which are stored in the `Withdrawal` struct
502
-
* If the caller is delegated to an operator, _scaled shares_ are pushed to that operator's `_cumulativeScaledSharesHistory`, which may be burned if slashing occurs.
502
+
* If the caller is delegated to an operator, _scaled shares_ are pushed to that operator's `_cumulativeScaledSharesHistory`, which may be burned or redistributed if slashing occurs.
503
503
* The `Withdrawal` is saved to storage
504
504
* The hash of the `Withdrawal` is marked as "pending"
505
505
* The hash of the `Withdrawal` is set in a mapping to the `Withdrawal` struct itself
@@ -644,40 +644,46 @@ These methods are all called by other system contracts: the `AllocationManager`
644
644
645
645
```solidity
646
646
/**
647
-
* @notice Decreases the operators shares in storage after a slash and increases the burnable shares by calling
647
+
* @notice Decreases the operators shares in storage after a slash and increases the burn or redistributable shares by calling
648
648
* into either the StrategyManager or EigenPodManager (if the strategy is beaconChainETH).
649
649
* @param operator The operator to decrease shares for
650
+
* @param operatorSet The OperatorSet to decrease shares for
651
+
* @param slashID The slashID to decrease shares for
650
652
* @param strategy The strategy to decrease shares for
651
653
* @param prevMaxMagnitude the previous maxMagnitude of the operator
652
654
* @param newMaxMagnitude the new maxMagnitude of the operator
653
655
* @dev Callable only by the AllocationManager
654
656
* @dev Note: Assumes `prevMaxMagnitude <= newMaxMagnitude`. This invariant is maintained in
655
657
* the AllocationManager.
658
+
* @return depositSharesToSlash The total deposit shares to slash (burn or redistribute).
656
659
*/
657
660
function slashOperatorShares(
658
661
address operator,
662
+
OperatorSet calldata operatorSet,
663
+
uint256 slashId,
659
664
IStrategy strategy,
660
665
uint64 prevMaxMagnitude,
661
666
uint64 newMaxMagnitude
662
667
)
663
668
external
664
669
onlyAllocationManager
665
670
nonReentrant
671
+
returns (uint256 depositSharesToSlash)
666
672
```
667
673
668
674
_See [Shares Accounting - Slashing](https://github.com/Layr-Labs/eigenlayer-contracts/blob/slashing-magnitudes/docs/core/accounting/SharesAccounting.md#slashing) for a description of the accounting in this method._
669
675
670
676
This method is called by the `AllocationManager` when processing an AVS's slash of an operator. Slashing occurs instantly, with this method directly reducing the operator's delegated shares proportional to the slash.
671
677
672
-
Additionally, any _slashable shares_ in the withdrawal queue are marked for burning according to the same slashing proportion (shares in the withdrawal queue remain slashable for `MIN_WITHDRAWAL_DELAY_BLOCKS`). For the slashed strategy, the corresponding share manager (`EigenPodManager/StrateyManager`) is called, increasing the burnable shares for that strategy.
678
+
Additionally, any _slashable shares_ in the withdrawal queue are marked for burn or redistribution according to the same slashing proportion (shares in the withdrawal queue remain slashable for `MIN_WITHDRAWAL_DELAY_BLOCKS`). For the slashed strategy, the corresponding share manager (`EigenPodManager/StrateyManager`) is called, increasing the burn or redistributable shares for that operatorSet, slashId, and strategy combination.
673
679
674
-
**Note**: native ETH does not currently possess a burning mechanism, as this requires Pectra to be able to force exit validators. Currently, slashing for the `beaconChainETHStrategy` is realized by modifying the amount stakers are able to withdraw.
680
+
**Note**: native ETH does not currently possess a burn/redistribution mechanism, as this requires Pectra to be able to force exit validators. Currently, slashing for the `beaconChainETHStrategy` is realized by modifying the amount stakers are able to withdraw.
675
681
676
682
*Effects*:
677
683
* The `operator's``operatorShares` are reduced for the given `strategy`, according to the proportion given by `prevMaxMagnitude` and `newMaxMagnitude`
678
-
* Any slashable shares in the withdrawal queue are marked for burning according to the same proportion
679
-
* See [`StrategyManager.increaseBurnableShares`](./StrategyManager.md#increaseBurnableShares)
680
-
* See [`EigenPodManager.increaseBurnableShares`](./EigenPodManager.md#increaseBurnableShares)
684
+
* Any slashable shares in the withdrawal queue are marked for burning or redistribution according to the same proportion
685
+
* See [`StrategyManager.increaseBurnOrRedistributableShares`](./StrategyManager.md#increaseBurnableShares)
686
+
* See [`EigenPodManager.increaseBurnOrRedistributableShares`](./EigenPodManager.md#increaseBurnableShares)
0 commit comments