Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: burn erc20s on slashing #881

Open
wants to merge 9 commits into
base: slashing-magnitudes
Choose a base branch
from
Open

Conversation

8sunyuan
Copy link
Collaborator

@8sunyuan 8sunyuan commented Nov 8, 2024

Synchronous Burning

One solution for burning slashed shares is to simply take the existing logic, take the sharesToDecrement in calcSlashedAmount and just burn that amount. But for all shares that were withdrawn and are still slashable for MIN_WITHDRAWAL_DELAY_BLOCKS, they would have to be slashed and burned when those withdrawals are completed.

Instead, completed withdrawals don't burn and we calculate all the shares to burn upon slashing. We burn synchronously all those slashabe shares in the queue by reading all the cumulative withdrawn shares from the time of slashing and MIN_WITHDRAWAL_DELAY_BLOCKS into the past. Here is where checkpointed values come into play again.

Changes:

  • Snapshots.sol: Added back OZ CheckpointsUpgradeable library for blocknumbers to the Snapshots library. The reasoning is because we want to keep track of cumulative queue withdrawn shares from an operator for a specific strategy and not using a default WAD value like we use for magnitudes.
  • DelegationManager.sol: renamed function decreaseAndBurnOperatorShares which will now read all the slashable shares queue withdrawn from an operator for a specific strategy, calculate amount of shares to burn, and call StrategyManager.burnShares.
  • StrategyManager.sol: burnShares function is exact same as the withdraw function but with the destination address being the DEFAULT_BURN_ADDRESS (address 0).
  • SlashingLib.sol: Changed calcSlashedAmount back to taking in as input prevMaxMagnitude and newMaxMagnitude because the way that burned shares are calculated with cumulative scaled shares.

Note: The call trace begins from ALM.slashOperator -> DM.decreaseAndBurnOperatorShares -> SM.burnShares -> Strategy.withdraw -> underlyingToken.transfer Each of these calls are permissioned by the core contracts in the protocol with the exception of slashOperator which is only callable by the AVS. We may want to additionally consider for a reentrancy guard on slashOperator as a result.

TODO:

  • Added unit and integration tests

@@ -26,6 +26,9 @@ abstract contract StrategyManagerStorage is IStrategyManager {
// index for flag that pauses deposits when set
uint8 internal constant PAUSED_DEPOSITS = 0;

/// @notice default address for burning slashed shares and transferring underlying tokens
address public constant DEFAULT_BURN_ADDRESS = address(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do some analysis on if this is ok for LSTs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for sure not, placeholder value for now. Personally a fan of 0xdeadbeef

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

91a806b
0xDeaDBeef

Copy link
Collaborator

@ypatil12 ypatil12 Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should at least do 0x000000000000000000000000000000000000dEaD or address(0) since other protocols use that. Working with Matt Nelson to get feedback

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we cannot do address(0) given that stETH's contract

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0x E 1 6 E 4 (eigen)

* withdrawal snapshot is probably "recent", defined as being among the last sqrt(N) withdrawal snapshots where N is the number of
* withdrawal snapshots.
*/
function getAtProbablyRecentBlock(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just do upperLookup imo. is this any different?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same logic but named more clearly for blocknumber usage. I can change this back though to be more consistent with DefaultWadHistory.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changing the name makes it clearer to me imo

@@ -685,6 +699,26 @@ contract DelegationManager is
_beaconChainSlashingFactor[staker] = bsf;
}

/// @dev Calculate amount of withdrawable shares from an operator for a strategy that is still in the queue
/// and therefore slashable.
function _getSlashableSharesInQueue(address operator, IStrategy strategy) internal view returns (uint256) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we expose a public view func for this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IStrategy strategy,
uint256 queueWithdrawnShares
) internal {
uint256 currCumulativeWithdrawalShares = uint256(_cumulativeWithdrawalsHistory[operator][strategy].latest());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this PR looks nice!

my main feedback is that we should store cumulative scaled shares queued for withdrawal, not shares.

Upon burning we should multiply the scaled shares in the withdrawal queue by the slashed magnitude. This would make it so that view functions for introspection into the withdrawal queue automatically update to reflect correct values after slashing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

138eef7
Added, had to change calcSlashedAmount back to old interface but it is more consistent with the way scaledShares are also calculated.

Copy link

Reading tracefile ./lcov.info.pruned
                                        |Lines       |Functions  |Branches    
Filename                                  |Rate     Num|Rate    Num|Rate     Num
================================================================================
[src/contracts/]
core/AVSDirectory.sol                     | 100%     16| 100%     7|    -      0
core/AllocationManager.sol                |90.0%    229|89.2%    37|    -      0
core/DelegationManager.sol                |91.4%    222|87.8%    41|    -      0
core/RewardsCoordinator.sol               |94.3%    123|87.1%    31|    -      0
core/StrategyManager.sol                  |88.1%     67|82.6%    23|    -      0
libraries/BeaconChainProofs.sol           | 100%     22| 100%    11|    -      0
libraries/BytesLib.sol                    | 0.0%    156| 0.0%    14|    -      0
libraries/Endian.sol                      | 100%      2| 100%     1|    -      0
libraries/Merkle.sol                      | 100%     38| 100%     5|    -      0
libraries/OperatorSetLib.sol              | 100%      2| 100%     2|    -      0
libraries/SlashingLib.sol                 | 100%     19| 100%    10|    -      0
libraries/Snapshots.sol                   |76.3%     59|87.5%     8|    -      0
mixins/SignatureUtils.sol                 | 100%      7| 100%     5|    -      0
permissions/Pausable.sol                  |94.7%     19|90.0%    10|    -      0
permissions/PauserRegistry.sol            | 100%     12| 100%     6|    -      0
pods/EigenPod.sol                         | 100%    131|96.2%    26|    -      0
pods/EigenPodManager.sol                  | 100%     68|93.3%    15|    -      0
strategies/EigenStrategy.sol              | 0.0%     10| 0.0%     4|    -      0
strategies/StrategyBase.sol               |90.9%     44|78.9%    19|    -      0
strategies/StrategyBaseTVLLimits.sol      | 100%     12| 100%     5|    -      0
strategies/StrategyFactory.sol            | 100%     32| 100%     8|    -      0
token/BackingEigen.sol                    |83.3%     30|69.2%    13|    -      0
token/Eigen.sol                           |45.0%     40|61.5%    13|    -      0
================================================================================
                                  Total:|80.2%   1360|83.4%   314|    -      0

1 similar comment
Copy link

Reading tracefile ./lcov.info.pruned
                                        |Lines       |Functions  |Branches    
Filename                                  |Rate     Num|Rate    Num|Rate     Num
================================================================================
[src/contracts/]
core/AVSDirectory.sol                     | 100%     16| 100%     7|    -      0
core/AllocationManager.sol                |90.0%    229|89.2%    37|    -      0
core/DelegationManager.sol                |91.4%    222|87.8%    41|    -      0
core/RewardsCoordinator.sol               |94.3%    123|87.1%    31|    -      0
core/StrategyManager.sol                  |88.1%     67|82.6%    23|    -      0
libraries/BeaconChainProofs.sol           | 100%     22| 100%    11|    -      0
libraries/BytesLib.sol                    | 0.0%    156| 0.0%    14|    -      0
libraries/Endian.sol                      | 100%      2| 100%     1|    -      0
libraries/Merkle.sol                      | 100%     38| 100%     5|    -      0
libraries/OperatorSetLib.sol              | 100%      2| 100%     2|    -      0
libraries/SlashingLib.sol                 | 100%     19| 100%    10|    -      0
libraries/Snapshots.sol                   |76.3%     59|87.5%     8|    -      0
mixins/SignatureUtils.sol                 | 100%      7| 100%     5|    -      0
permissions/Pausable.sol                  |94.7%     19|90.0%    10|    -      0
permissions/PauserRegistry.sol            | 100%     12| 100%     6|    -      0
pods/EigenPod.sol                         | 100%    131|96.2%    26|    -      0
pods/EigenPodManager.sol                  | 100%     68|93.3%    15|    -      0
strategies/EigenStrategy.sol              | 0.0%     10| 0.0%     4|    -      0
strategies/StrategyBase.sol               |90.9%     44|78.9%    19|    -      0
strategies/StrategyBaseTVLLimits.sol      | 100%     12| 100%     5|    -      0
strategies/StrategyFactory.sol            | 100%     32| 100%     8|    -      0
token/BackingEigen.sol                    |83.3%     30|69.2%    13|    -      0
token/Eigen.sol                           |45.0%     40|61.5%    13|    -      0
================================================================================
                                  Total:|80.2%   1360|83.4%   314|    -      0

// Staker was delegated and remains slashable during the withdrawal delay period
// Cumulative withdrawn scaled shares are updated for the strategy, this is for accounting
// purposes for burning shares if slashed
_updateCumulativeScaledShares(operator, strategies[i], scaledShares[i]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't want to do this for beaconchain ETH, because this value is sorta useless since it doesn't take slashing factors into account

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, yes this only for SM Strategies

Base automatically changed from alex/dm-refactor to slashing-magnitudes November 14, 2024 16:03
Copy link

Reading tracefile ./lcov.info.pruned
                                        |Lines       |Functions  |Branches    
Filename                                  |Rate     Num|Rate    Num|Rate     Num
================================================================================
[src/contracts/]
core/AVSDirectory.sol                     | 100%     16| 100%     7|    -      0
core/AllocationManager.sol                |90.0%    229|89.2%    37|    -      0
core/DelegationManager.sol                |91.5%    223|87.8%    41|    -      0
core/RewardsCoordinator.sol               |94.3%    123|87.1%    31|    -      0
core/StrategyManager.sol                  |88.1%     67|82.6%    23|    -      0
libraries/BeaconChainProofs.sol           | 100%     22| 100%    11|    -      0
libraries/BytesLib.sol                    | 0.0%    156| 0.0%    14|    -      0
libraries/Endian.sol                      | 100%      2| 100%     1|    -      0
libraries/Merkle.sol                      | 100%     38| 100%     5|    -      0
libraries/OperatorSetLib.sol              | 100%      2| 100%     2|    -      0
libraries/SlashingLib.sol                 | 100%     19| 100%    10|    -      0
libraries/Snapshots.sol                   |76.3%     59|87.5%     8|    -      0
mixins/SignatureUtils.sol                 | 100%      7| 100%     5|    -      0
permissions/Pausable.sol                  |94.7%     19|90.0%    10|    -      0
permissions/PauserRegistry.sol            | 100%     12| 100%     6|    -      0
pods/EigenPod.sol                         | 100%    131|96.2%    26|    -      0
pods/EigenPodManager.sol                  | 100%     68|93.3%    15|    -      0
strategies/EigenStrategy.sol              | 0.0%     10| 0.0%     4|    -      0
strategies/StrategyBase.sol               |90.9%     44|78.9%    19|    -      0
strategies/StrategyBaseTVLLimits.sol      | 100%     12| 100%     5|    -      0
strategies/StrategyFactory.sol            | 100%     32| 100%     8|    -      0
token/BackingEigen.sol                    |83.3%     30|69.2%    13|    -      0
token/Eigen.sol                           |45.0%     40|61.5%    13|    -      0
================================================================================
                                  Total:|80.2%   1361|83.4%   314|    -      0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants