Introduction
In our previous article, we reviewed the Ethereum validator lifecycle in detail, discussing multiple aspects related to the upcoming Electra hard fork. Now, it’s time to focus on the changes in the upcoming Electra and Prague upgrades and explain them in detail.
The history of Ethereum 2.0 “Proof of Stake” hard forks is a complex one. It started with the addition of a beacon layer to the existing execution layer, which initiated the Proof of Stake consensus while the execution layer still maintained Proof of Work (Phase0 and Altair hard forks). Subsequently, PoS was fully activated in the Bellatrix hard fork (although withdrawals were not enabled). Then, the Capella hard fork allowed withdrawals, completing the validator lifecycle. The recent hard fork Deneb (part of the Dencun (Deneb/Cancun) upgrade) introduced minor revisions to the beacon chain parameters, such as the inclusion of a time window for proofs, handling voluntary exits, and validator replacement limits. The major changes in Dencun occurred at the execution layer, introducing blob transactions, blob gas, KZG commitments for blobs, and deprecating the SELFDESTRUCT operation.
Now, the Prague/Electra (aka Pectra) hard fork introduces important upgrades to the execution and consensus layers. As auditors for the Lido project, we primarily focus on the consensus and staking related changes in this hard fork. However, we cannot ignore the execution layer changes in Prague, as they include important features that affect the Ethereum network and validators. Let's dive into the details of these changes.
High-Level Overview of Pectra
Electra introduces a number of features to the beacon layer. Major updates include:
Allow validators to have effective balances that vary between 32 and 2048 ETH (instead of a fixed 32 ETH).
Allow validators to initiate exits via secondary “withdrawal” credentials (no longer requires an active validator key).
Changes to how the beacon layer handles Eth1 deposits (no longer parses events from the deposit contract).
Adds a new general framework for handling requests from regular Eth1 contracts on the beacon layer (similar to how deposits were managed before Electra).
Meanwhile, Prague introduces the following changes to the execution layer:
A new precompiled contract with support for the BLS12-381 curve for verifying zkSNARK proofs (in addition to the popular BN254 curve).
A new system contract for storing and accessing up to 8192 historical block hashes (very useful for stateless clients).
Increase in calldata gas costs to reduce block sizes and encourage projects to migrate calldata-intensive operations (like rollups) to blobs introduced in Dencun.
Support for a larger number of blobs per Eth1 block, and provide an API to read these numbers.
Allowing EOAs (externally owned accounts) to have their own account code greatly expands the operations that EOAs can perform, such as performing multicalls or delegating execution to other addresses.
Let’s refer to the relevant Ethereum Improvement Proposals (EIPs) for further discussion:
EIP-7251: Increase MAX_EFFECTIVE_BALANCE
EIP-7002: Execution-layer-triggered exits
EIP-6110: On-chain provision of validator deposits
EIP-7549: Move committee index out of proof
EIP-7685: Generic Execution-layer requests
EIP-2537: BLS12-381 Precompile of curve operations
EIP-2935: Save historical block hashes in state
EIP-7623: Increase calldata cost
EIP-7691: Blob throughput increase
EIP-7840: Add blob scheduling to EL configuration file
EIP-7702: Set EOA account code
Some of these EIPs are primarily concerned with the consensus (beacon) layer, while others are related to the execution layer. Some span both layers because certain operations (such as deposits and withdrawals) require synchronized changes between the consensus and execution layers. Due to this interdependency, it is impractical to separate Electra and Prague, so we will review each EIP in turn, specifying the Ethereum components affected in each case.
EIP-7251: Increase MAX_EFFECTIVE_BALANCE
Reference: EIP-7251
Since the first Phase 0 hard fork, in preparation for Ethereum's Proof of Stake, and until Electra, the maximum effective balance of a validator was fixed at 32 ETH. Activation of a validator requires at least spec.min_activation_balance (32 ETH). After activation, a validator starts with this maximum effective balance, but can reduce its effective balance to spec.ejection_balance (16 ETH) and be ejected when that threshold is reached. This "minimum" logic remains the same in Electra, but now spec.max_effective_balance has been increased to 2048 ETH. Therefore, a validator can deposit between 32 and 2048 ETH to activate, and all of these amounts will contribute to their effective balance. This shift marks the move from "32ETH-Proof of Stake" to "Proof of Stake" :)
This variable effective balance will now be used to:
Increase the probability of becoming a block proposer, proportional to the effective balance
Increase the probability of becoming a member of the Sync Committee, proportional to the effective balance
As the basis for calculating relative slashing and inactivity penalty amounts
The first two activities are the most rewarding actions for a validator. Thus, after Electra, validators with large stakes will participate in block proposals and sync committees more frequently, with a frequency proportional to their effective balance.
Another effect is related to slashing. All slashing penalties are proportional to the validator's effective balance:
"Immediate" and "delayed" slashing penalties are larger for validators with high stakes.
"Delayed" slashing penalties with slashed validators with high stakes are also larger, because the "slashed" portion of the total stake becomes larger.
Whistleblowers who report validators with high effective balances receive a larger proportion of the slashed stake.
Electra also proposes changes to the slashing ratio, defining the portion of a validator’s balance that is slashed and received by the whistleblower.
Next are the invalidity effects. When a validator goes offline while active (attesting or proposing), invalidity scores accumulate, resulting in invalidity penalties being applied each epoch. These penalties are also proportional to the validator’s effective balance.
Due to the increase in effective balances, the validator “churn limit” has also changed. In Ethereum “before Electra,” validators typically had the same effective balance, and the exit churn limit was defined as “no more than 1/65536 (spec.churn_limit_quotient) of the total stake can exit in a epoch.” This created a “fixed” number of validators with the same stake that can exit. However, “after Electra”, there may be a situation where only a few “whales” exit, as they represent a significant portion of the total stake.
Another consideration is the rotation of many validator keys on a single validator instance. Large validators are currently forced to run thousands of validator keys on a single instance to accommodate large stakes, split into 32 ETH parts. With Electra, this behavior is no longer mandatory. From a financial perspective, this change has little impact, as rewards and probabilities scale linearly with the staked amount. Therefore, 100 validators with 32 ETH each are equivalent to one validator with 3200 ETH. In addition, multiple active validator keys can have the same Eth1 withdrawal voucher, allowing all rewards to be withdrawn to a single ETH address, thus avoiding the gas costs associated with reward consolidation. However, managing a large number of keys incurs additional administrative costs.
The ability to aggregate validators’ balances adds a new type of execution layer request. Before, we had deposits and withdrawals. Now, there will be another type: an aggregation request. It merges two validators into one. This operation request will include the source validator's public key and the destination public key, and will be processed similar to deposits and withdrawals. Aggregations will also have pending requests and balance change limits, just like deposits and withdrawals.
To summarize:
For small independent validators, Electra introduced the ability to automatically increase their effective balance (and rewards). Before, any surplus beyond 32 ETH could only be withdrawn, but after Electra, this surplus will eventually contribute to their effective balance. However, the effective balance can only increase in multiples of spec.effective_balance_increment (1 ETH), which means that the increase only occurs after reaching the next "1 ETH boundary".
For large independent validators, Electra provides significant management simplification by allowing multiple active validator keys to be consolidated into one. While this is not a game changer, operating a 1x2048 stake is undoubtedly much simpler than managing a 64x32 stake.
For liquid stake providers, who collect small stakes from users and distribute them among validators, Electra adds more flexibility in the stake distribution scheme, but also requires a serious refactoring of validator accounting based on a fixed 32 ETH effective balance.
Another important topic is validator historical data and profit estimation, which is particularly relevant for new participants who are trying to assess risk and reward. Before Electra (as of this writing), the 32 ETH cap (either minimum or maximum, in practice) created uniformity in historical data. All validators have the same effective balance, rewards, individual slashing penalties, block proposal frequency, and other metrics. This uniformity enables Ethereum to test its consensus mechanism without statistical outliers, thereby collecting valuable data on network behavior.
After Electra, the distribution of stake will change significantly. Large validators will participate more frequently in block proposals and sync committees, face larger penalties in slashing events, and have a greater impact on late slashing, activation queues, and exit queues. While this may create challenges in data aggregation, Ethereum's consensus ensures that non-linear calculations are minimal. The only non-linear component uses sqrt(total_effective_balance) to calculate the base reward, which applies to all validators. This means that validator rewards and slashing can still be estimated on a "per 1 ETH" basis (or more accurately, according to spec.effective_balance_increment, which may change in the future).
For more details, see our previous article on validator behavior.
EIP-7002: Triggerable Execution Layer Exits
Reference: EIP-7002
Each validator in Ethereum has two key pairs: an active key and a withdrawal key. The active public BLS key serves as the validator’s primary identity in the beacon chain, and is used to sign blocks, attest, slash, sync committee convergence, and (before this EIP) voluntary exits (to initiate a consensus exit of a validator after a delay). The second key pair (the “withdrawal credentials”) can be another BLS key pair or a regular Eth1 account (private key and address). Right now, withdrawals to an ETH address require a withdrawal message signed by the active BLS private key. This EIP changes that.
In practice, the owners of these two (active and withdrawal) key pairs can be different. The validator's active key is responsible for the validation duties: running the server, keeping it up and running, etc., while the withdrawal voucher is usually controlled by the stake owner, who receives the rewards and is responsible for the funds. Currently, the stake owner who controls the withdrawal voucher cannot initiate the validator's exit, only withdraw the rewards. This situation allows the validator's active key owner to effectively hold the validator's balance "hostage". The validator can "pre-sign" the exit message and hand it to the stake owner, but this workaround is not ideal. In addition, both withdrawals and exits currently require interaction with the beacon layer validator through a dedicated API.
The best solution is to allow stake owners to perform both exit and withdrawal operations through regular smart contract calls. This involves standard Eth1 signature checks, which greatly simplifies operations.
This EIP allows stake owners to trigger withdrawals and exits by sending standard transactions from their ETH address to a dedicated smart contract (similar to the existing deposit process using a "deposit" contract). Withdrawals (or exits when enough stake has been removed) proceed as follows:
A staker sends a withdrawal request (an "in" request) to the system's "withdrawal" contract.
The contract charges a specific fee (in ETH) to mitigate potential malicious attacks, and similar to EIP-1559, the fee increases when the request queue is busy.
The contract saves the "in" withdrawal/exit requests to its storage.
When a block is proposed to the beacon layer, the queued "in" withdrawal/exit requests are retrieved from storage.
The beacon layer processes the "in" requests, interacts with the balances of active validators, schedules validator exits, and forms "out" withdrawal requests.
“Out” withdrawal requests are processed at the execution layer and stakers receive their ETH.
While deposits are actions triggered in Eth1 blocks and then “moved” to the beacon layer via a “pending” deposit queue, withdrawals follow a different scheme. They are triggered on the beacon layer (via the CLI) and then “moved” to Eth1 blocks. Both schemes will now operate through the same general framework (described below): create a request at the Eth1 layer, process the “pending” deposit/withdrawal/merge queue, and process at the beacon layer. For “output” actions like withdrawals, the output queue is also processed and the result is “settled” in an Eth1 block.
With this EIP, stakers can withdraw and exit their validators using regular ETH transactions without having to interact directly with the validator CLI or access the validator’s infrastructure. This greatly simplifies staking operations, especially for large stake providers. Validator infrastructure can now be almost completely isolated, as only the keys of active validators need to be maintained, while all staking operations can be handled elsewhere. It removes the need for independent stakers to wait for active validators to act, and significantly simplifies the off-chain parts of Lido services like the Community Staking Module.
Thus, this EIP "completes" staking operations, completely migrating them to the Eth1 layer, significantly reducing infrastructure security risks, and enhancing decentralization for independent staking initiatives.
EIP-6110: Provision Validator Deposits On-Chain
Reference: EIP-6110
Currently, deposits are implemented via events in the system "deposit" contract (as discussed in detail in a previous post). The contract accepts ETH and validator credentials, emitting "Deposit()" events, which are then parsed and converted into deposit requests on the beacon layer. This system has a number of drawbacks: it requires voting on the beacon chain layer's eth1data, which adds significant latency. Additionally, the beacon layer needs to query the execution layer, further adding complexity. These issues are discussed in detail in the EIP. A simpler approach, without having to deal with many of these issues, is to include deposit requests directly in the Eth1 block at the specified location. This mechanism is similar to the withdrawal processing flow described in the previous EIP.
The changes proposed in this EIP are promising. The eth1data processing can now be removed entirely, eliminating the need for voting or long delays (currently around 12 hours) between events on the Eth1 side and the inclusion of deposits on the beacon layer. It also removes the logic for snapshotting the deposit contract. This EIP simplifies deposit processing and aligns it with the withdrawal processing scheme described above.
For stakers and validators, these changes significantly reduce the latency between deposits and validator activation. When validators are slashed, the necessary replenishment is also faster.
There is not much more to say about this EIP, except that it removes outdated logic, simplifies the process and creates a better outcome for everyone involved.
EIP-7685: Generic Execution Layer Request
Reference: EIP-7685
This EIP should have been proposed before the first three EIPs related to deposits/withdrawals/merging, as it lays the foundation for those EIPs. However, it is introduced here to highlight the growing need to consistently move specialized data between Eth1 (execution) and beacon (consensus) chain blocks (layers). This EIP affects both layers, making the processing of requests triggered by regular ETH transactions more efficient. Currently, we observe:
Deposit events in Eth1 blocks are "moved" to the beacon block for processing.
Withdrawal requests (using the CLI) in the beacon block are "moved" to the Eth1 block for processing.
Validator merges need to be handled, which are also Eth1->beacon requests.
These three actions demonstrate the necessity for consistent handling of various types of requests when transitioning between the execution layer and the beacon layer. Furthermore, we need the ability to trigger these actions using only the Eth1 layer, as this would allow us to isolate the validator infrastructure from the stake management infrastructure, thereby improving security. Therefore, a general solution for managing such requests is both practical and necessary.
This EIP establishes a framework for at least three main cases: deposits, withdrawals, and consolidation. That's why earlier EIPs introduced fields like WITHDRAWAL_REQUEST_TYPE and DEPOSIT_REQUEST_TYPE, and now consolidation will add another field, CONSOLIDATION_REQUEST_TYPE. Additionally, this EIP may also include a generic mechanism for handling limits on such requests (reference constants: PENDING_DEPOSITS_LIMIT, PENDING_PARTIAL_WITHDRAWALS_LIMIT, PENDING_CONSOLIDATIONS_LIMIT).
While detailed implementation details of this framework are still unavailable, it will certainly include key request types, integrity mechanisms (e.g., hashing and merkle-ized requests), as well as pending queue handling and rate limiting.
This EIP has architectural significance, enabling Eth1 to trigger key operations in the beacon layer through a unified framework. For end users and projects, this means that all requests triggered at the Eth1 layer will be delivered and processed more efficiently on the beacon layer.
EIP-2537: Precompile of BLS12-381 curve operations
Reference: EIP-2537
If you don't want to get too deep into it, think of the precompile of BLS12-381 as a complex cryptographic "hash" operation that can now be used in smart contracts. For those who are interested, let's explore further.
Mathematical operations on elliptic curves such as BLS12-381 (and its counterpart BN-254) are currently used for two main purposes:
BLS signatures, where a special operation called "pairing" is used to verify these signatures. BLS signatures are widely used by validators because they enable multiple signatures to be aggregated into one. Validators rely on BLS signatures based on the BLS12-381 curve (although they can also be implemented using any curve that supports pairing, such as BN254).
Verification of zkSNARK proofs, where pairings are used to verify proofs. Additionally, KZG commitments to large blocks introduced by the Dencun hard fork also use pairings to verify block commitments.
If you want to verify BLS signatures or zkSNARK proofs in a smart contract, you have to compute these "pairings", which is computationally very expensive. Ethereum already has a precompiled contract for BN254 curve operations (EIP-196 and EIP-197). However, the BLS12-381 curve (which is now considered more secure and more widely used today) has not yet been implemented as a precompilation. In the absence of such a precompilation, implementing pairings and other curve operations in smart contracts requires a lot of computation, as shown here, and consumes huge amounts of gas (about ~10^5 to 10^6 gas).
This EIP opens the door to many potential applications, especially in cheap BLS signature verification based on the BLS12-381 curve. This makes it possible to implement threshold schemes for various purposes. As mentioned earlier, Ethereum validators already use signatures based on BLS12-381. With this EIP, standard smart contracts can now efficiently verify aggregated validator signatures. This can simplify consensus proofs and bridging of cross-network assets, as BLS signatures are widely used in blockchains. Threshold BLS signatures themselves allow the construction of many efficient threshold schemes for voting, decentralized random number generation, multi-signatures, and more.
Cheaper zkSNARK proof verification will in turn unlock a large number of applications. Many zkSNARK-based solutions are currently hindered by high proof verification costs, which makes certain projects almost impractical. This EIP has the potential to change that.
EIP-2935: Save historical block hashes in the state
Reference: EIP-2935
This EIP proposes to store 8192 (~27.3 hours) historical block hashes in the blockchain state, providing extended history for stateless clients (such as rollups) and smart contracts. It proposes to retain the current behavior of the BLOCKHASH opcode, maintaining the limit of 256 blocks, while introducing a new system contract specifically designed to store and retrieve historical hashes. This contract performs a set() operation when a block is processed by the execution layer. Its get() method, accessible to anyone, retrieves the desired block hash from the ring buffer.
Currently, it is possible to reference historical block hashes in the EVM, but access is limited to the most recent 256 blocks (~50 minutes). However, there are cases where access to older block data is critical, in particular for cross-chain applications (which need to prove data about previous blocks) and stateless clients, which periodically need access to early block hashes.
This EIP extends the timeframe available to rollups and cross-chain applications, allowing them to access historical data directly in the EVM without having to collect it externally. As a result, these solutions become more robust and sustainable.
EIP-7623: Increase calldata cost
Reference: EIP-7623
The calldata cost regulates the available size of transaction payloads, which can be large in some cases (e.g. when large arrays or binary buffers are passed as parameters). Significant calldata usage is primarily attributed to rollups, which send payloads via calldata containing the current rollup state.
Introducing large, provable binary data to the blockchain is critical for rollups. The Dencun (Deneb-Cancun) upgrade introduces an important innovation for such use cases - blob transactions (EIP-4844). Blob transactions have their own dedicated "blob" gas fee, and while their body is stored temporarily, their cryptographic proof (KZG commitment) is integrated into the consensus layer along with their hash. Therefore, blobs provide a better solution for rollups than using calldata to store data.
Encouraging rollups to move their data to blobs can be achieved through a "carrot and stick" approach. Reduced blob gas fees serve as the "carrot", while this EIP acts as a "lever" by increasing calldata costs, thereby disincentivizing excessive data storage in transactions. This EIP complements the next EIP-7691 (Blob Throughput Increase), which increases the maximum number of blobs allowed per block.
EIP-7691: Increased blob throughput
Reference: EIP-7691
Blobs were introduced in the previous Dencun hard fork, and the initial values for the maximum and target number of blobs "per block" were conservative estimates. This was due to the complexity of predicting how the p2p network would handle the propagation of large binary objects between validator nodes. The previous configuration has proven to be good, making this an appropriate time to test new values. Previously, the target/maximum number of blobs per block was set to 3/6. These limits are now raised to 6/9, respectively.
Combined with the previous EIP-7623 (increasing calldata cost), this adjustment further incentivizes rollups to move their data from calldata to blobs. Work on finding the optimal blob parameters is ongoing.
EIP-7840: Add blob scheduling to the EL configuration file
Reference: EIP-7840
This EIP proposes to add the target and maximum "per block" number of blobs (discussed earlier) as well as the baseFeeUpdateFraction value to the Ethereum Execution Layer (EL) configuration file. It also enables clients to retrieve these values through the node API. This feature is particularly useful for tasks such as estimating blob gas fees.
EIP-7702: Set EOA account code
Reference: EIP-7702
This is a very important EIP that will bring major changes to Ethereum users. As we know, EOAs (Externally Owned Accounts) cannot have any code, but can provide transaction signatures (tx.origin). In contrast, a smart contract has bytecode, but cannot proactively propose a direct signature of "it". Any user interaction that requires additional, automated and verifiable logic can currently only be done by calling an external contract to perform the desired action. However, in this case, the external contract becomes the msg.sender of the subsequent contract, making the call "a call from the contract, not the user".
This EIP introduces a new SET_CODE_TX_TYPE=0x04 transaction type (we previously had the old 0x1 transaction, the new 0x02 transaction from the Berlin and EIP-1559 upgrades, and the 0x03 blob transaction introduced in Dencun). This new transaction type allows setting code for an EOA account. In effect, it allows an EOA to execute external code "in the context of its own EOA account". From an external perspective, during the transaction, the EOA appears to "borrow" code from an external contract and execute it. Technically, this is achieved by adding a special authorization data tuple to the "code" storage of the EOA address (before this EIP, this "code" storage was always empty for EOA).
Currently, the new 0x04 transaction type proposed by this EIP contains an array:
authorization_list=[[chain_id,address,nonce,y_parity,r,s],...]
Each element allows the account to use the code from the specified address (from the last valid authorization item). When processing such a transaction, the code of the given EOA is set to a special 0xef0100 || address value (23 bytes), where the address points to the contract with the required code, || indicates a connection, and 0xef0100 indicates a special magic value that regular smart contracts cannot contain (as per EIP-3541). This magic value ensures that this EOA cannot be treated as a regular contract and cannot be called like a regular contract.
When this EOA initiates a transaction, the specified address will be used to call the corresponding code in the context of this EOA. While the full implementation details of this EIP are not yet known, it is certain that it will bring significant changes.
One major impact is the ability to make multicalls directly from EOAs. Multicalls are an ongoing trend in DeFi, and many protocols provide this feature as a powerful tool (such as Uniswap V4, Balancer V3, or Euler V2). With this EIP, it is now possible to make multicalls directly from EOAs.
For example, this new feature solves a common problem in DeFi: the inefficiency of approve() + anything() requiring two separate transactions. This EIP allows for general "pre-authorization" logic so that things like approve(X) + deposit(X) can be done in a single transaction.
Another advantage of being able to delegate transaction execution "on behalf of" EOAs is the concept of sponsorship. Sponsorship is an often discussed and highly desired feature to help new users get onboard to Ethereum.
The programmable logic associated with EOAs unlocks many possibilities, such as enforcing security restrictions, setting spending caps, enforcing KYC requirements, and more.
Of course, this shift also raises many design issues. One issue is the use of chain_id, which determines whether the same signature can be valid across multiple networks, depending on its inclusion or non-inclusion in the signature. Another complication is the choice between using the address of the target code and embedding the actual bytecode. Each of these approaches has unique characteristics and limitations. Additionally, the use of nonce plays a key role in defining whether a permission is "multi-purpose" or "single-purpose". These elements impact functionality and security issues, including aspects such as bulk invalidation of signatures and ease of use. Vitalik raised these issues in a discussion (here) and they are worth further exploration.
It is worth noting that this change will affect one of Ethereum's security mechanisms, tx.origin. More details on the implementation of this EIP are necessary, but it looks like the behavior of require(tx.origin == msg.sender) will change. This check has always been the most reliable way to ensure that msg.sender is an EOA, not a contract. Other approaches, such as checking EXTCODESIZE (to check if it is a contract), often fail and can be circumvented (for example, by calling the constructor or deploying code at a predefined address after the transaction). These checks are used to prevent reentrancy and flash loan attacks, but are far from ideal as they also hinder integration with external protocols. After this EIP, even the trusty require(tx.origin == msg.sender) check seems to become obsolete. The protocol must adapt by removing these checks, as the distinction between "EOA" and "contract" will no longer apply - now every address may have associated code.
The separation of traditional EOAs and smart contracts continues to blur. This EIP brings Ethereum closer to designs like TON, where every account is essentially executable code. As interactions with the protocol become more complex, using programmable logic to improve the end-user experience is a natural progression of this evolution.
Conclusion
The Prague/Electra (Pectra) upgrade is scheduled for March 2025. Its most notable planned changes include:
Variable validator effective stake, up to 2048 ETH, which will significantly change the stake distribution, validator schedule, and simplify the management of large stake providers by consolidating smaller stakes
Improved interaction between the execution layer and the consensus layer, simplifying data exchange between Eth1 execution blocks and beacon chain blocks. This will greatly simplify deposits, activations, withdrawals, and exits, speeding up these processes and laying the foundation for further interactions between the consensus and execution layers
Support cheaper BLS signatures and zkSNARK verification directly in smart contracts via new “pairing-friendly” BLS12-381 precompiles
Encourage Rollups to adopt blob transactions by increasing blob transaction thresholds and raising calldata costs
Enable EOAs to act as programmable accounts, giving them multi-call, sponsorship, and other advanced features
As you can see, Pectra will have a significant impact on the end-user experience of the staking and consensus layers, as well as the execution layer. While we cannot analyze all of these changes in detail through the code at this stage, as development is still ongoing, we will cover these updates in future posts.