⚠️ This EIP is not recommended for general use or implementation as it is likely to change.

EIP-4895: Beacon chain push withdrawals as operations Source

Support validator withdrawals from the beacon chain to the EVM via a new "system-level" operation type.

AuthorAlex Stokes, Danny Ryan
Discussions-Tohttps://ethereum-magicians.org/t/eip-4895-beacon-chain-withdrawals-as-system-level-operations/8568
StatusDraft
TypeStandards Track
CategoryCore
Created2022-03-10

Abstract

Introduce a system-level “operation” to support validator withdrawals that are “pushed” from the beacon chain to the EVM.

These operations effect unconditional balance increases to the specified recipients.

Motivation

This EIP provides a way for validator withdrawals made on the beacon chain to enter into the EVM. The architecture is “push”-based, rather than “pull”-based, where withdrawals are required to be processed in the execution block as soon as they are dequeued from the beacon chain.

This approach is more involved than “pull”-based alternatives (e.g. EIP-4788 + user-space withdrawal contract) with respect to the core protocol (by providing a new object type – operation – with special semantics) but does provide tighter integration of a critical feature into the protocol itself.

Additionally, the withdrawals themselves are represented as a new type of object in the block – an “operation” – that keeps their concern separate from user-level transactions. This approach is more involved than the prior EIP-4863 but it cleanly separates this “system-level” operation from regular transactions. The separation simplifies testing (so facilitates security) by reducing interaction effects generated by mixing this system-level concern with user data.

Specification

constants value units
FORK_TIMESTAMP TBD  

Beginning with the execution timestamp FORK_TIMESTAMP, execution clients MUST introduce the following extensions to block validation and processing:

System-level operation: withdrawal

Define a new block-level object called a withdrawal that describes withdrawals that have been validated at the consensus layer. Withdrawals are syntactically similar to a user-level transaction but live in a different domain than user-level transactions.

Withdrawals have three key pieces of information supplied from the consensus layer:

  1. a monotonically increasing index as a uint64 value
  2. a recipient for the withdrawn ether address as a 20-byte value
  3. an amount of ether given in wei as a 256-bit value.

Withdrawal objects are serialized as a RLP list according to the schema: [index, address, amount].

New field in the execution block: withdrawals

The execution block gains a new field referred to as withdrawals which is an RLP list of Withdrawal data.

For example:

withdrawal_0 = [index_0, address_0, amount_0]
withdrawal_1 = [index_1, address_1, amount_1]
withdrawals = [withdrawal_0, withdrawal_1]

This new field is encoded after the existing fields in the block structure and is considered part of the block’s body.

block_rlp = RLP([header, transactions, ommers, withdrawals])

block_body_rlp = RLP([transactions, ommers, withdrawals])

NOTE: due to EIP-3675 the ommers value in this serialization is the RLP encoding of an empty list.

Commitment to withdrawals

The execution block header gains a new field committing to the withdrawals in the block.

This commitment is constructed identically to the transactions root in the existing block header by inserting each withdrawal into a Merkle-Patricia trie keyed by index in the list of withdrawals.

def compute_trie_root_from_indexed_data(data):
    trie = Trie.from([(i, obj) for i, obj in enumerate(data)])
    return trie.root

block_header.withdrawals_root = compute_trie_root_from_indexed_data(block.withdrawals)

New field in the execution block header: withdrawals root

The block header gains a new field containing the 32 byte root of the trie committing to the list of withdrawals provided in a given block (see section on commitment).

This new field, the withdrawals_root, is appended to the end of the existing list of fields in the block header.

block_header_rlp = RLP([
  parent_hash,
  ommers_hash,
  coinbase,
  state_root,
  txs_root,
  receipts_root,
  bloom,
  difficulty,
  number,
  gas_limit,
  gas_used,
  time,
  extradata,
  mix_hash,
  nonce,
  withdrawals_root,
])

NOTE: refer to EIP-3675 as some of the values in the header RLP have fixed values that MUST* be used.

Block validity

Assuming the block is well-formatted, the execution client has an additional block validation to ensure that the withdrawals_root matches the expected value given the list present in the block.

assert block_header.withdrawals_root == compute_trie_root_from_indexed_data(block.withdrawals)

State transition

The withdrawals in a block are processed after any user-level transactions are applied.

For each withdrawal in the list of block.withdrawals, the implementation should increase the balance of the address specified by the amount given.

This balance change is unconditional and MUST not fail.

This operation has no associated gas costs.

Rationale

Why not a new transaction type?

This EIP suggests a new type of object – the “withdrawal operation” – as it has special semantics different from other existing types of EVM transactions.

Operations are initiated by the overall system, rather than originating from end users like typical transactions.

An entirely new type of object firewalls off generic EVM execution from this type of processing to simplify testing and security review of withdrawals.

Why no (gas) costs for the withdrawal type?

The maximum number of this operation that can reach the execution layer at a given time is bounded (enforced by the consensus layer) and this limit is kept small so that any execution layer operational costs are negligible in the context of the broader block execution.

This bound applies to both computational cost (only a few balance updates in the state) and storage/networking cost as the additional block footprint is kept small (current parameterizations put the additional overhead at ~1% of current average block size).

Why only balance updates? No general EVM execution?

More general processing introduces the risk of failures, which complicates accounting on the beacon chain.

This EIP suggests a route for withdrawals that provides most of the benefits for a minimum of the (complexity) cost.

Backwards Compatibility

No issues.

Security Considerations

Consensus-layer validation of withdrawal transactions is critical to ensure that the proper amount of ETH is withdrawn back into the execution layer. This consensus-layer to execution-layer ETH transfer does not have a current analog in the EVM and thus deserves very high security scrutiny.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Alex Stokes, Danny Ryan, "EIP-4895: Beacon chain push withdrawals as operations [DRAFT]," Ethereum Improvement Proposals, no. 4895, March 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-4895.