An Operational Semantics for Yul
Vasileios Koutavas, Yu-Yang Lin, Nikos Tzevelekos
TL;DR
This work delivers a rigorous, tool-agnostic operational semantics for Yul, the Solidity compiler's intermediate representation, in both big-step and small-step forms and proves their equivalence. It provides a modular interpreter (YulTracer) parameterised by dialects (illustrated on a Shanghai-EVM subset) and validates the approach against Solidity tests and custom benchmarks. By clarifying under-specified aspects such as void function calls and multi-value returns, the paper establishes a foundation for formal verification and symbolic execution directly in Yul, with implications for security and correctness in Ethereum smart contracts. The results enable verifiable optimisations, guide future type-system work, and aim to unify disparate formalizations under a standard mathematical model.
Abstract
We present a big-step and small-step operational semantics for Yul -- the intermediate language used by the Solidity compiler to produce EVM bytecode -- in a mathematical notation that is congruous with the literature of programming languages, lends itself to language proofs, and can serve as a precise, widely accessible specification for the language. Our two semantics stay faithful to the original, informal specification of the language but also clarify under-specified cases such as void function calls. Our presentation allows us to prove the equivalence between the two semantics. We also implement the small-step semantics in an interpreter for Yul which avails of optimisations that are provably correct. We have tested the interpreter using tests from the Solidity compiler and our own. We envisage that this work will enable the development of verification and symbolic execution technology directly in Yul, contributing to the Ethereum security ecosystem, as well as aid the development of a provably sound future type system.
