## Slashing Release - Beacon Chain ETH Changes [TOC] ### Share Accounting Changes Share accounting is changing. When an `EigenPod's` checkpoint is completed, a negative balance delta no longer reduces your shares. Instead, the proportion of your new and previous balances are accumulated in your "beacon chain slashing factor," a monotonically-decreasing value the `EigenPodManager` uses to keep track of how many assets the pod's shares actually correspond to ([link to code](https://github.com/Layr-Labs/eigenlayer-contracts/blob/slashing-magnitudes/src/contracts/pods/EigenPodManager.sol#L104-L131)): ```solidity /** * @notice Returns the historical sum of proportional balance decreases a pod owner has experienced when * updating their pod's balance. */ function beaconChainSlashingFactor( address staker ) external view returns (uint64); ``` For example, say your `EigenPod` has 32 ETH worth of native ETH shares. If your validator accrued a 16 ETH slash and this was reported in a checkpoint, the `EigenPodManager` would: * Keep your `stakerDepositShares` equal to 32 ETH * Calculate the assets actually backing the pod as a proportion of `WAD` (`16 ETH * (WAD/32 ETH) == 0.5 WAD`) * Multiply this into your existing beacon chain slashing factor. Since this is `WAD` by default, your new beacon chain slashing factor would be `WAD * (0.5 WAD / WAD) == 0.5 WAD` If you then restaked a new validator with 32 ETH, the `EigenPodManager` would increase your `stakerDepositShares` to 64 ETH. However, the amount the `DelegationManager` delegates to your operator (or allows you to queue for withdrawal) is based in part off of your beacon chain slashing factor. In this case, the amount delegated / withdrawable would be 48 ETH, equal to the actual assets backing your pod. **What you need to know**: * `EigenPodManager.stakerDepositShares` will no longer return a negative value * If your pod reports a balance decrease, `stakerDepositShares` will not decrease. Instead, `EigenPodManager.beaconChainSlashingFactor(staker)` will be updated to reflect this * **Note** that "balance decrease" specifically means the sum of your validator balances and your pod's native ETH balance is _strictly less_ than it was the last time you completed a checkpoint. This should only happen if you suffer from inactivity penalties or are slashed on the beacon chain. * You can calculate the actual delegatable/withdrawable shares for the beacon chain ETH strategy using `DelegationManager.getWithdrawableShares`: ```solidity /** * @notice Given a staker and a set of strategies, return the shares they can queue for withdrawal and the * corresponding depositShares. * This value depends on which operator the staker is delegated to. * The shares amount returned is the actual amount of Strategy shares the staker would receive (subject * to each strategy's underlying shares to token ratio). */ function getWithdrawableShares( address staker, IStrategy[] memory strategies ) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares); ``` ### `EigenPod` Changes To accommodate the accounting changes described above, there are some small changes coming to `EigenPods`: ##### `Checkpoint` struct definition _The `Checkpoint` struct definition is changing_ to accommodate a new "previous balance" calculation used to update your beacon chain slashing factor: ```solidity struct Checkpoint { bytes32 beaconBlockRoot; uint24 proofsRemaining; uint64 podBalanceGwei; int64 balanceDeltasGwei; uint64 prevBeaconBalanceGwei; } ``` Note that `balanceDeltasGwei` is now an `int64` (down from `int128`), and there is a new field, `prevBeaconBalanceGwei`, which keeps track of the sum of prior validator balances for each validator proven in a checkpoint. ##### Checkpoint finalization _When finalizing a checkpoint, it is no longer deleted from state._ The current behavior is to delete both `currentCheckpoint` and `currentCheckpointTimestamp`, setting them both back to zero ([link](https://github.com/Layr-Labs/eigenlayer-contracts/blob/v0.4.3-mainnet-rewards-foundation-incentives/src/contracts/pods/EigenPod.sol#L663-L666)). As of the slashing release, only the `currentCheckpointTimestamp` will be deleted ([link](https://github.com/Layr-Labs/eigenlayer-contracts/blob/601f8e24752e8617d33242912d7f85f111a47c01/src/contracts/pods/EigenPod.sol#L645-L649)). This is unrelated to the above changes, but saves gas when starting a new checkpoint - as a checkpoint's storage slots no longer need to be initialized from 0. ### Pre-Release Migration In order to accommodate the changes to `EigenPods`, we will be performing a brief "migration" just before the slashing release. The current plans for this are, roughly: * ~1-2 hours before the slashing release is live on mainnet, the `EigenPod.startCheckpoint` method will be paused for all `EigenPods`. * We will run a script to _complete any outstanding checkpoints_ for all `EigenPods`. * When the slashing release is executed, `EigenPod.startCheckpoint` will be unpaused and normal operations can resume. ### Edge Cases ##### Fully Slashed Your beacon chain slashing factor starts at `1 WAD` (1e18), and decreases as your pod reports balance decreases through checkpoints. _If at any point your beacon chain slashing factor hits 0, the `DelegationManager` will be unable to process balance increases, undelegations, or withdrawals for your pod._ In essence, your pod will be bricked - as trying to add new validators, undelegating, or queueing withdrawals will [result in a revert](https://github.com/Layr-Labs/eigenlayer-contracts/blob/slashing-magnitudes/src/contracts/core/DelegationManager.sol#L536-L538). However, this "fully slashed" case should only occur in the extreme case where **all** of your pod's validators are slashed down to 0, _and_ you have no ETH balance in your `EigenPod`. ##### Finishing Legacy Withdrawals _If you have negative `stakerDepositShares` as of the slashing release,_ you will be unable to complete a checkpoint or add new validators to your pod. See the relevant [check and explanation here](https://github.com/Layr-Labs/eigenlayer-contracts/blob/slashing-magnitudes/src/contracts/pods/EigenPodManager.sol#L95-L102). To address this case, you will need to complete any existing withdrawals in the `DelegationManager` with `receiveAsTokens == false`.