From c44f72576008f8a7ea4d626825435672d927a7f0 Mon Sep 17 00:00:00 2001 From: Michael Sun <35479365+8sunyuan@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:19:49 -0500 Subject: [PATCH] refactor: async burning (#1001) * refactor: burning * chore: fmt * chore: update storage report * chore: update readme * refactor: add burnableShares for epm storage * chore: update storage report --- README.md | 8 + docs/core/AllocationManager.md | 2 +- docs/storage-report/EigenPodManager.md | 4 +- docs/storage-report/EigenPodManagerStorage.md | 4 +- docs/storage-report/StrategyManager.md | 4 +- docs/storage-report/StrategyManagerStorage.md | 4 +- src/contracts/core/AllocationManager.sol | 4 +- src/contracts/core/DelegationManager.sol | 10 +- src/contracts/core/StrategyManager.sol | 13 +- src/contracts/core/StrategyManagerStorage.sol | 5 +- .../interfaces/IDelegationManager.sol | 9 +- src/contracts/interfaces/IEigenPodManager.sol | 6 + src/contracts/interfaces/IShareManager.sol | 9 ++ src/contracts/interfaces/IStrategyManager.sol | 15 +- src/contracts/pods/EigenPodManager.sol | 6 + src/contracts/pods/EigenPodManagerStorage.sol | 5 +- src/test/mocks/DelegationManagerMock.sol | 2 +- src/test/unit/DelegationUnit.t.sol | 150 ++++++++---------- src/test/unit/EigenPodManagerUnit.t.sol | 46 +++++- src/test/unit/StrategyManagerUnit.t.sol | 93 ++++++++--- 20 files changed, 267 insertions(+), 132 deletions(-) diff --git a/README.md b/README.md index 72cecb6ce8..58d6b07c5d 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,14 @@ surya mdreport surya_report.md ./src/contracts/**/*.sol make bindings ``` +### Generate updated Storage Report + +To update the storage reports in `/docs/storage-report` run: + +```bash +make storage-report +``` + ## Deployments ### Current Mainnet Deployment diff --git a/docs/core/AllocationManager.md b/docs/core/AllocationManager.md index 40e928e865..4e722b5228 100644 --- a/docs/core/AllocationManager.md +++ b/docs/core/AllocationManager.md @@ -623,7 +623,7 @@ Once slashing is processed for a strategy, [slashed stake is burned via the `Del * If the `allocation` now has a `currentMagnitude` of 0: * Removes `strategy` from the `allocatedStrategies[operator][operatorSetKey]` list * If this list now has a length of 0, remove `operatorSetKey` from `allocatedSets[operator]` - * Calls [`DelegationManager.burnOperatorShares`](./DelegationManager.md#burnoperatorshares) + * Calls [`DelegationManager.slashOperatorShares`](./DelegationManager.md#slashoperatorshares) * Emit an `OperatorSlashed` event *Requirements*: diff --git a/docs/storage-report/EigenPodManager.md b/docs/storage-report/EigenPodManager.md index 3b5963838d..e0f91d0dbe 100644 --- a/docs/storage-report/EigenPodManager.md +++ b/docs/storage-report/EigenPodManager.md @@ -32,7 +32,9 @@ |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| | _beaconChainSlashingFactor | mapping(address => struct IEigenPodManagerTypes.BeaconChainSlashingFactor) | 157 | 0 | 32 | src/contracts/pods/EigenPodManager.sol:EigenPodManager | |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| -| __gap | uint256[43] | 158 | 0 | 1376 | src/contracts/pods/EigenPodManager.sol:EigenPodManager | +| burnableETHShares | uint256 | 158 | 0 | 32 | src/contracts/pods/EigenPodManager.sol:EigenPodManager | +|---------------------------------+----------------------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| +| __gap | uint256[42] | 159 | 0 | 1344 | src/contracts/pods/EigenPodManager.sol:EigenPodManager | |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| | _status | uint256 | 201 | 0 | 32 | src/contracts/pods/EigenPodManager.sol:EigenPodManager | |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| diff --git a/docs/storage-report/EigenPodManagerStorage.md b/docs/storage-report/EigenPodManagerStorage.md index 61213da4d0..42e293f48f 100644 --- a/docs/storage-report/EigenPodManagerStorage.md +++ b/docs/storage-report/EigenPodManagerStorage.md @@ -16,6 +16,8 @@ |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| | _beaconChainSlashingFactor | mapping(address => struct IEigenPodManagerTypes.BeaconChainSlashingFactor) | 6 | 0 | 32 | src/contracts/pods/EigenPodManagerStorage.sol:EigenPodManagerStorage | |---------------------------------+----------------------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| -| __gap | uint256[43] | 7 | 0 | 1376 | src/contracts/pods/EigenPodManagerStorage.sol:EigenPodManagerStorage | +| burnableETHShares | uint256 | 7 | 0 | 32 | src/contracts/pods/EigenPodManagerStorage.sol:EigenPodManagerStorage | +|---------------------------------+----------------------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| +| __gap | uint256[42] | 8 | 0 | 1344 | src/contracts/pods/EigenPodManagerStorage.sol:EigenPodManagerStorage | ╰---------------------------------+----------------------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------╯ diff --git a/docs/storage-report/StrategyManager.md b/docs/storage-report/StrategyManager.md index cb1e9c26b3..8749413c82 100644 --- a/docs/storage-report/StrategyManager.md +++ b/docs/storage-report/StrategyManager.md @@ -44,6 +44,8 @@ |----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| | __deprecated_thirdPartyTransfersForbidden | mapping(contract IStrategy => bool) | 211 | 0 | 32 | src/contracts/core/StrategyManager.sol:StrategyManager | |----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| -| __gap | uint256[39] | 212 | 0 | 1248 | src/contracts/core/StrategyManager.sol:StrategyManager | +| burnableShares | mapping(contract IStrategy => uint256) | 212 | 0 | 32 | src/contracts/core/StrategyManager.sol:StrategyManager | +|----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+--------------------------------------------------------| +| __gap | uint256[38] | 213 | 0 | 1216 | src/contracts/core/StrategyManager.sol:StrategyManager | ╰----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+--------------------------------------------------------╯ diff --git a/docs/storage-report/StrategyManagerStorage.md b/docs/storage-report/StrategyManagerStorage.md index 54988cff6e..16a2c41f94 100644 --- a/docs/storage-report/StrategyManagerStorage.md +++ b/docs/storage-report/StrategyManagerStorage.md @@ -24,6 +24,8 @@ |----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| | __deprecated_thirdPartyTransfersForbidden | mapping(contract IStrategy => bool) | 10 | 0 | 32 | src/contracts/core/StrategyManagerStorage.sol:StrategyManagerStorage | |----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| -| __gap | uint256[39] | 11 | 0 | 1248 | src/contracts/core/StrategyManagerStorage.sol:StrategyManagerStorage | +| burnableShares | mapping(contract IStrategy => uint256) | 11 | 0 | 32 | src/contracts/core/StrategyManagerStorage.sol:StrategyManagerStorage | +|----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------| +| __gap | uint256[38] | 12 | 0 | 1216 | src/contracts/core/StrategyManagerStorage.sol:StrategyManagerStorage | ╰----------------------------------------------------------+------------------------------------------------------------+------+--------+-------+----------------------------------------------------------------------╯ diff --git a/src/contracts/core/AllocationManager.sol b/src/contracts/core/AllocationManager.sol index d09fa8bab2..2c77cc02b4 100644 --- a/src/contracts/core/AllocationManager.sol +++ b/src/contracts/core/AllocationManager.sol @@ -132,8 +132,8 @@ contract AllocationManager is _updateMaxMagnitude(params.operator, params.strategies[i], info.maxMagnitude); - // 6. Decrease and burn operators shares in the DelegationManager - delegation.burnOperatorShares({ + // 6. Slash operators shares in the DelegationManager + delegation.slashOperatorShares({ operator: params.operator, strategy: params.strategies[i], prevMaxMagnitude: prevMaxMagnitude, diff --git a/src/contracts/core/DelegationManager.sol b/src/contracts/core/DelegationManager.sol index 3000c9b527..2d5350b408 100644 --- a/src/contracts/core/DelegationManager.sol +++ b/src/contracts/core/DelegationManager.sol @@ -275,7 +275,7 @@ contract DelegationManager is } /// @inheritdoc IDelegationManager - function burnOperatorShares( + function slashOperatorShares( address operator, IStrategy strategy, uint64 prevMaxMagnitude, @@ -307,11 +307,9 @@ contract DelegationManager is sharesToDecrease: operatorSharesSlashed }); - // NOTE: native ETH shares will be burned by a different mechanism in a future release - if (strategy != beaconChainETHStrategy) { - strategyManager.burnShares(strategy, totalDepositSharesToBurn); - emit OperatorSharesBurned(operator, strategy, totalDepositSharesToBurn); - } + IShareManager shareManager = _getShareManager(strategy); + // NOTE: for beaconChainETHStrategy, increased burnable shares currently have no mechanism for burning + shareManager.increaseBurnableShares(strategy, totalDepositSharesToBurn); } /** diff --git a/src/contracts/core/StrategyManager.sol b/src/contracts/core/StrategyManager.sol index eb8c545d6f..3f986fedec 100644 --- a/src/contracts/core/StrategyManager.sol +++ b/src/contracts/core/StrategyManager.sol @@ -140,8 +140,19 @@ contract StrategyManager is strategy.withdraw(staker, token, shares); } + /// @inheritdoc IShareManager + function increaseBurnableShares(IStrategy strategy, uint256 addedSharesToBurn) external onlyDelegationManager { + burnableShares[strategy] += addedSharesToBurn; + emit BurnableSharesIncreased(strategy, addedSharesToBurn); + } + /// @inheritdoc IStrategyManager - function burnShares(IStrategy strategy, uint256 sharesToBurn) external onlyDelegationManager { + function burnShares( + IStrategy strategy + ) external nonReentrant { + uint256 sharesToBurn = burnableShares[strategy]; + burnableShares[strategy] = 0; + emit BurnableSharesDecreased(strategy, sharesToBurn); // burning shares is functionally the same as withdrawing but with different destination address strategy.withdraw(DEFAULT_BURN_ADDRESS, strategy.underlyingToken(), sharesToBurn); } diff --git a/src/contracts/core/StrategyManagerStorage.sol b/src/contracts/core/StrategyManagerStorage.sol index 3834ac6745..705dab4a44 100644 --- a/src/contracts/core/StrategyManagerStorage.sol +++ b/src/contracts/core/StrategyManagerStorage.sol @@ -69,6 +69,9 @@ abstract contract StrategyManagerStorage is IStrategyManager { /// @dev Do not remove, deprecated storage. mapping(IStrategy strategy => bool) private __deprecated_thirdPartyTransfersForbidden; + /// @notice Returns the amount of `shares` that have been slashed on EigenLayer but not burned yet. + mapping(IStrategy strategy => uint256) public burnableShares; + // Construction /** @@ -85,5 +88,5 @@ abstract contract StrategyManagerStorage is IStrategyManager { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[39] private __gap; + uint256[38] private __gap; } diff --git a/src/contracts/interfaces/IDelegationManager.sol b/src/contracts/interfaces/IDelegationManager.sol index e42fb1beec..4533fffe7b 100644 --- a/src/contracts/interfaces/IDelegationManager.sol +++ b/src/contracts/interfaces/IDelegationManager.sol @@ -148,9 +148,6 @@ interface IDelegationManagerEvents is IDelegationManagerTypes { /// @notice Emitted whenever an operator's shares are decreased for a given strategy. Note that shares is the delta in the operator's shares. event OperatorSharesDecreased(address indexed operator, address staker, IStrategy strategy, uint256 shares); - /// @notice Emitted whenever an operator's shares are burned for a given strategy - event OperatorSharesBurned(address indexed operator, IStrategy strategy, uint256 shares); - /// @notice Emitted when @param staker delegates to @param operator. event StakerDelegated(address indexed staker, address indexed operator); @@ -353,8 +350,8 @@ interface IDelegationManager is ISignatureUtils, IDelegationManagerErrors, IDele ) external; /** - * @notice Decreases the operators shares in storage after a slash and burns the corresponding Strategy shares - * by calling into the StrategyManager or EigenPodManager to burn the shares. + * @notice Decreases the operators shares in storage after a slash and increases the burnable shares by calling + * into either the StrategyManager or EigenPodManager (if the strategy is beaconChainETH). * @param operator The operator to decrease shares for * @param strategy The strategy to decrease shares for * @param prevMaxMagnitude the previous maxMagnitude of the operator @@ -363,7 +360,7 @@ interface IDelegationManager is ISignatureUtils, IDelegationManagerErrors, IDele * @dev Note: Assumes `prevMaxMagnitude <= newMaxMagnitude`. This invariant is maintained in * the AllocationManager. */ - function burnOperatorShares( + function slashOperatorShares( address operator, IStrategy strategy, uint64 prevMaxMagnitude, diff --git a/src/contracts/interfaces/IEigenPodManager.sol b/src/contracts/interfaces/IEigenPodManager.sol index 3417965414..b7611b50a4 100644 --- a/src/contracts/interfaces/IEigenPodManager.sol +++ b/src/contracts/interfaces/IEigenPodManager.sol @@ -54,6 +54,9 @@ interface IEigenPodManagerEvents { event BeaconChainSlashingFactorDecreased( address staker, uint64 prevBeaconChainSlashingFactor, uint64 newBeaconChainSlashingFactor ); + + /// @notice Emitted when an operator is slashed and shares to be burned are increased + event BurnableETHSharesIncreased(uint256 shares); } interface IEigenPodManagerTypes { @@ -161,4 +164,7 @@ interface IEigenPodManager is function beaconChainSlashingFactor( address staker ) external view returns (uint64); + + /// @notice Returns the accumulated amount of beacon chain ETH Strategy shares + function burnableETHShares() external view returns (uint256); } diff --git a/src/contracts/interfaces/IShareManager.sol b/src/contracts/interfaces/IShareManager.sol index aaf5d68546..6ee50bc627 100644 --- a/src/contracts/interfaces/IShareManager.sol +++ b/src/contracts/interfaces/IShareManager.sol @@ -37,4 +37,13 @@ interface IShareManager { /// @dev strategy must be beaconChainETH when talking to the EigenPodManager /// @dev returns 0 if the user has negative shares function stakerDepositShares(address user, IStrategy strategy) external view returns (uint256 depositShares); + + /** + * @notice Increase the amount of burnable shares for a given Strategy. This is called by the DelegationManager + * when an operator is slashed in EigenLayer. + * @param strategy The strategy to burn shares in. + * @param addedSharesToBurn The amount of added shares to burn. + * @dev This function is only called by the DelegationManager when an operator is slashed. + */ + function increaseBurnableShares(IStrategy strategy, uint256 addedSharesToBurn) external; } diff --git a/src/contracts/interfaces/IStrategyManager.sol b/src/contracts/interfaces/IStrategyManager.sol index 7a2d0c38d8..6b31224c72 100644 --- a/src/contracts/interfaces/IStrategyManager.sol +++ b/src/contracts/interfaces/IStrategyManager.sol @@ -43,6 +43,12 @@ interface IStrategyManagerEvents { /// @notice Emitted when a strategy is removed from the approved list of strategies for deposit event StrategyRemovedFromDepositWhitelist(IStrategy strategy); + + /// @notice Emitted when an operator is slashed and shares to be burned are increased + event BurnableSharesIncreased(IStrategy strategy, uint256 shares); + + /// @notice Emitted when shares are burned + event BurnableSharesDecreased(IStrategy strategy, uint256 shares); } /** @@ -109,12 +115,13 @@ interface IStrategyManager is IStrategyManagerErrors, IStrategyManagerEvents, IS ) external returns (uint256 shares); /** - * @notice Burns Strategy shares for the given strategy by calling into the strategy to transfer to the default burn address. + * @notice Burns Strategy shares for the given strategy by calling into the strategy to transfer + * to the default burn address. * @param strategy The strategy to burn shares in. - * @param sharesToBurn The amount of shares to burn. - * @dev This function is only called by the DelegationManager when an operator is slashed. */ - function burnShares(IStrategy strategy, uint256 sharesToBurn) external; + function burnShares( + IStrategy strategy + ) external; /** * @notice Owner-only function to change the `strategyWhitelister` address. diff --git a/src/contracts/pods/EigenPodManager.sol b/src/contracts/pods/EigenPodManager.sol index eb3f36b0ee..c15b60f8fe 100644 --- a/src/contracts/pods/EigenPodManager.sol +++ b/src/contracts/pods/EigenPodManager.sol @@ -219,6 +219,12 @@ contract EigenPodManager is } } + /// @inheritdoc IShareManager + function increaseBurnableShares(IStrategy, uint256 addedSharesToBurn) external onlyDelegationManager { + burnableETHShares += addedSharesToBurn; + emit BurnableETHSharesIncreased(addedSharesToBurn); + } + // INTERNAL FUNCTIONS function _deployPod() internal returns (IEigenPod) { diff --git a/src/contracts/pods/EigenPodManagerStorage.sol b/src/contracts/pods/EigenPodManagerStorage.sol index c02d63bcc3..dc1281521a 100644 --- a/src/contracts/pods/EigenPodManagerStorage.sol +++ b/src/contracts/pods/EigenPodManagerStorage.sol @@ -78,6 +78,9 @@ abstract contract EigenPodManagerStorage is IEigenPodManager { /// Note: this is specifically updated when the staker's beacon chain balance decreases mapping(address staker => BeaconChainSlashingFactor) internal _beaconChainSlashingFactor; + /// @notice Returns the amount of `shares` that have been slashed on EigenLayer but not burned yet. + uint256 public burnableETHShares; + constructor(IETHPOSDeposit _ethPOS, IBeacon _eigenPodBeacon, IDelegationManager _delegationManager) { ethPOS = _ethPOS; eigenPodBeacon = _eigenPodBeacon; @@ -89,5 +92,5 @@ abstract contract EigenPodManagerStorage is IEigenPodManager { * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[43] private __gap; + uint256[42] private __gap; } diff --git a/src/test/mocks/DelegationManagerMock.sol b/src/test/mocks/DelegationManagerMock.sol index 771c4e502f..0c9ed77411 100644 --- a/src/test/mocks/DelegationManagerMock.sol +++ b/src/test/mocks/DelegationManagerMock.sol @@ -25,7 +25,7 @@ contract DelegationManagerMock is Test { isOperator[operator] = _isOperatorReturnValue; } - function burnOperatorShares( + function slashOperatorShares( address operator, IStrategy strategy, uint64 prevMaxMagnitude, diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index 6ca5869eb9..35573510ee 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -829,18 +829,16 @@ contract DelegationManagerUnitTests is EigenLayerUnitTestSetup, IDelegationManag } } - struct BurnOperatorSharesEmitStruct { + struct SlashOperatorSharesEmitStruct { address operator; IStrategy strategy; uint256 sharesToDecrease; uint256 sharesToBurn; } - function _burnOperatorShares_expectEmit(BurnOperatorSharesEmitStruct memory params) internal { + function _slashOperatorShares_expectEmit(SlashOperatorSharesEmitStruct memory params) internal { cheats.expectEmit(true, true, true, true, address(delegationManager)); emit OperatorSharesDecreased(params.operator, address(0), params.strategy, params.sharesToDecrease); - cheats.expectEmit(true, true, true, true, address(delegationManager)); - emit OperatorSharesBurned(params.operator, params.strategy, params.sharesToBurn); } /// ----------------------------------------------------------------------- @@ -4215,7 +4213,7 @@ contract DelegationManagerUnitTests_undelegate is DelegationManagerUnitTests { uint256 delegatedSharesBefore = delegationManager.operatorShares(defaultOperator, strategy); _setOperatorMagnitude(defaultOperator, strategy, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategy, prevMaxMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, strategy, prevMaxMagnitude, newMaxMagnitude); (, uint256 operatorSharesAfterSlash) = _assertOperatorSharesAfterSlash({ operator: defaultOperator, strategy: strategy, @@ -4340,7 +4338,7 @@ contract DelegationManagerUnitTests_undelegate is DelegationManagerUnitTests { { _setOperatorMagnitude(defaultOperator, strategy, operatorMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategy, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategy, WAD, 0); operatorSharesAfterSlash = delegationManager.operatorShares(defaultOperator, strategy); assertEq(operatorSharesAfterSlash, 0, "operator shares not fully slashed"); } @@ -4476,7 +4474,7 @@ contract DelegationManagerUnitTests_undelegate is DelegationManagerUnitTests { _setOperatorMagnitude(defaultOperator, strategyMock, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, prevMaxMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, prevMaxMagnitude, newMaxMagnitude); _assertOperatorSharesAfterSlash({ operator: defaultOperator, strategy: strategyMock, @@ -5222,7 +5220,7 @@ contract DelegationManagerUnitTests_queueWithdrawals is DelegationManagerUnitTes uint256 operatorSharesBefore = delegationManager.operatorShares(defaultOperator, strategyMock); _setOperatorMagnitude(defaultOperator, strategyMock, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, prevMaxMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, prevMaxMagnitude, newMaxMagnitude); // Assertions on amount burned (uint256 operatorSharesSlashed, ) = _assertOperatorSharesAfterSlash({ operator: defaultOperator, @@ -5318,7 +5316,7 @@ contract DelegationManagerUnitTests_queueWithdrawals is DelegationManagerUnitTes uint64 operatorMagnitude = 0; _setOperatorMagnitude(defaultOperator, strategyMock, operatorMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0); _assertOperatorSharesAfterSlash({ operator: defaultOperator, strategy: strategyMock, @@ -5602,7 +5600,7 @@ contract DelegationManagerUnitTests_queueWithdrawals is DelegationManagerUnitTes uint256[] memory slashedOperatorShares = new uint256[](strategies.length); for (uint256 i = 0; i < strategies.length; i++) { uint256 operatorSharesBefore = delegationManager.operatorShares(defaultOperator, strategies[i]); - delegationManager.burnOperatorShares(defaultOperator, strategies[i], prevMaxMagnitudes[i], newMaxMagnitudes[i]); + delegationManager.slashOperatorShares(defaultOperator, strategies[i], prevMaxMagnitudes[i], newMaxMagnitudes[i]); // Assert correct amount of shares slashed from operator (slashedOperatorShares[i], ) = _assertOperatorSharesAfterSlash({ operator: defaultOperator, @@ -5717,7 +5715,7 @@ contract DelegationManagerUnitTests_queueWithdrawals is DelegationManagerUnitTes cheats.startPrank(address(allocationManagerMock)); for (uint256 i = 0; i < strategies.length; i++) { uint256 operatorSharesBefore = delegationManager.operatorShares(defaultOperator, strategies[i]); - delegationManager.burnOperatorShares(defaultOperator, strategies[i], prevMaxMagnitudes[i], newMaxMagnitudes[i]); + delegationManager.slashOperatorShares(defaultOperator, strategies[i], prevMaxMagnitudes[i], newMaxMagnitudes[i]); // Assertions on amount burned (slashedOperatorShares[i], ) = _assertOperatorSharesAfterSlash({ @@ -5978,7 +5976,7 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage // Slash all of operator's shares _setOperatorMagnitude(defaultOperator, strategyMock, 0); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0); // Complete withdrawal as shares and assert that operator has no shares increased cheats.roll(block.number + 1); @@ -6197,7 +6195,7 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage }); _setOperatorMagnitude(defaultOperator, strategyMock, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, withdrawal.strategies[0], prevMaxMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, withdrawal.strategies[0], prevMaxMagnitude, newMaxMagnitude); uint256 operatorSharesAfterSlash = delegationManager.operatorShares(defaultOperator, strategyMock); assertEq( operatorSharesAfterSlash, @@ -6405,7 +6403,7 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage uint64 operatorMagnitude = 5e17; _setOperatorMagnitude(defaultOperator, withdrawal.strategies[0], operatorMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, withdrawal.strategies[0], WAD, operatorMagnitude); + delegationManager.slashOperatorShares(defaultOperator, withdrawal.strategies[0], WAD, operatorMagnitude); uint256 operatorSharesAfterAVSSlash = delegationManager.operatorShares(defaultOperator, beaconChainETHStrategy); assertApproxEqAbs(operatorSharesAfterAVSSlash, operatorSharesAfterBeaconSlash / 2, 1, "operator shares should be decreased after AVS slash"); } @@ -6574,26 +6572,26 @@ contract DelegationManagerUnitTests_completeQueuedWithdrawal is DelegationManage } } -contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests { +contract DelegationManagerUnitTests_slashingShares is DelegationManagerUnitTests { using ArrayLib for *; using SlashingLib for *; using Math for *; - /// @notice Verifies that `DelegationManager.burnOperatorShares` reverts if not called by the AllocationManager - function testFuzz_Revert_burnOperatorShares_invalidCaller(Randomness r) public rand(r) { + /// @notice Verifies that `DelegationManager.slashOperatorShares` reverts if not called by the AllocationManager + function testFuzz_Revert_slashOperatorShares_invalidCaller(Randomness r) public rand(r) { address invalidCaller = r.Address(); cheats.startPrank(invalidCaller); cheats.expectRevert(IDelegationManagerErrors.OnlyAllocationManager.selector); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, 0, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, 0, 0); } /// @notice Verifies that there is no change in shares if the staker is not delegatedd - function testFuzz_Revert_burnOperatorShares_noop() public { + function testFuzz_Revert_slashOperatorShares_noop() public { _registerOperatorWithBaseDetails(defaultOperator); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, WAD/2); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, WAD/2); assertEq(delegationManager.operatorShares(defaultOperator, strategyMock), 0, "shares should not have changed"); } @@ -6628,10 +6626,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // Slash all of operator's shares _setOperatorMagnitude(defaultOperator, strategyMock, 0); - cheats.expectEmit(true, true, true, true, address(delegationManager)); - emit OperatorSharesBurned(defaultOperator, strategyMock, depositAmount); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0); uint256 slashableSharesInQueueAfter = delegationManager.getSlashableSharesInQueue(defaultOperator, strategyMock); @@ -6695,7 +6691,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // Slash all of operator's shares _setOperatorMagnitude(defaultOperator, strategyMock, 0); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0); // Complete withdrawal as tokens and assert that we call back into teh SM with 100 tokens IERC20[] memory tokens = strategyMock.underlyingToken().toArray(); @@ -6760,13 +6756,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests strategyMock, depositAmount / 6 // 1 withdrawal not queued so decreased ); - cheats.expectEmit(true, true, true, true, address(delegationManager)); - emit OperatorSharesBurned( - defaultOperator, - strategyMock, - depositAmount / 6 * 4 // 4 parts are burned - ); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0); // Assert slashable shares slashableSharesInQueue = delegationManager.getSlashableSharesInQueue(defaultOperator, strategyMock); @@ -6774,10 +6764,10 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests } /** - * @notice Verifies that `DelegationManager.burnOperatorShares` properly decreases the delegated `shares` that the operator + * @notice Verifies that `DelegationManager.slashOperatorShares` properly decreases the delegated `shares` that the operator * who the `defaultStaker` is delegated to has in the strategies */ - function testFuzz_burnOperatorShares_slashedOperator(Randomness r) public rand(r) { + function testFuzz_slashOperatorShares_slashedOperator(Randomness r) public rand(r) { // sanity-filtering on fuzzed input length & staker IStrategy[] memory strategies = r.StrategyArray(16); uint256 shares = r.Uint256(1, MAX_STRATEGY_SHARES); @@ -6822,7 +6812,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests _delegateToOperatorWhoAcceptsAllStakers(defaultStaker, defaultOperator); address delegatedTo = delegationManager.delegatedTo(defaultStaker); - // check shares before call to `burnOperatorShares` + // check shares before call to `slashOperatorShares` for (uint256 i = 0; i < strategies.length; ++i) { // store delegated shares in a mapping delegatedSharesBefore[strategies[i]] = delegationManager.operatorShares(delegatedTo, strategies[i]); @@ -6848,7 +6838,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests strategies[i], sharesToDecrease ); - delegationManager.burnOperatorShares(defaultOperator, strategies[i], prevMaxMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, strategies[i], prevMaxMagnitude, newMaxMagnitude); // Also update maxMagnitude in ALM mock _setOperatorMagnitude(defaultOperator, strategies[i], newMaxMagnitude); @@ -6858,7 +6848,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests cheats.stopPrank(); } - // check shares after call to `burnOperatorShares` + // check shares after call to `slashOperatorShares` (uint256[] memory withdrawableShares, ) = delegationManager.getWithdrawableShares(defaultStaker, strategies); for (uint256 i = 0; i < strategies.length; ++i) { uint256 delegatedSharesAfter = delegationManager.operatorShares(delegatedTo, strategies[i]); @@ -6881,7 +6871,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * - Asserts slashable shares before and after in queue is 0 * - Asserts operator shares are decreased by half */ - function testFuzz_burnOperatorShares_NoQueuedWithdrawals( + function testFuzz_slashOperatorShares_NoQueuedWithdrawals( Randomness r ) public rand(r) { address operator = r.Address(); @@ -6906,8 +6896,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests uint256 sharesToBurn = shares/2; // Burn shares - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToBurn, @@ -6915,7 +6905,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: initMagnitude, @@ -6937,7 +6927,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * - Asserts operator shares are decreased by half after burning * - Asserts that the slashable shares in queue before/after burning are 0 */ - function testFuzz_burnOperatorShares_NoQueuedWithdrawalsInWindow( + function testFuzz_slashOperatorShares_NoQueuedWithdrawalsInWindow( Randomness r ) public rand(r) { // 1. Randomize operator and staker info @@ -6990,8 +6980,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 4. Burn shares _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToBurn, @@ -6999,7 +6989,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: WAD, @@ -7018,7 +7008,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * @notice Test burning shares for an operator with slashable queued withdrawals in past MIN_WITHDRAWAL_DELAY_BLOCKS window. * There exists a single withdrawal that is slashable. */ - function testFuzz_burnOperatorShares_SingleSlashableWithdrawal(Randomness r) public rand(r) { + function testFuzz_slashOperatorShares_SingleSlashableWithdrawal(Randomness r) public rand(r) { // 1. Randomize operator and staker info // Operator info address operator = r.Address(); @@ -7068,8 +7058,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 4. Burn shares _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToDecrease, @@ -7077,7 +7067,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: WAD, @@ -7096,7 +7086,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * @notice Test burning shares for an operator with slashable queued withdrawals in past MIN_WITHDRAWAL_DELAY_BLOCKS window. * There exists multiple withdrawals that are slashable. */ - function testFuzz_burnOperatorShares_MultipleSlashableWithdrawals( + function testFuzz_slashOperatorShares_MultipleSlashableWithdrawals( Randomness r ) public rand(r) { // 1. Randomize operator and staker info @@ -7159,8 +7149,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 4. Burn shares _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToDecrease, @@ -7168,7 +7158,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: WAD, @@ -7196,7 +7186,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * slashed amount for staker 1 should be 75% and staker 2 should be 50% where the total * slashed amount is the sum of both */ - function testFuzz_burnOperatorShares_MultipleWithdrawalsMultipleSlashings( + function testFuzz_slashOperatorShares_MultipleWithdrawalsMultipleSlashings( Randomness r ) public rand(r) { address operator = r.Address(); @@ -7233,8 +7223,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 3.2 Burn shares _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToDecrease, @@ -7242,7 +7232,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: WAD, @@ -7290,8 +7280,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 4.2 Burn shares _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: sharesToDecrease, @@ -7299,7 +7289,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: newMagnitude*2, @@ -7330,7 +7320,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * However if the withdrawal is not completable and the withdrawal delay hasn't elapsed, then the withdrawal * should be counted as slashable. */ - function testFuzz_burnOperatorShares_Timings(Randomness r) public rand(r) { + function testFuzz_slashOperatorShares_Timings(Randomness r) public rand(r) { // 1. Randomize operator and staker info // Operator info address operator = r.Address(); @@ -7395,8 +7385,8 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // 4. Burn 0 shares when new magnitude is set _setOperatorMagnitude(operator, strategyMock, newMagnitude); - _burnOperatorShares_expectEmit( - BurnOperatorSharesEmitStruct({ + _slashOperatorShares_expectEmit( + SlashOperatorSharesEmitStruct({ operator: operator, strategy: strategyMock, sharesToDecrease: 0, @@ -7404,7 +7394,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests }) ); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: strategyMock, prevMaxMagnitude: WAD, @@ -7427,7 +7417,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * and there are no slashable shares in the queue. Note: this will be implemented in a future release with * consideration of the Pectra upgrade. */ - function testFuzz_burnOperatorShares_BeaconChainStrategy(Randomness r) public rand(r) { + function testFuzz_slashOperatorShares_BeaconChainStrategy(Randomness r) public rand(r) { // 1. Randomize operator and staker info // Operator info address operator = r.Address(); @@ -7479,7 +7469,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests cheats.expectEmit(true, true, true, true, address(delegationManager)); emit OperatorSharesDecreased(operator, address(0), beaconChainETHStrategy, sharesToDecrease); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: operator, strategy: beaconChainETHStrategy, prevMaxMagnitude: WAD, @@ -7500,7 +7490,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests * We want this property otherwise undelegating/queue withdrawing all shares as a staker could lead to a underflow revert. * Note: If the SlashingLib.calcSlashedAmount function were to round down (overslash) then this test would fail. */ - function test_burnOperatorShares_slashedRepeatedly() public { + function test_slashOperatorShares_slashedRepeatedly() public { uint64 initialMagnitude = 90009; uint256 shares = 40000000004182209037560531097078597505; @@ -7523,7 +7513,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests _setOperatorMagnitude(defaultOperator, strategyMock, newOperatorMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares( + delegationManager.slashOperatorShares( defaultOperator, strategyMock, newOperatorMagnitude + slashMagnitude, @@ -7627,7 +7617,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests // do a slash via an AVS _setOperatorMagnitude(defaultOperator, beaconChainETHStrategy, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, beaconChainETHStrategy, initialMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator, beaconChainETHStrategy, initialMagnitude, newMaxMagnitude); // save the outcome (withdrawableShares,) = delegationManager.getWithdrawableShares(defaultStaker, beaconChainETHStrategy.toArray()); @@ -7682,7 +7672,7 @@ contract DelegationManagerUnitTests_burningShares is DelegationManagerUnitTests _setOperatorMagnitude(defaultOperator2, beaconChainETHStrategy, newMaxMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator2, beaconChainETHStrategy, initialMagnitude, newMaxMagnitude); + delegationManager.slashOperatorShares(defaultOperator2, beaconChainETHStrategy, initialMagnitude, newMaxMagnitude); uint256 expectedWithdrawable = _calcWithdrawableShares( uint256(beaconShares), @@ -7786,7 +7776,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -7870,7 +7860,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -7952,7 +7942,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -8029,7 +8019,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -8104,7 +8094,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -8183,7 +8173,7 @@ contract DelegationManagerUnitTests_SharesUnderflowChecks is DelegationManagerUn currMagnitude -= slashMagnitude; _setOperatorMagnitude(defaultOperator, strategyMock, currMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares({ + delegationManager.slashOperatorShares({ operator: defaultOperator, strategy: strategyMock, prevMaxMagnitude: currMagnitude + slashMagnitude, @@ -8320,7 +8310,7 @@ contract DelegationManagerUnitTests_Lifecycle is DelegationManagerUnitTests { { _setOperatorMagnitude(defaultOperator, strategy, operatorMagnitude); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategy, WAD, 0); + delegationManager.slashOperatorShares(defaultOperator, strategy, WAD, 0); operatorSharesAfterSlash = delegationManager.operatorShares(defaultOperator, strategy); assertEq(operatorSharesAfterSlash, 0, "operator shares not fully slashed"); } @@ -8552,7 +8542,7 @@ contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUni uint256 newStakerShares = depositShares[i] / 2; _setOperatorMagnitude(defaultOperator, strategies[i], 0.5 ether); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategies[i], WAD, 0.5 ether); + delegationManager.slashOperatorShares(defaultOperator, strategies[i], WAD, 0.5 ether); uint256 afterSlash = delegationManager.operatorShares(defaultOperator, strategies[i]); assertApproxEqAbs(afterSlash, newStakerShares, 1, "bad operator shares after slash"); } @@ -8595,7 +8585,7 @@ contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUni uint256 newStakerShares = totalDepositShares / 2; _setOperatorMagnitude(defaultOperator, strategyMock, 0.5 ether); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, strategyMock, WAD, 0.5 ether); + delegationManager.slashOperatorShares(defaultOperator, strategyMock, WAD, 0.5 ether); uint256 afterSlash = delegationManager.operatorShares(defaultOperator, strategyMock); assertApproxEqAbs(afterSlash, newStakerShares, 1, "bad operator shares after slash"); @@ -8698,7 +8688,7 @@ contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUni }); _setOperatorMagnitude(defaultOperator, strategyMock, 50e16); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, withdrawal.strategies[0], uint64(WAD), 50e16); + delegationManager.slashOperatorShares(defaultOperator, withdrawal.strategies[0], uint64(WAD), 50e16); uint256 operatorSharesAfterSlash = delegationManager.operatorShares(defaultOperator, strategyMock); assertEq( operatorSharesAfterSlash, @@ -8729,7 +8719,7 @@ contract DelegationManagerUnitTests_getQueuedWithdrawals is DelegationManagerUni }); _setOperatorMagnitude(defaultOperator, strategyMock, 25e16); cheats.prank(address(allocationManagerMock)); - delegationManager.burnOperatorShares(defaultOperator, withdrawal.strategies[0], 50e16, 25e16); + delegationManager.slashOperatorShares(defaultOperator, withdrawal.strategies[0], 50e16, 25e16); uint256 operatorSharesAfterSecondSlash = delegationManager.operatorShares(defaultOperator, strategyMock); assertEq( operatorSharesAfterSecondSlash, diff --git a/src/test/unit/EigenPodManagerUnit.t.sol b/src/test/unit/EigenPodManagerUnit.t.sol index 72befd4fdf..f1286f0316 100644 --- a/src/test/unit/EigenPodManagerUnit.t.sol +++ b/src/test/unit/EigenPodManagerUnit.t.sol @@ -521,4 +521,48 @@ contract EigenPodManagerUnitTests_BeaconChainETHBalanceUpdateTests is EigenPodMa assertEq(eigenPodManager.podOwnerDepositShares(defaultStaker), int(sharesBefore), "Shares should not be adjusted"); assertTrue(eigenPodManager.beaconChainSlashingFactor(defaultStaker) <= prevSlashingFactor, "bcsf should always decrease"); } -} \ No newline at end of file +} + +contract EigenPodManagerUnitTests_increaseBurnableShares is EigenPodManagerUnitTests { + function testFuzz_onlyDelegationManager(address invalidCaller) public filterFuzzedAddressInputs(invalidCaller) { + cheats.assume(invalidCaller != address(delegationManagerMock)); + cheats.prank(invalidCaller); + cheats.expectRevert(IEigenPodManagerErrors.OnlyDelegationManager.selector); + eigenPodManager.increaseBurnableShares(beaconChainETHStrategy, 1 ether); + } + + function testFuzz_singleDeposit(uint256 increasedBurnableShares) public { + cheats.expectEmit(true, true, true, true, address(eigenPodManager)); + emit BurnableETHSharesIncreased(increasedBurnableShares); + + cheats.prank(address(delegationManagerMock)); + eigenPodManager.increaseBurnableShares(beaconChainETHStrategy, increasedBurnableShares); + + assertEq(eigenPodManager.burnableETHShares(), increasedBurnableShares, "Burnable shares not updated correctly"); + } + + function testFuzz_existingDeposit( + uint256 existingBurnableShares, + uint256 increasedBurnableShares + ) public { + // prevent overflow + cheats.assume(existingBurnableShares < type(uint256).max - increasedBurnableShares); + + cheats.expectEmit(true, true, true, true, address(eigenPodManager)); + emit BurnableETHSharesIncreased(existingBurnableShares); + cheats.prank(address(delegationManagerMock)); + eigenPodManager.increaseBurnableShares(beaconChainETHStrategy, existingBurnableShares); + + assertEq(eigenPodManager.burnableETHShares(), existingBurnableShares, "Burnable shares not setup correctly"); + + cheats.expectEmit(true, true, true, true, address(eigenPodManager)); + emit BurnableETHSharesIncreased(increasedBurnableShares); + cheats.prank(address(delegationManagerMock)); + eigenPodManager.increaseBurnableShares(beaconChainETHStrategy, increasedBurnableShares); + + assertEq( + eigenPodManager.burnableETHShares(), + existingBurnableShares + increasedBurnableShares, "Burnable shares not updated correctly" + ); + } +} diff --git a/src/test/unit/StrategyManagerUnit.t.sol b/src/test/unit/StrategyManagerUnit.t.sol index 1f8484fc75..d5ba4146ee 100644 --- a/src/test/unit/StrategyManagerUnit.t.sol +++ b/src/test/unit/StrategyManagerUnit.t.sol @@ -1450,33 +1450,62 @@ contract StrategyManagerUnitTests_withdrawSharesAsTokens is StrategyManagerUnitT } } -contract StrategyManagerUnitTests_burnShares is StrategyManagerUnitTests { +contract StrategyManagerUnitTests_increaseBurnableShares is StrategyManagerUnitTests { function test_Revert_DelegationManagerModifier() external { DelegationManagerMock invalidDelegationManager = new DelegationManagerMock(); cheats.prank(address(invalidDelegationManager)); cheats.expectRevert(IStrategyManagerErrors.OnlyDelegationManager.selector); - strategyManager.burnShares(dummyStrat, 1); + strategyManager.increaseBurnableShares(dummyStrat, 1); } - /** - * @notice deposits a single strategy and withdrawSharesAsTokens(). Tests that we revert when we - * burn more than expected - */ - function testFuzz_RevertShareAmountTooHigh( - address staker, - uint256 depositAmount, - uint256 sharesToBurn - ) external filterFuzzedAddressInputs(staker) { - cheats.assume(staker != address(0)); - cheats.assume(depositAmount > 0 && depositAmount < dummyToken.totalSupply() && depositAmount < sharesToBurn); + function testFuzz_increaseBurnableShares(uint256 addedSharesToBurn) external { IStrategy strategy = dummyStrat; - _depositIntoStrategySuccessfully(strategy, staker, depositAmount); + + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesIncreased(strategy, addedSharesToBurn); + cheats.prank(address(delegationManagerMock)); + strategyManager.increaseBurnableShares(strategy, addedSharesToBurn); + assertEq( + strategyManager.burnableShares(strategy), + addedSharesToBurn, + "strategyManager.burnableShares(strategy) != addedSharesToBurn" + ); + } + + function testFuzz_increaseBurnableShares_existingShares( + uint256 existingBurnableShares, + uint256 addedSharesToBurn + ) external { + // preventing fuzz overflow, in practice StrategyBase has a 1e38 - 1 maxShares limit so this won't + // be an issue on mainnet/testnet environments + existingBurnableShares = bound(existingBurnableShares, 1, type(uint256).max/2); + addedSharesToBurn = bound(addedSharesToBurn, 1, type(uint256).max/2); + IStrategy strategy = dummyStrat; cheats.prank(address(delegationManagerMock)); - cheats.expectRevert(IStrategyErrors.WithdrawalAmountExceedsTotalDeposits.selector); - strategyManager.burnShares(strategy, sharesToBurn); + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesIncreased(strategy, existingBurnableShares); + strategyManager.increaseBurnableShares(strategy, existingBurnableShares); + assertEq( + strategyManager.burnableShares(strategy), + existingBurnableShares, + "strategyManager.burnableShares(strategy) != existingBurnableShares" + ); + + cheats.prank(address(delegationManagerMock)); + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesIncreased(strategy, addedSharesToBurn); + strategyManager.increaseBurnableShares(strategy, addedSharesToBurn); + + assertEq( + strategyManager.burnableShares(strategy), + existingBurnableShares + addedSharesToBurn, + "strategyManager.burnableShares(strategy) != existingBurnableShares + addedSharesToBurn" + ); } +} +contract StrategyManagerUnitTests_burnShares is StrategyManagerUnitTests { function testFuzz_SingleStrategyDeposited( address staker, uint256 depositAmount, @@ -1488,18 +1517,22 @@ contract StrategyManagerUnitTests_burnShares is StrategyManagerUnitTests { IStrategy strategy = dummyStrat; IERC20 token = dummyToken; _depositIntoStrategySuccessfully(strategy, staker, depositAmount); + + // slash shares and increase amount to burn from DelegationManager + cheats.prank(address(delegationManagerMock)); + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesIncreased(strategy, sharesToBurn); + strategyManager.increaseBurnableShares(strategy, sharesToBurn); + uint256 strategyBalanceBefore = token.balanceOf(address(strategy)); uint256 burnAddressBalanceBefore = token.balanceOf(strategyManager.DEFAULT_BURN_ADDRESS()); cheats.prank(address(delegationManagerMock)); - strategyManager.burnShares(strategy, sharesToBurn); + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesDecreased(strategy, sharesToBurn); + strategyManager.burnShares(strategy); uint256 strategyBalanceAfter = token.balanceOf(address(strategy)); uint256 burnAddressBalanceAfter = token.balanceOf(strategyManager.DEFAULT_BURN_ADDRESS()); - console.log(strategyBalanceAfter); - console.log(strategyBalanceBefore); - console.log(strategyBalanceBefore - sharesToBurn); - console.log(sharesToBurn); - assertEq( strategyBalanceBefore - sharesToBurn, strategyBalanceAfter, @@ -1513,7 +1546,7 @@ contract StrategyManagerUnitTests_burnShares is StrategyManagerUnitTests { } /// @notice check that balances are unchanged with a reverting token but burnShares doesn't revert - function testFuzz_revertTryCatchWithRevertToken( + function testFuzz_BurnableSharesUnchangedWithRevertToken( address staker, uint256 depositAmount, uint256 sharesToBurn @@ -1524,13 +1557,25 @@ contract StrategyManagerUnitTests_burnShares is StrategyManagerUnitTests { IERC20 token = dummyToken; _depositIntoStrategySuccessfully(strategy, staker, depositAmount); + // slash shares and increase amount to burn from DelegationManager + cheats.prank(address(delegationManagerMock)); + cheats.expectEmit(true, true, true, true, address(strategyManager)); + emit BurnableSharesIncreased(strategy, sharesToBurn); + strategyManager.increaseBurnableShares(strategy, sharesToBurn); + // Now set token to be contract that reverts simulating an upgrade cheats.etch(address(token), address(revertToken).code); ERC20_SetTransferReverting_Mock(address(token)).setTransfersRevert(true); cheats.expectRevert("SafeERC20: low-level call failed"); cheats.prank(address(delegationManagerMock)); - strategyManager.burnShares(strategy, sharesToBurn); + strategyManager.burnShares(strategy); + + assertEq( + strategyManager.burnableShares(strategy), + sharesToBurn, + "burnable shares should be unchanged" + ); } }