A Journey Through Phase 2 of Ethereum 2.0

Will Villanueva
May 15 · 19 min read

Moving 1.0 ether into the 2.0 chain

Beacon Chain Contracts

Buying into a framework

# Your account in the beacon chain holding the eth
"validator_index": uint64,
"data": {
shard: 5,
address: address
"pubkey": BLSPubkey,
"signature": BLSSignature

Shard Chain Contract and State Execution

# What we think of as the actual "state"
"objects": [[StateObject, 2**256], 2**64],
# Receipts
"receipts": [Receipt],
"next_receipt_index": uint64,
# Current slot
"slot": uint64,
# Version number for future compatibility
"version": uint64,
# Contents
"storage": bytes,
# StateObject can be removed if it expires (ie. now > ttl)
"ttl": uint64

Moving Ether into the Shard Chain

def depositToShard(state: BeaconState,
receipt: WithdrawalReceipt,
proof: WithdrawalReceiptRootProof):
# Verify Merkle proof of the withdrawal receipt
assert verify_withdrawal_receipt_root_proof(
# Interpret receipt data as an object in our own format
receipt_data = deserialize(receipt.withdrawal.data, FormattedReceiptData)
# Check that this function is being executed on the right shard
assert receipt_data.shard_id == getShard()
# Check that the account does not exist yet
assert getStorageValue(hash(receipt_data.pubkey)) == b''
# Set its storage
setStorage(hash(receipt_data.pubkey), serialize(EthAccount(
EthAccount {
pubkey: BLSPubkey,
nonce: 0,
value: 32eth

Transferring funds

def transfer(sender: bytes32,
nonce: uint64,
target: bytes32,
amount: uint64,
signature: BLSSignature):
sender_account = deserialize(getStorageValue(sender), EthAccount)
target_account = deserialize(getStorageValue(target), EthAccount)
assert nonce == sender_account.nonce
assert sender_account.value >= amount
assert bls_verify(
message_hash=hash(nonce, target, amount),
setStorage(sender, EthAccount(
nonce=sender_account.nonce + 1,
value=sender_account.value - amount
setStorage(target, EthAccount(
value=target_account.value + amount

Recap on current journey so far

Fee Markets

'to': address,
'from': address,
'amount': uint64,
'gas_price': uint64,
'signature': bytes
'transactions': [Transaction],
'signature': bytes,
'fee': uint64
def process_block(block: BlockProposal):
assert verify_signature(block, block.signature)
for transaction in transactions:
def proccess_transfer(tx):
assert verify_signature(tx, tx.signature)

to = get_storage(tx.to)
to.balance += tx.amount
gas_fee = TRANSFER_GAS * tx.gas_price
from = get_storage(tx.from)
from.balance -= (tx.amount + gas_fee)

relayer = get_storage(get_relayer())
relayer.balance += gas_fee

set_storage(tx.to, to)
set_storage(tx.from, from)
set_storage(get_relayer(), relayer)

Shard Chains Don’t Need State

nonce: 3,
value: 1232,
pub_key: BLSPubkey
nonce: 12,
value: 22,
pub_key: BLSPubkey

Cross Shard Transactions

Expanding to Full State Execution

EthAccount {
pubkey: BLSPubkey,
nonce: 0,
value: uint64,
code: bytes
executeCode(code: bytes, data: bytes) -> bytes

Double Spending Protection via Bitfields

# Unique nonce
"receipt_index": uint64,
# Execution Script (beacon chain contract index) that the receipt is created by
"executor": uint64,
# Address that it is intended for
"target": bytes32,
# Data
"data": bytes
check_and_set_bitfield_bit(bitfield_id: uint64, bit: uint64):


Thanks to Matt Garnett and John Adler

Will Villanueva

Written by

@wjvill Currently: R&D on Phase 2 for Ethereum 2.0 Past: CTO, Cofounder & original #buidler at @ethBounties hello@willvillanueva.com @consensys

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade