https://eof.wtf/ https://notes.ethereum.org/@axic/evm-object-format This page analyzes the differences between Ethereum Object Format (EOF) and standard Ethereum Virtual Machine (EVM) compilation outputs for a minimal Solidity contract, `EOF.sol`. The contract is simple: ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.29; contract EOF {} ``` We’ll compare two compilation outputs: 1. **EOF Compilation**: `solc-macos --evm-version osaka --experimental-eof-version 1 --via-ir --opcodes EOF.sol` 2. **Standard EVM Compilation**: `solc-macos --opcodes EOF.sol` ## Compilation Outputs ### 1. EOF Compilation Output Command: `solc-macos --evm-version osaka --experimental-eof-version 1 --via-ir --opcodes EOF.sol` **Opcodes**: ``` 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP GT STOP SUB SUB STOP ADD STOP PUSH8 0x400000000800002 STOP DUP1 STOP MUL PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE RJUMPI 0x5 PUSH0 PUSH1 0x80 RETURNCONTRACT 0x0 JUMPF 0x1 PUSH0 DUP1 REVERT 0xEF STOP ADD ADD STOP ADDMOD MUL STOP MUL STOP ADDMOD STOP SUB DIV STOP NUMBER STOP STOP DUP1 STOP MUL STOP DUP1 STOP MUL PUSH1 0x80 PUSH1 0x40 MSTORE JUMPF 0x1 PUSH0 DUP1 REVERT LOG3 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xB9 BASEFEE OR DUP9 EOFCREATE 0xE3 PUSH4 0x50CC3A14 0xC2 0xC1 STOP RETURN SWAP14 0x2D 0xB2 0xAB 0x26 PUSH19 0x177AFB6FF1D8690A95F816C6578706572696D PUSH6 0x6E74616CF564 PUSH20 0x6F6C634300081D00410000000000000000000000 ``` - **Key Features**: - Starts with `0xEF`, the EOF magic byte, indicating an EOF container. - Uses EOF-specific opcodes: `RJUMPI`, `JUMPF`, `RETURNCONTRACT`, `EOFCREATE`. - Structured control flow with relative jumps and function calls. ### 2. Standard EVM Compilation Output Command: `solc-macos --opcodes EOF.sol` **Opcodes**: ``` PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xE JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x3E DUP1 PUSH1 0x1A PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH0 PUSH0 REVERT INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 SWAP9 PUSH1 0xA4 PUSH25 0xD5BA037ECC3E72F42F09230DCF98422C750C750B1B9C710738 0xCD PUSH30 0xC064736F6C634300081D0033000000000000000000000000000000000000 ``` - **Key Features**: - Classic EVM bytecode with no EOF structure. - Uses traditional opcodes: `JUMPI`, `JUMPDEST`, `CODECOPY`, `RETURN`. - Appends Solidity metadata (e.g., `solc 0.8.29`). --- ## Key Differences | | **EOF Compilation** | **Legacy EVM** | | --------------------- | ---------------------------------------- | ------------------------------ | | **Format** | EOF container (`0xEF` prefix) | Legacy EVM bytecode | | **Jump Instructions** | `RJUMPI`, `JUMPF` (relative, structured) | `JUMPI`, `JUMPDEST` (absolute) | | **Contract Creation** | `EOFCREATE`, `RETURNCONTRACT` | `CODECOPY`, `RETURN` | | **Validation** | Strict, compile-time enforced | Lenient, runtime checks | | **Stack Management** | Enhanced (solves "Stack Too Deep") | Limited (16 slots max) | | **Metadata** | Embedded in data pushes | Appended as a blob | --- ## EOF Improvements Over Standard EVM EOF (Ethereum Object Format) introduces a new bytecode structure to address longstanding EVM limitations. Here’s how it improves on the standard EVM, with examples from the opcodes: ### 1. Solving "Stack Too Deep" - **Problem in Standard EVM**: - The EVM has a stack limit of 16 slots. In complex contracts with many variables (e.g., >16 local variables or function arguments), Solidity throws a "Stack Too Deep" error. Developers must work around this by splitting functions or using storage, increasing gas costs and complexity. - **Example**: In the standard output, opcodes like `DUP1`, `SWAP9`, and multiple `PUSH` operations manipulate the stack directly, but if the contract were larger, stack overflow would halt compilation. - **EOF Solution**: - EOF introduces a new stack model with explicit function calls (`JUMPF`) and return values, reducing reliance on the operand stack. It separates code into sections (e.g., initialization, runtime), allowing the compiler to manage stack usage more efficiently via the intermediate representation (IR) pipeline (`--via-ir`). - **Example**: In the EOF output, `JUMPF 0x1` jumps to a function section, implying a subroutine-like structure. This isolates stack usage per section, avoiding overflow even in complex contracts. ### 2. JUMPDEST Analysis: Compile-Time vs. Runtime - **Problem in Standard EVM**: - The EVM uses `JUMP` and `JUMPI` with absolute offsets, requiring `JUMPDEST` markers to denote valid jump targets. At runtime, the EVM performs "JUMPDEST analysis" to validate these targets, adding overhead and potential vulnerabilities (e.g., if a jump lands on an invalid offset). - **Example**: In the standard output, `PUSH1 0xE JUMPI` jumps to `JUMPDEST`, and the EVM must scan the bytecode at runtime to ensure `0xE` is a valid `JUMPDEST`. This analysis slows execution and complicates gas estimation. - **EOF Solution**: - EOF eliminates `JUMP` and `JUMPI` in favor of `RJUMPI` (relative jump if) and `JUMPF` (jump to function), with offsets validated at compile time. The bytecode is split into sections, and jumps are restricted to predefined targets, removing runtime `JUMPDEST` analysis entirely. - **Example**: In the EOF output, `RJUMPI 0x5` uses a relative offset (+5 bytes), and `JUMPF 0x1` targets a function section. These are pre-validated by the compiler, ensuring no invalid jumps occur. ### 3. Structured Contract Creation - **Standard EVM**: Uses `CODECOPY` and `RETURN` to deploy runtime code, a manual process prone to errors in complex deployments. - **Example**: `PUSH0 CODECOPY PUSH0 RETURN` copies and returns the runtime bytecode. - **EOF**: Introduces `EOFCREATE` and `RETURNCONTRACT` for modular contract creation, with explicit section handling. - **Example**: `EOFCREATE 0xE3` creates a new EOF container, and `RETURNCONTRACT 0x0` returns it, streamlining deployment. #### How RJUMPI Improves Security Over JUMPI `RJUMPI` uses relative offsets for jumps, which are checked during compilation to ensure they point to valid locations. This contrasts with `JUMPI`, which uses absolute offsets and requires runtime validation to ensure the jump destination is a valid `JUMPDEST`. By validating at compile time, `RJUMPI` reduces the risk of jumping to invalid or malicious locations, enhancing contract security and preventing runtime errors. #### Why JUMPF Helps with Stack Management `JUMPF` jumps to a predefined function section, likely with its own stack frame. This isolation means each function manages its stack separately, preventing the stack from becoming too deep. In standard EVM, the 16-slot stack limit often causes "Stack Too Deep" errors in complex contracts, but `JUMPF` ’s structure could mitigate this, making it easier to handle larger, more intricate contracts. #### Gas Savings from EOF’s Compile-Time Validation EOF validates contracts at deployment, eliminating the need for runtime checks like jump destination validation, which saves gas during execution. While exact savings vary by contract, this approach should reduce overhead, especially for frequently executed contracts. The structured format may also allow for more efficient EVM optimizations, further lowering costs. #### How EOFCREATE Might Change Contract Deployment Workflows `EOFCREATE` is a new opcode for creating EOF-formatted contracts, potentially simplifying deployment by ensuring contracts are structured and validated upfront. This could introduce new capabilities, like version-specific deployments, and might require adjustments in deployment tools, offering a more streamlined process compared to standard `CREATE`. # Related EIPs and Implementations Several EIPs complementing EOF’s implementation in the coming Ethereum Pectra upgrade are included in the [**EIP-7692**](https://eips.ethereum.org/EIPS/eip-7692) such as: - [EIP-3540](https://eips.ethereum.org/EIPS/eip-3540): Introduces EOF Version 1, establishing the initial structure for structured bytecode. - [EIP-3670](https://eips.ethereum.org/EIPS/eip-3670), [EIP-4200](https://eips.ethereum.org/EIPS/eip-4200), [EIP-4750](https://eips.ethereum.org/EIPS/eip-4750), [EIP-5450](https://eips.ethereum.org/EIPS/eip-5450), [EIP-6206](https://eips.ethereum.org/EIPS/eip-6206), [EIP-7480](https://eips.ethereum.org/EIPS/eip-7480), [EIP-663](https://eips.ethereum.org/EIPS/eip-663), [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069), [EIP-7620](https://eips.ethereum.org/EIPS/eip-7620), [EIP-7698](https://eips.ethereum.org/EIPS/eip-7698): Enhance EOF functionalities, improving security, efficiency, and usability across Ethereum’s ecosystem. ## Conclusion EOF represents Ethereum’s future, solving critical issues like "Stack Too Deep" and runtime `JUMPDEST` analysis with a structured, validated bytecode format. For `EOF.sol`, the EOF output is verbose but forward-looking, while the standard EVM output is minimal and practical today. As EOF matures, it’ll unlock new possibilities for Solidity developers—study its opcodes now to stay ahead!