Ethereum Execution Layer Specification
- EELS is an execution layer reference implementation in Python.
- It’s up to date with mainnet.
- It fills tests, and passes existing ones.
- There’s an example of an EIP implemented in EELS below.
After more than a year in development, we’re pleased to publicly introduce the Ethereum Execution Layer Specification (affectionately known as EELS.) EELS is a Python reference implementation of the core components of an Ethereum execution client focused on readability and clarity. Intended as a spiritual successor to the Yellow Paper that’s more programmer friendly and up-to-date with post-merge forks, EELS can fill and execute state tests, follow mainnet1, and is a great place to prototype new EIPs.
EELS provides complete snapshots of the protocol at each fork—including upcoming ones—making it much easier to follow than EIPs (which only propose changes) and production clients (which often mix multiple forks in the same codepath.)
Beginning in 2021, as a project of ConsenSys’ Quilt team and the Ethereum Foundation, the eth1.0-spec (as it was known then) was inspired by the sheer frustration of having to decipher the cryptic notation of the Yellow Paper (Figure 1) to understand the specific behavior of an EVM instruction.
Figure 1. arcane runes describing the basis of the blockchain paradigm
Drawing on the successful Consensus Layer Specification, we set out to create a similar executable specification for the execution layer.
Today, EELS is consumable as a traditional Python repository and as rendered documentation. It’s still a bit rough around the edges, and doesn’t provide much in the way of annotations or English explanations for what various pieces do, but those will come with time.
It’s just Python
Hopefully a side-by-side comparison of the Yellow Paper and the equivalent code from EELS can show why EELS is a valuable complement to it:
Figure 2. Less-than (LT) EVM instruction from Yellow Paper
def less_than(evm: Evm) -> None: # STACK left = pop(evm.stack) right = pop(evm.stack) # GAS charge_gas(evm, GAS_VERY_LOW) # OPERATION result = U256(left < right) push(evm.stack, result) # PROGRAM COUNTER evm.pc += 1
Figure 3. Less-than (LT) EVM instruction from EELS
Here’s a video walk-through of adding a simple EVM instruction if that’s your kind of thing.
Having snapshots at each fork is great for a smart contract developer popping in to see the specifics of how an EVM instruction works, but isn’t very helpful for client developers themselves. For them, EELS can display the differences between forks:
Figure 4. one difference between homestead and the DAO fork
An Example EIP
Figure 5. EIP-6768’s specification section
First, we introduce a created_contracts variable to the EVM with transaction-level scope:
@dataclass class Environment: caller: Address block_hashes: List[Hash32] origin: Address coinbase: Address number: Uint base_fee_per_gas: Uint gas_limit: Uint gas_price: Uint time: U256 prev_randao: Bytes32 state: State chain_id: U64 + created_contracts: Set[Address]
Second, we note which contracts were created in each transaction:
Finally, we modify selfdestruct so it only works for contracts noted in created_contracts:
- # register account for deletion - evm.accounts_to_delete.add(originator) - + # Only continue if the contract has been created in the same tx + if originator in evm.env.created_contracts: + + # register account for deletion + evm.accounts_to_delete.add(originator) +
We want EELS to become the default way to specify Core EIPs, the first place EIP authors go to prototype their proposals, and the best possible reference for how Ethereum works.