Beacon Chain Withdrawals

Beacon Chain Withdrawals


Special thanks to Alex Stokes, Danny Ryan, and Vitalik Buterin for their invaluable assistance and insightful feedback during the review process.

What is beacon chain withdrawal

With “the merge”, the consensus of Ethereum is changed from Proof-of-Work to Proof-of-Stake. PoS Ethereum requires you to stake 32 ETH to become a validator, which can be randomly assigned as a proposer (responsible for producing blocks) or an attester (responsible for submitting attestations), then validators will be rewarded according to their workload.

And the architecture of Ethereum has also changed from a monolithic chain to a modular blockchain with two layers: the consensus layer and the execution layer, which communicate through the engine API.

A modular blockchain with two layers

Previously, the validator could only send funds to the beacon chain via a deposit contract, and these funds would be locked in the consensus layer because there was no mechanism to withdraw the fund.

So the goal of withdrawal is to unlock validators’ funds, allow them to withdraw their funds (including 32 ETH + earned rewards) from CL to EL, and eventually enable validators’ exit function.

Withdraw staked ETH from CL to EL

This article will delve into this modest yet indispensable feature and provide an expanded explanation of its design philosophy, workflow, and potential impact. Please enjoy!

How does withdrawal work in more detail

Design Philosophy

The design goal is to enable the withdrawal function of the consensus layer under the strict premise of ensuring the security and stability of the Ethereum network, and eventually ensure that any validator can exit safely.

Besides, we also want no backward-compatible breaks, minimize complexity and engineering workload, and allow many projects can reuse withdrawal’s research and code, such as rollups and staking pools.

With this goal in mind, there have three critical questions.

When to activate withdrawals?

Withdrawals will always be active, but we will only remove stakes when the economic layer is secure enough. Also, we want to identify the spare stake (i.e., the balance in excess of 32 ETH) and remove it from the protocol.

Based on this goal, we want to make withdrawals that can still incentives honest validators. Therefore, we have two different types of withdrawals, namely partial withdrawals and full withdrawals.

All submitted full withdrawals must pass through the exit queue before they become withdrawable, then they can be sent to the EL and exit the network. The rate of exit queue depends on the number of active validators, which is proportional to each other, more specifically, until 327680 active validators, 4 validators can exit to be withdrawable per epoch. After that for every 65536 active validators, the validators’ exit rate goes up by one (same as the validator activation rate).

The lifecycle of full withdrawals

The rate of exit queue

If we assume that no new validators join the network and there only have full withdrawals. At this rate, the current 556983 validators need at least 119399 epochs (i.e. 530 days) to be withdrawable.

The time for all validators to go through the exit queue

How to signal?

Because of the modular design of Ethereum (i.e., CL and EL), we need to send the withdrawal information from the consensus layer to the execution layer. This introduces a new question, how to signal the execution layer?

In general, there are two solutions. One is “pull”-based solution (i.e., EIP-4788), and the other is “push”-based solution (i.e., EIP-4895).

These two solutions have different implementations. For the pull-based solution, we need to introduce a new “stateful” precompiled contract that handles withdrawal-related operations (i.e., can access the beacon state, but does not store the state data), and a new opcode (BEACON_STATE_ROOT) to read the state data from the “stateful” precompiled contract.

For the push-based solution, it reduces some complexity by using a withdrawal queue. However, the EL still needs to be modified accordingly (e.g., execution payload and header).

And they also have different trade-offs. The pull-based solution is simpler for protocol development but adds additional complexity (i.e., new concept of “stateful precompiled contract”, more testing, etc.) and bad UX. Users have to pay the gas for contract interactions and the withdrawals will take up the block space from other transactions.

For the push-based solution, most of the work is defined in the protocol layer rather than on the user end, so it gets better UX. And since there are no precompiled contracts, naturally no additional gas cost and block space take-up. So after all the considerations, we finally choose the “push”-based solution.

Where does the withdrawn ETH come from?

After deciding how to send the withdrawal message to the EL, we also need to design how to credit withdrawn ETH (the Ether that the EL sends to the withdrawal address). In general, two options can be chosen.

Withdrawal contract brings too much potential complexity and risks (i.e., if there is a bug in the contract then the entire protocol is borked). Also if large amounts of ETH are stored in the withdrawal contract (either by transferring from the deposit contract or by creating new ETH), it would look very unneutral.

Meanwhile, the system-level operation is separated from user-level transactions, which is cleaner and simpler, and does not require EVM execution (meaning no failure and no gas cost). So we finally chose the system-level operation.

How does it exactly work?

After we have clarified the goal, the design philosophy, and the critical questions of withdrawal, we can now explain how beacon chain withdrawal actually works. In short, a withdrawal is finished in the following four steps.

  1. Validator check and submit
  2. CL Processing
  3. Engine API
  4. EL Processing

We show the complete process of withdrawals by expanding these four steps one by one.

1. Validator check and submit

The most important thing for the validator is to set an Ethereum address so the funds can be withdrawn from the CL to the corresponding EL recipient address.

Validators can check if they set the Ethereum address by a withdrawal_credentials field (see it here). If there is an EL withdrawal address, the field is prefixed with 0x01, otherwise it defaults to 0x00 (as the example below).


Withdrawal credentials with 0x00 prefix

For partial withdrawals, it will only be initiated after the validator migrates withdrawal credentials from 0x00 to 0x01. Besides that, the validator does not need to do anything, and the reward over 32 ETH will automatically be sent to the withdrawal address.

And for full withdrawals, the validator can exit the network and unassign the duty at any time. But again, the fund (32 ETH + earned reward) will only be sent to the withdrawal address after migration to 0x01.

So validators should first check that if they have migrated the withdrawal credentials prefix from 0x00 to 0x01. If not, we have two ways to perform the migration.

However, note that the migration from 0x00 to 0x01 is a one-time process, and the Ethereum address cannot be changed after it is set. Also, full withdrawals cannot be canceled once they are submitted. So please operate it carefully!

2. CL Processing After the validator stage, we move to CL processing. Full withdrawals and partial withdrawals will have separate processing logic.

The complete workflow is like this in the diagram below.

Lifecycle of withdrawals

3. Engine API After that, the client will run the corresponding functions at each slot to scan all withdrawable validators (i.e., look up to 16384 at once) but only put the first 16 withdrawals (full or partial) into the withdrawal queue.

The withdrawal queue is a single channel that processes both partial withdrawals and full withdrawals. It will send the unified withdrawal objects (withdrawal and validator index, withdrawal amount, and receipt address) to the execution layer.

In the end, the withdrawal queue will be added to the execution payload (i.e., Ethereum block) when blocks are constructed.

Sending withdrawals to EL

4. EL Processing EL processes the execution payload as usual and takes the withdrawal information out (now it has a withdrawal field), adding the corresponding amount to the withdrawal address.

Since validators’ balance increase is a “system-level operation” (similar to block reward and coinbase), it will not be executed by EVM and will not be displayed as a normal transaction.

Upgrade timeline

Before enabling withdrawal to the mainnet, a lot of testing was done, including protocol layer testing (e.g., Zhejiang testnet and Hive test sets) and application layer testing (e.g., MEV-boost). But the most important time points are Sepolia testnet, Goerli testnet, and mainnet.

So we’ll see the mainnet enable beacon chain withdrawal on April 12!

The potential impact of withdrawals

Is there going to have a large-scale exit?

After two and a half years of growth, the total number of active validators has grown from around 20,000 in December 2020 to around 555,000 in 2023.

The number of active validators

And the total number of stakes has grown to 17.77 million ETH, which is 14.8% of the total supply (12 million in the stake pools).

Percentage of staking to supply

Also, PoS Ethereum has issued about 0.356 million new ETH through the validator’s reward (PoW Ethereum is about 5.94 million), decreasing the average annual issuance from 5.62% to 0.59% (reduced by 89.5% compared to PoW Ethereum’s issuance).

Issuance

Most people are concerned about whether a large number of users will withdraw their ETH from the network to the market after enabling the withdrawals. We are worried that this will impact the network’s stability and ETH’s price.

But in fact, users may feel safer after enabling withdrawals and prefer to keep their funds in the network. The data shows that there is no large-scale withdrawal event. Only 1179 validators have submitted voluntary exits so far, and the exited ETH only represents 0.0323% of the total amount of the network, which will not have a significant impact.

Voluntary exit count

For staking pools, they already allow users to exchange staked ETH (such as sETH and rETH) for real ETH at the rate of 1:1 before they officially activate the withdrawal feature. So users of staking pools will not make large-scale withdrawals either.

Even if all validators choose to exit, it would take at least 500 days to be withdrawable (based on the rate of gradual decrease of the exit queue). So we don’t need to worry about a large-scale withdrawal event or network stability breakdown after activating the withdrawal function.

What can we learn from withdrawals?

Besides the consensus-related software upgrades (such as flashbot MEV-boost, Lido upgrade, Rocket Pool upgrade, etc.), rollups can benefit from existing withdrawal research and codebase.

For instance, to guarantee credible neutrality and prevent malicious activity, rollups must ensure users can withdraw their funds from L2 to L1 at any time. So when rollups design a forced withdrawal mechanism, they can reuse engine API and withdrawal queue. Users can easily push their money from the rollup sequencer to the Ethereum execution layer.

Also, if Ethereum client-based rollups have a staking layer (users may need to deposit a certain amount of tokens to become a sequencer/prover), they can reuse the engine API and withdrawal queue to safely withdraw funds from the staking layer to the L2 sequencer too.


Rollups can reuse the Engine API

Conclusions

This comprehensive article delves into the concept of withdrawal, its mechanics, and its broader implications. I hope that it assists the wider community in gaining a deeper understanding of the withdrawal function.

In addition, I eagerly anticipate the Shapella upgrade. Following this update, the consensus R&D team will forge ahead with numerous developments, such as EIP-4844, in-protocol PBS, verkle tree/statelessness, fork-choice rule enhancements, and the ultimate aim of achieving single-slot finality.

A wealth of exciting developments lies ahead, and I look forward to sharing these stories with you in upcoming articles!