You're staring at your validator record and there's a single byte sitting in the `withdrawal_credentials` field that is either routing your ETH cleanly to a destination address or quietly holding it hostage until you do something about it. One byte. The rest of the 32-byte field follows its lead entirely.
The Two Credential Types, and Why the Difference Matters
Ethereum's proof-of-stake design stores a 32-byte `withdrawal_credentials` value in each validator's on-chain record. The first byte is the version prefix. `0x00` means BLS withdrawal credentials. `0x01` means execution-layer credentials, pointing to a standard Ethereum address.
BLS credentials (`0x00`) use the hash of a separate BLS public key as their identifier. Cryptographically valid. Functionally blind. The consensus layer has no idea what Ethereum address to send ETH to when you want to exit, so the withdrawal key exists, your funds are safe, and nothing flows anywhere until you supply a destination.
Execution-layer credentials (`0x01`) contain an actual 20-byte Ethereum address in the last 20 bytes of the field, zero-padded at the front. Once a validator carries `0x01` credentials, partial withdrawals (excess balance above 32 ETH) happen automatically every few days, swept by the protocol itself. Full withdrawals after a voluntary exit also land at that address without further action.
The migration from `0x00` to `0x01` is the process of supplying that address. Irreversible. Once set, the destination cannot be changed.
The Mechanics of the Migration Message
The migration works by broadcasting a `BLSToExecutionChange` message. This is a signed operation submitted to the beacon chain, not a regular Ethereum transaction. No gas. No mempool in the usual sense. It gets gossiped across the consensus layer's peer-to-peer network and included in a beacon block by the proposer.
The message contains four fields:
- `validator_index`: which validator you're updating
- `from_bls_pubkey`: the BLS withdrawal public key (the one whose hash lives in the `0x00` credential)
- `to_execution_address`: the 20-byte Ethereum address you want withdrawals to go to
- A BLS signature over the whole thing, made with the withdrawal private key
That signature is what proves you control the withdrawal key. The consensus layer checks it against the `from_bls_pubkey`, verifies that hashing `from_bls_pubkey` matches the stored `0x00` credential, and if both checks pass, overwrites the credential with the `0x01` version pointing at `to_execution_address`.
The verification step is worth pausing on. The withdrawal key never appears on-chain until this moment. During normal validator operation, nobody knows what it is, which makes the migration function like a sealed envelope finally opened in public: you reveal the key, prove control, set the address, and the envelope is gone. One shot. The design is deliberate, and it's the right one.
A Concrete Walk-Through
Call the validator Alice. She generated her keys using the standard EIP-2334 derivation path and deposited early in the Beacon Chain's life, before tooling defaulted to `0x01`. Her `withdrawal_credentials` on-chain read:
``` 0x00 + [30 zero bytes] + [last 2 bytes of BLS pubkey hash] ```
(In full: 32 bytes, `0x00` prefix, then the 31-byte remainder of `SHA256(withdrawal_pubkey)`.)
Alice wants partial withdrawals to sweep automatically to her hardware wallet address, `0xAb3...`. She uses `ethdo` or the official `staking-deposit-cli` to construct the `BLSToExecutionChange` message offline, signing it with her withdrawal private key on an air-gapped machine.
She submits the signed message to a beacon node via its API. Within one or two epochs (roughly 6 to 13 minutes), a block proposer picks it up. The consensus layer verifies the BLS signature, confirms the pubkey hash matches, and updates her validator record. From that point the protocol's withdrawal sweep mechanism processes her excess balance automatically, typically within a few days depending on queue depth, no further action required.
Now call the validator Bob. He did the exact same thing but typed his hardware wallet address with a transposition error. There is no undo. His rewards will sweep to the wrong address forever, or until that address's owner cooperates. This is not a hypothetical edge case: it is the advertised behavior. Mutable withdrawal destinations would create an attack surface where coerced or compromised signing keys could redirect funds, so the protocol simply refuses to offer that option.
The Honest Caveats
The address is permanent, but it doesn't have to be a plain externally owned account. It can be a multisig or a smart contract address, which gives you composability and recovery options a single private key can't match. Several institutional stakers use a contract address specifically because it lets them rotate signers without touching the withdrawal credential. Worth considering before you commit.
There's also a rate limit: 16 `BLSToExecutionChange` messages per block, per the Capella specification. During migration waves, a queue builds. For a solo validator this barely matters, but an operator running thousands of validators should plan for it the same way a data center plans for a maintenance window.
And here's the one thing people consistently miscalculate: `0x01` credentials don't mean you get paid instantly. Partial withdrawals are automated, but processed by a sweep mechanism that cycles through all validators in index order. With hundreds of thousands of active validators, the sweep can take several days to reach yours. Your balance is fine. The pipe is just long.
So: already showing `0x01` in your validator record? You're set. Showing `0x00`? The migration tooling is mature, well-documented, and designed to be done safely on air-gapped hardware.
The One-Way Door
The irreversibility deserves the most respect. Ethereum's designers made a deliberate tradeoff: simplicity and security over flexibility. A mutable withdrawal address would require a time-lock (complex), a second key type (more complexity), or social recovery (trust assumptions). The protocol chose none of those. You prove you hold the withdrawal key once, you name your address once, the conversation is over.
Triple-check the address. Use a contract if you need flexibility. Do it offline.
The withdrawal key is nothing like your validator signing key, which you use every epoch and keep hot. It's closer to the shutoff valve behind your wall: you hope never to touch it, it controls everything that matters, and by the time you realize you installed it wrong the ceiling is already wet.