Part III · Chapter 30 of 43 · Shanghai · Capella

EIP-4895: getting staked ETH back without a transaction

After the Merge, a validator's 32 ETH and its rewards lived on the consensus layer with no way home. A normal transaction can't move them — there's no EOA, no key, nothing on the execution layer to sign. EIP-4895 inverts the flow: the consensus layer pushes withdrawals into each block, and the EVM just credits the balance.

Updated Jun 23, 2026 · 10 min
Assumed
  • the Merge (consensus + execution layers)
  • staking basics

After the Merge, Ethereum runs as two layers bolted together: the consensus layer The beacon chain — it runs proof-of-stake, tracks validators and their balances (the 32 ETH stake plus accrued rewards), and decides which execution block is canonical. It does not run the EVM. tracks validators and their balances, and the execution layer The EVM and the world state of accounts and contracts — where ordinary balances live and transactions execute. It has no idea about validator balances on the beacon chain. runs the EVM over ordinary accounts. You could put ETH in (the one-way deposit contract), but from September 2022 until the Shanghai/Capella upgrade in April 2023, there was no way to get staked ETH out. The funds existed only as a number on the beacon chain, and nothing on the execution layer could touch them. EIP-4895 is the elegant fix. Let’s derive it.

1 step Trapped on the CL

The problem: a balance no transaction can reach

A validator’s money lives on the consensus layer as a plain balance entry — 32 ETH of stake plus whatever it has earned. The natural way to move ETH on Ethereum is a transaction: an account signs “send X to Y”. But a validator is not an execution-layer account. It has no EOA, no private key the EVM recognizes, and no balance in the execution-layer state to draw from. So there is literally no transaction anyone can write to pull that money across — the sender doesn’t exist where transactions live.

two layers after the Merge consensus layer · beacon chain validator: 32 ETH + rewards execution layer · accounts & EVM no account holds the stake ✗ no way back staked ETH and rewards sit on the CL with no path home to the EL
The validator's stake and rewards sit on the consensus layer; ordinary accounts and the EVM live on the execution layer. Deposits flow in one-way, but nothing on the execution side can sign for or reach the validator balance — so it can't come back.

The two layers don’t share an account model, and a transaction is a pull initiated by an account that owns the funds. Here the owner of the funds is the protocol’s validator registry, not an EOA.

→ Step 2: stop pulling and start pushing.

2 step Push, don't pull

Invert the flow: the CL pushes withdrawals into the block

A transaction is a pull the funds’ owner signs. So flip the direction: let the consensus layer push. Define a new object — a withdrawal A system-level object the consensus layer inserts into an execution block: { index, validatorIndex, address, amount }. It is not a transaction — it has no signature, no sender account, and costs no gas. A user can never create one. — that the CL inserts directly into each execution block. Every execution block gains a withdrawals list, and the block header gains a withdrawalsRoot (a Merkle root committing to that list, exactly like transactionsRoot commits to the transactions). The execution layer doesn’t ask for these; the consensus layer hands them over as part of building the block.

the CL pushes withdrawals into each block consensus layer push execution block header · withdrawalsRoot ✓ transactions signed · gas · sender withdrawals no signature · no gas a new withdrawals list + withdrawalsRoot — pushed by the CL, not sent by you
Each execution block gains a withdrawals list and a withdrawalsRoot in the header. Unlike transactions — which carry a signature, a sender, and gas — withdrawals are pushed in by the consensus layer with none of those; they're system operations, not user actions.

This is the key reframing: a withdrawal is a system-level operation, not a transaction. No one signs it, it has no from, and it consumes no gas. The protocol itself moves the money, and the withdrawalsRoot makes the set verifiable and part of consensus.

→ Step 3: the simplest possible processing.

3 step Just credit the balance

Processing a withdrawal: increase a balance, full stop

Here’s how little it takes. For each withdrawal { index, validatorIndex, address, amount }, the execution layer simply adds amount (converted from Gwei to Wei) to address’s balance. That’s the entire operation. It is not a value-bearing call: no EVM execution is triggered, no contract code runs, no receive() or fallback fires, and it costs no gas. It can’t revert, because there’s nothing to execute — it’s an unconditional credit, the protocol minting back ETH that was already staked.

processing = credit the balance, nothing else withdrawal index · validatorIndex address · amount (Gwei) recipient account 10.0 → 12.0 no EVM call · no gas · no code runs an unconditional credit — not a transfer that could run contract code
Processing is a pure balance increase: add the withdrawal's amount to the recipient address. No EVM call is made, so no contract code runs, nothing can revert, and no gas is spent — it's an unconditional credit, not a transfer.

Because it bypasses the EVM entirely, even a contract account receiving a withdrawal just sees its balance go up, with no execution. The index is a global, ever-increasing counter so every withdrawal is unique and ordered.

→ Step 4: two flavors, both automatic.

4 step Skim vs exit

Two flavors — and you never press a button

The consensus layer continuously walks the validator set (a rolling sweep) and emits withdrawals automatically, in two forms. A partial withdrawal Automatic 'skimming' of rewards: any validator balance above the 32 ETH cap is periodically withdrawn to the validator's withdrawal address, while the 32 ETH stays staked and keeps validating. skims everything above the 32 ETH effective-balance cap — your rewards come home while your stake keeps working. A full withdrawal returns a validator’s entire remaining balance once it has fully exited the active set. Both require the validator to have set an 0x01 withdrawal credential pointing at an execution-layer address — and once it has, the ETH simply arrives; there’s no withdrawal transaction to send.

the CL sweeps the validator set automatically — no withdraw button 32 excess 32+ excess 32+ exited excess 32+ excess above 32 is skimmed off; an exited validator's whole stake returns both just arrive on the rolling sweep — you never press a button
Partial withdrawals skim rewards above 32 ETH while the stake keeps validating; full withdrawals return an exited validator's whole balance. Both are emitted automatically by the consensus layer's sweep to the validator's withdrawal address — no user action required.
04 Go Deeper Where to take it from here