# v0.2.3 (m2 mainnet release) Reference: * [Mainnet release commit](https://github.com/Layr-Labs/eigenlayer-contracts/commit/90a0f6aee79b4a38e1b63b32f9627f21b1162fbb) --- Introducing the newest version of the EigenLayer core contracts! This is a massive release and contract upgrade that builds on 2023's m1 release. M2 removes unused code, rearchitects core system components, and introduces several new features: * **Operators can now register with EigenLayer** * **Stakers can now delegate stake to Operators** * **AVSs can now accept Operator registrations** Together, these features mean that Operators can now provide services to AVSs, and AVSs can weight Operators based on their delegated stake. Note, though, that slashing and in-protocol payments are not yet implemented. These features are under active development by EigenLabs. There are two additional major changes to highlight: * **Withdrawal processing is now handled in the `DelegationManager`** for LST shares and beacon chain ETH shares. Previously, this was handled in the `StrategyManager`. * **EigenPods are now more fully-featured**, supporting various proofs against beacon chain state. EigenPod-using Stakers will need to submit these state proofs in order to (i) receive delegatable beacon chain ETH shares and (ii) exit their validators and withdraw their assets. For more info on these two changes, see the contract changelogs or [migrations](#Migrations) sections below. **Finally**: this release comes with a TON of documentation to help you understand how the m2 contracts work. Please look through our [`/docs`](https://github.com/Layr-Labs/eigenlayer-contracts/tree/mainnet/docs) folder! It should answer a lot of questions. ### Contents [TOC] ### New Features by Contract #### `AVSDirectory` A new contract that allows an AVS to register/deregister Operators with the AVS within the core contracts. *New methods:* * `registerOperatorToAVS`: Allows an AVS to submit a signature from an Operator, recording that Operator as registered to the AVS * `deregisterOperatorFromAVS`: Allows an AVS to declare an Operator deregistered *See the full docs here: [`docs/core/AVSDirectory.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/AVSDirectory.md).* #### `DelegationManager` The `DelegationManager` was included in the previous mainnet release, but has been completely paused since the m1 launch. The m2 upgrade unpauses this contract and also refactors it completely from its m1 version. *New methods:* * `registerAsOperator`: Allows anyone to register as an Operator. Operators can register for AVSs using the AVS's contracts. * *Note:* Registering as an Operator is not reversible. * `delegateTo`: Allows a Staker to delegate 100% of their shares to an Operator. Partial delegation is not supported. * `delegateToBySignature`: Allows a third party to delegate a Staker to an Operator on the Staker's behalf (requires a valid signature). * `undelegate`: Allows a Staker to undelegate from an Operator, or an Operator to force-undelegate a Staker. Undelegation also queues a withdrawal on behalf of the Staker. *Changed methods:* * `queueWithdrawals`: Allows a Staker to queue a withdrawal of their shares for any Strategy (LSTs or beacon chain ETH). * *Note:* this method was originally in the `StrategyManager`. It has been removed from the `StrategyManager`; all withdrawal processing now takes place in the `DelegationManager`. * *Note*: this method originally allowed a Staker to specify a third party to receive a withdrawal. This functionality has been removed. * `completeQueuedWithdrawals`: Allows a Staker to complete a queued withdrawal after the withdrawal delay has passed. Stakers can choose to complete their withdrawal *as shares* to "stay in the system," or *as tokens* to "exit the system." * *Note:* this method was originally in the `StrategyManager`. It has been removed from the `StrategyManager`; all withdrawal processing now takes place in the `DelegationManager`. *See the full docs here: [`docs/core/DelegationManager.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/DelegationManager.md).* #### `StrategyManager` The `StrategyManager's` changes are primarily removed methods. The m1 `StrategyManager` was conceptually overloaded, performing lots of tasks better suited for other contracts. This release simplifies the `StrategyManager` significantly: its primary function now is to allow Stakers to deposit LSTs into Strategies, and to manage Staker share accounting between Strategies. *New methods:* * `addShares`, `removeShares`, `withdrawSharesAsTokens`: These methods are *only callable by the `DelegationManager`*, and are used to manage staker share balances during withdrawal processing. *Removed methods (beacon chain ETH):* * `depositBeaconChainETH` * `recordOvercommittedBeaconChainETH` In m1, both of these methods would have been used to record share changes for Stakers in the beacon chain ETH strategy. However, because beacon chain state proofs were not enabled, there was no way for Stakers to receive shares for their beacon chain ETH. These methods have been removed entirely, and any related functionality moved to the `EigenPodManager`. *Removed methods (delegation):* * `undelegate` * `queueWithdrawal` * `completeQueuedWithdrawal` In m1, `undelegate` was paused because delegation was not fully implemented. As of m2, both delegation/undelegation and queuing/completing withdrawals are handled in the `DelegationManager`. See [migrations](#Migrations) for details on migrating m1 queued withdrawals to the `DelegationManager`. *Removed methods (slashing):* * `slashShares` * `slashQueuedWithdrawal` In m1, both of these methods were paused because slashing was not fully implemented. As of m2, slashing is still not implemented, so we opted to remove these methods to avoid confusion. *Additional Changes:* * Removed several calls to the `Slasher` contract, as well as references to "frozen" addresses. These were all no-ops in m1, and are being removed in m2 solely to clarify existing features. We will reintroduce these when we release slashing. *See the full docs here: [`docs/core/StrategyManager.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/StrategyManager.md).* #### `EigenPodManager` The `EigenPodManager` no longer interacts with the `StrategyManager`. Instead, it primarily interacts with the `DelegationManager` when relaying delegated share changes, or during withdrawal processing. Additionally, now that beacon chain state proofs are active, `EigenPods` can now provide beacon chain proofs in exchange for delegatable shares in the "beacon chain ETH strategy." The `EigenPodManager` keeps track of a Staker's delegatable shares, and updates the `DelegationManager` when they change. *New methods:* * `recordBeaconChainETHBalanceUpdate`: Only callable by an `EigenPod`. Used to add/subtract shares when a beacon chain proof updates their validator's balance. * `addShares`, `removeShares`, `withdrawSharesAsTokens`: These methods are *only callable by the `DelegationManager`*, and are used to manage staker share balances during withdrawal processing. *Changed methods:* * `createPod`: Now returns the address of the created `EigenPod`. *Removed methods (withdrawals):* * `withdrawRestakedBeaconChainETH`: As part of moving withdrawal processing to the `DelegationManager`, this function was removed. When a withdrawal results in native ETH being withdrawn, the `DelegationManager` calls `EigenPodManager.withdrawSharesAsTokens`, instead. *Removed methods (balance updates):* * `restakeBeaconChainETH` * `recordOvercommittedBeaconChainETH` Both of these methods have been replaced by `recordBeaconChainETHBalanceUpdate`, which handles both newly-restaked validators as well as existing validator balance changes. *See the full docs here: [`docs/core/EigenPodManager.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md).* #### `EigenPod` `EigenPods` now use the [EIP-4788 beacon block root oracle](https://eips.ethereum.org/EIPS/eip-4788) to enable beacon chain state proofs for validators pointed at the pod. While m1 had many beacon state proof-related methods, all were paused for the duration of m1. Because m2 refactors most of this functionality (and unpauses everything), the methods are listed here as "new methods." *New methods (beacon state proofs):* * `verifyWithdrawalCredentials`: Used to prove that a validator on the beacon chain has withdrawal credentials poitned at this `EigenPod`. A successful proof awards the Staker with delegatable shares. * `verifyBalanceUpdates`: Used to prove that a repointed validator's balance has changed. A successful proof will either increase or reduce the Staker's shares, depending on how the balance changed. * `verifyAndProcessWithdrawals`: Used to prove that a repointed validator has withdrawn some ETH into the `EigenPod`. This is used to prove both validator exits *and* consensus reward sweeps. * If this method shows that a validator has exited, the exited ETH can be withdrawn via the `DelegationManager`. * If this method shows that a validator has received a consensus reward sweep, the ETH is sent to the Staker via the `DelayedWithdrawalRouter`. *New methods (misc):* * `receive`, `withdrawNonBeaconChainETHBalanceWei`: A `receive` method was added to handle ETH sent directly to an `EigenPod`. ETH sent to the `receive` method can be withdrawn using `withdrawNonBeaconChainETHBalanceWei`. * Note: This withdrawal is routed through the `DelayedWithdrawalRouter` (rather than the `DelegationManager`), and is one of the few remaining withdrawal types that still use this contract. * `activateRestaking`: Used solely by pods deployed before m2 as part of the m1->m2 migration process. See [migrations](#Migrations) for more info. * `recoverTokens`: Can be used by the pod owner to rescue ERC20 tokens accidentally sent to the pod. * `withdrawRestakedBeaconChainETH`: This method is *only callable by the `EigenPodManager`*, and is used as part of the `DelegationManager` withdrawal flow to withdraw native ETH that has been provably exited from the beacon chain. *Additional Changes*: * Pods deployed *after the m2 upgrade* are automatically "restaked." That is, `EigenPod.hasRestaked` is set to `true`. For pods deployed during m1, pod owners will need to activate restaking manually. See [migrations](#Migrations) for more info. *See the full docs here: [`docs/core/EigenPodManager.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md). (`EigenPods` are included in the `EigenPodManager` docs page)* #### `DelayedWithdrawalRouter` This contract is actually almost entirely unchanged! It's included here because so much has changed, it's probably helpful to know what hasn't. One important difference here though is that as of m2, `EigenPods` can receive shares for provably-repointed validators. For any withdrawals involving shares, the `DelegationManager` is used to initiate and complete the withdrawal. This leaves only a few edge cases that use the `DelayedWithdrawalRouter`: * Withdrawing consensus rewards * Withdrawing ETH after it was sent to an `EigenPod's` `receive` method * Withdrawing any ETH in the pod if "restaking" is not active (applies only to pre-m2 pods that have not completed a migration) *See the full docs here: [`docs/core/EigenPodManager.md`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md). (`DelayedWithdrawalRouter` is included in the `EigenPodManager` docs page)* #### `Slasher` The `Slasher` was included in the previous mainnet release, but has been completely paused since the m1 launch. Since slashing is not a feature in the m2 release, we opted to remove the code in the `Slasher`, and leave it as an empty, non-functional contract to reduce confusion about whether slashing exists or not. In m1, several contracts referenced the Slasher and/or made calls to the Slasher. None of these were functional, as the Slasher has been paused since our original mainnet launch. As of m2, we've cleaned up a lot of this to better reflect its non-functional state. ### Migrations As part of m2, there are two important state migrations that need to take place: * `StrategyManager` Withdrawals * Activating your `EigenPod` #### `StrategyManager` Withdrawals ###### Background In m1, the `StrategyManager` was used to queue/complete withdrawals of LSTs. Additionally, there was code in m1 to support queuing/completing beacon chain ETH - though this latter functionality was paused. M2 moves all of this queuing/completing withdrawal behavior to the `DelegationManager`, because it's closely related to "undelegation" (undelegating also queues a withdrawal). See the docs for a reference to each of the methods involved with undelegation/withdrawal: [`docs/core/DelegationManager.md#Undelegating-and-Withdrawing`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/DelegationManager.md#undelegating-and-withdrawing). ###### Migrating Withdrawals to the `DelegationManager` *As of the m2 upgrade, if you have a withdrawal in the `StrategyManager` withdrawal queue*, **no action is required.** We intend to migrate these withdrawals to the `DelegationManager` shortly after the upgrade to the m2 system (on behalf of our users). *However, if you want to do this yourself* and are comfortable interacting with our contracts, the migration method is permissionless - see [`DelegationManager.migrateQueuedWithdrawals`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/src/contracts/core/DelegationManager.sol#L334-L336). You'll need to call this method with the withdrawal struct sitting in the m1 `StrategyManager` queue; it will migrate your withdrawal to the `DelegationManager`. #### Activating your `EigenPod` ###### Background In m1, `EigenPods` only had two methods available to be called: * `stake` * `withdrawBeforeRestaking` (The m1 codebase shows a lot of additional methods, but those have all been paused or otherwise inaccessible since the original mainnet launch.) M2 adds a lot of new methods that `EigenPod` owners can use to interact with the new m2 system - for example, providing beacon chain proofs that award shares, which can then be delegated to an Operator. ###### `EigenPods` Deployed After M2 *If you deploy an `EigenPod` after the m2 upgrade, **no action is required.*** Pods deployed after the m2 upgrade are automatically initialized with `EigenPod.hasRestaked == true`. Refer to the [`EigenPodManager` docs](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md) for a comprehensive list of m2's pod-related methods. ###### `EigenPods` Deployed Before M2 *If you deployed an `EigenPod` before the m2 upgrade, **you have a choice** between keeping the pod's existing functionality, or "activating restaking" to participate in the new m2 system.* * If you choose to keep your pod's m1 functionality, *no action is required*. Note that you will not receive shares for your restaked ETH (and will be unable to delegate your would-be shares to an Operator). * If you choose to activate restaking, call the `activateRestaking` method. (See the docs for [`EigenPod.activateRestaking`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md#eigenpodactivaterestaking)) In exchange for participating in the m2 system, your `EigenPod` will be awarded shares that can be delegated to an Operator as they provide services to an AVS. *In future releases,* it will be possible to earn yield based on these delegated shares. Note that activating restaking also comes with a few expected costs: * For each validator in your pod, you need to submit a one-time proof to verify that your validator exists on the beacon chain and has its withdrawal credentials pointed at your `EigenPod`. (See the docs for [`EigenPod.verifyWithdrawalCredentials`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md#eigenpodverifywithdrawalcredentials)) * If you fully exit your validator from the beacon chain, you need to submit a proof that your validator is withdrawn. A successful proof will enable you to withdraw this ETH via the `DelegationManager's` withdrawal queue. (See the docs for [`EigenPod.verifyAndProcessWithdrawals`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md#eigenpodverifyandprocesswithdrawals)) * In order to claim consensus rewards your validator earns, you need to submit a proof of the consensus reward's withdrawal. (See the docs for [`EigenPod.verifyAndProcessWithdrawals`](https://github.com/Layr-Labs/eigenlayer-contracts/blob/mainnet/docs/core/EigenPodManager.md#eigenpodverifyandprocesswithdrawals)) * Note: as of m2, this needs to be done for each individual beacon chain withdrawal sweep your pod receives, and is currently fairly expensive. A future release will support some form of batched withdrawals.