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
Add focused unit and integration coverage for delayed burn/redistribution clearing edge cases, and align docs/NatSpec with the accepted grandfathering and native ETH behavior.
Made-with: Cursor
Allows a staker to delegate their assets to an operator. Delegation is all-or-nothing: when a staker delegates to an operator, they delegate ALL their assets. Stakers can only be delegated to one operator at a time.
339
+
Allows a staker to delegate their assets to an operator. Delegation is all-or-nothing: when a staker delegates to an operator, they delegate ALL their assets. Stakers can only be delegated to one operator at a time.
340
340
341
341
*Note: Delegating to an operator who has very low magnitudes (on the order of wei) may result in loss of funds.*
342
342
@@ -364,7 +364,7 @@ For each strategy the staker has deposit shares in, the `DelegationManager` will
364
364
/**
365
365
* @notice Undelegates the staker from their operator and queues a withdrawal for all of their shares
366
366
* @param staker The account to be undelegated
367
-
* @return withdrawalRoots The roots of the newly queued withdrawals, if a withdrawal was queued. Returns
367
+
* @return withdrawalRoots The roots of the newly queued withdrawals, if a withdrawal was queued. Returns
368
368
* an empty array if none was queued.
369
369
*
370
370
* @dev Reverts if the `staker` is also an operator, since operators are not allowed to undelegate from themselves.
@@ -373,7 +373,7 @@ For each strategy the staker has deposit shares in, the `DelegationManager` will
373
373
*/
374
374
function undelegate(
375
375
address staker
376
-
)
376
+
)
377
377
external
378
378
nonReentrant
379
379
returns (bytes32[] memory withdrawalRoots);
@@ -387,7 +387,7 @@ Undelegation immediately sets the staker's delegated operator to 0, decreases th
387
387
388
388
Just as with a normal queued withdrawal, these withdrawals can be completed by the staker after `MIN_WITHDRAWAL_DELAY_BLOCKS`. These withdrawals do not require the staker to "fully exit" from the system -- the staker may choose to keep their assets in the system once withdrawals are completed (See [`completeQueuedWithdrawal`](#completequeuedwithdrawal) for details).
389
389
390
-
*Effects*:
390
+
*Effects*:
391
391
* The `staker` is undelegated from their operator
392
392
* If the `staker` has no deposit shares, there is no withdrawal queued or further effects
393
393
* For each strategy held by the `staker`, a `Withdrawal` is queued:
@@ -430,14 +430,14 @@ Just as with a normal queued withdrawal, these withdrawals can be completed by t
`redelegate` is a convenience method that combines the effects of `undelegate` and `delegateTo`. `redelegate` allows a staker to switch their delegated operator to `newOperator` with a single call. **Note**, though, that the staker's assets will not be fully delegated to `newOperator` until the withdrawals queued during the undelegation portion of this method are completed.
439
439
440
-
*Effects*:
440
+
*Effects*:
441
441
* See [`delegateTo`](#delegateto) and [`undelegate`](#undelegate)
@@ -559,13 +559,13 @@ function completeQueuedWithdrawal(
559
559
Withdrawal calldata withdrawal,
560
560
IERC20[] calldata tokens,
561
561
bool receiveAsTokens
562
-
)
563
-
external
562
+
)
563
+
external
564
564
onlyWhenNotPaused(PAUSED_EXIT_WITHDRAWAL_QUEUE)
565
565
nonReentrant
566
566
```
567
567
568
-
`MIN_WITHDRAWAL_DELAY_BLOCKS` after queueing, a staker can complete a `Withdrawal` by calling this method. The staker can elect to receive _either_ tokens OR shares depending on the value of the `receiveAsTokens` parameter.
568
+
`MIN_WITHDRAWAL_DELAY_BLOCKS` after queueing, a staker can complete a `Withdrawal` by calling this method. The staker can elect to receive _either_ tokens OR shares depending on the value of the `receiveAsTokens` parameter.
569
569
570
570
Before processing a withdrawal, this method will calculate the slashing factor at the withdrawal's completion block (`withdrawal.startBlock + MIN_WITHDRAWAL_DELAY_BLOCKS`), according to the operator that was delegated to when the withdrawal was queued (`withdrawal.delegatedTo`). This slashing factor is used to determine if any additional slashing occurred while the withdrawal was in the queue. If so, this slashing is applied now.
571
571
@@ -575,16 +575,16 @@ If the staker chooses to receive the withdrawal _as tokens_, the withdrawable sh
575
575
576
576
If the staker chooses to receive the withdrawal _as shares_, the withdrawable shares are credited to the staker via the corresponding share manager (`EigenPodManager`/`StrategyManager`). Additionally, if the caller is delegated to an operator, the new slashing factor for the given `(staker, operator, strategy)` determines how many shares are awarded to the operator (and how the staker's deposit scaling factor is updated) (See [Slashing Factors and Scaling Shares](#slashing-factors-and-scaling-shares)). In receiving the withdrawal as shares, this amount is credited as deposit shares for the staker. Due to known rounding error, the amount of withdrawable shares after completing the withdrawal may be slightly less than what was originally withdrawable.
577
577
578
-
**Note:** if the staker (i) receives the withdrawal as shares, (ii) has `MAX_STAKER_STRATEGY_LIST_LENGTH` unique deposit strategies in the `StrategyManager`, and (iii) is withdrawing to a `StrategyManager` strategy in which they do not currently have shares, this will revert. The staker cannot withdraw such that their `stakerStrategyList` length exceeds the maximum; this withdrawal will have to be completed as tokens instead.
578
+
**Note:** if the staker (i) receives the withdrawal as shares, (ii) has `MAX_STAKER_STRATEGY_LIST_LENGTH` unique deposit strategies in the `StrategyManager`, and (iii) is withdrawing to a `StrategyManager` strategy in which they do not currently have shares, this will revert. The staker cannot withdraw such that their `stakerStrategyList` length exceeds the maximum; this withdrawal will have to be completed as tokens instead.
579
579
580
580
**Note:** if the staker receives a `beaconChainETHStrategy` withdrawal as tokens, the staker's `EigenPod` MUST have sufficient `withdrawableExecutionLayerGwei` to honor the withdrawal.
581
581
582
-
**Note:** if the strategy is not in the whitelist of the `StrategyManager`, the withdrawal will still succeed regardless of whether it is completed as shares or tokens.
582
+
**Note:** if the strategy is not in the whitelist of the `StrategyManager`, the withdrawal will still succeed regardless of whether it is completed as shares or tokens.
583
583
584
584
*Effects*:
585
585
* The hash of the `Withdrawal` is removed from the pending withdrawals
586
586
* The hash of the `Withdrawal` is removed from the enumerable set of staker queued withdrawals
587
-
* The `Withdrawal` struct is removed from the queued withdrawals
587
+
* The `Withdrawal` struct is removed from the queued withdrawals
588
588
* If `receiveAsTokens`:
589
589
* See [`StrategyManager.withdrawSharesAsTokens`](./StrategyManager.md#withdrawsharesastokens)
590
590
* See [`EigenPodManager.withdrawSharesAsTokens`](./EigenPodManager.md#withdrawsharesastokens)
@@ -621,9 +621,9 @@ function completeQueuedWithdrawals(
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.
677
677
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.
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/StrategyManager`) is called, increasing the burn or redistributable shares for that operatorSet, slashId, and strategy combination.
679
679
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.
680
+
**Note**: ERC20 strategy shares marked in the `StrategyManager` are cleared through the slash-resolution delay flow documented in [`StrategyManager.increaseBurnOrRedistributableShares`](./StrategyManager.md#increaseburnorredistributableshares). Native ETH uses `EigenPodManager` accounting instead: slashed beacon chain ETH shares accrue in `burnableETHShares`, but there is no current StrategyManager-style delayed clear or redistribution execution path for native ETH, as burning native ETH requires the Pectra hard fork to be able to force exit validators.
681
681
682
682
*Effects*:
683
683
* The `operator's``operatorShares` are reduced for the given `strategy`, according to the proportion given by `prevMaxMagnitude` and `newMaxMagnitude`
684
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)
685
+
* See [`StrategyManager.increaseBurnOrRedistributableShares`](./StrategyManager.md#increaseburnorredistributableshares)
686
+
* See [`EigenPodManager.increaseBurnOrRedistributableShares`](./EigenPodManager.md#increaseburnorredistributableshares)
687
687
688
688
689
689
*Requirements*:
@@ -694,7 +694,7 @@ Additionally, any _slashable shares_ in the withdrawal queue are marked for burn
694
694
```solidity
695
695
/**
696
696
* @notice Called by a share manager when a staker's deposit share balance in a strategy increases.
697
-
* This method delegates any new shares to an operator (if applicable), and updates the staker's
697
+
* This method delegates any new shares to an operator (if applicable), and updates the staker's
698
698
* deposit scaling factor regardless.
699
699
* @param staker The address whose deposit shares have increased
700
700
* @param strategy The strategy in which shares have been deposited
@@ -710,15 +710,15 @@ function increaseDelegatedShares(
710
710
IStrategy strategy,
711
711
uint256 prevDepositShares,
712
712
uint256 addedShares
713
-
)
713
+
)
714
714
external
715
715
onlyStrategyManagerOrEigenPodManager
716
716
nonReentrant
717
717
```
718
718
719
719
Called by either the `StrategyManager` or `EigenPodManager` when a staker's deposit shares for one or more strategies increase.
720
720
721
-
If the staker is delegated to an operator, the new deposit shares are directly added to that operator's `operatorShares`. Regardless of delegation status, the staker's deposit scaling factor is updated. In addition, if the operator has allocated slashable stake for the strategy, the staker's deposit is immediately slashable by an operatorSet.
721
+
If the staker is delegated to an operator, the new deposit shares are directly added to that operator's `operatorShares`. Regardless of delegation status, the staker's deposit scaling factor is updated. In addition, if the operator has allocated slashable stake for the strategy, the staker's deposit is immediately slashable by an operatorSet.
722
722
723
723
**Note** that if either the staker's current operator has been slashed 100% for `strategy`, OR the staker has been slashed 100% on the beacon chain such that the calculated slashing factor is 0, this method WILL REVERT. See [Shares Accounting - Fully Slashed](./accounting/SharesAccountingEdgeCases.md#fully-slashed-for-a-strategy) for details. This doesn't block delegation to an operator if the staker has 0 deposit shares for a strategy which has a slashing factor of 0, but any subsequent deposits that call `increaseDelegatedShares` will revert from the **Fully Slashed** edge case.
724
724
@@ -745,7 +745,7 @@ function decreaseDelegatedShares(
0 commit comments