We are excited to announce the release of the Solidity Compiler v0.8.35!
This release introduces a new builtin, erc7201, that computes the base slot of an ERC-7201 namespaced storage layout from its namespace string. It also formalizes how experimental features are exposed to users: in-development functionality is now gated behind a new top-level --experimental flag, with a documented lifecycle and a canonical list of which features are currently considered experimental. The first major code-generation feature shipped under this new lifecycle is an experimental SSA-form control-flow graph (SSA CFG) code generator that we expect to be the long-term answer to long compilation times as well as stack-too-deep errors in the IR pipeline. On the bugfix side, the IR pipeline no longer over-strips custom errors when compiled with --revert-strings strip.
It also continues the 0.9.0 deprecation work started in 0.8.31, this time warning about identifiers that will be promoted to keywords in 0.9.0.
Some of these features were previously available in the v0.8.35-pre.1 pre-release we shared back in March.
Notable Features and Changes
erc7201 Comptime Builtin
Solidity 0.8.35 introduces a new builtin function:
function erc7201(string memory id) returns (uint)
It computes the base storage slot for a namespace string using the formula defined in ERC-7201, equivalent to keccak256(keccak256(id) - 1) & ~0xff. ERC-7201 formalizes the practice of placing a contract's state behind a hashed namespace to avoid storage collisions in proxy-based and diamond-style upgradeable patterns.
The builtin pairs naturally with the layout at storage layout specifier introduced in 0.8.29 and extended in 0.8.31:
contract MyContract layout at erc7201("openzeppelin.storage.MyContract") {
uint256 x;
uint256 y;
}
What makes erc7201 special is that it is the first comptime builtin in the language. Until now, Solidity's comptime evaluator only handled arithmetic on rational number literals. Existing builtins like keccak256 do get folded by the codegen at the optimization stage; you get the gas savings, but not the type-system benefit of being usable in a comptime context such as a layout specifier. erc7201 is the first builtin whose result can be used wherever a comptime expression is required: as the base slot in layout at, or as an array length. This directly addresses one of the limitations we flagged in 0.8.31, and we expect more such builtins as we work toward a more capable comptime evaluator.
Formalizing the Experimental Feature Process
Past releases have shipped a number of in-development features that could be enabled through a mix of ad-hoc CLI flags and pragma experimental directives. There was no consistent way for a user to know they were opting into something unstable, and the metadata signaling was patchy.
With 0.8.35 we are formalizing this. The full process is described in the new Experimental Mode docs page; the key user-facing changes are below.
The --experimental Flag
Using any experimental feature now requires the new top-level --experimental flag, or the analogous boolean settings.experimental field in Standard JSON input. --experimental is a master toggle: it does not enable any specific feature on its own, but is required for any of the per-feature flags or pragmas to be accepted. The current list of experimental features, their IDs and the flags or pragmas that drive each one is maintained in the Experimental Mode docs page.
Using any of those without --experimental is now a hard error. Users who were already passing the affected flags directly will need to add --experimental (or set settings.experimental: true in JSON input) to keep their builds working. This is not a backwards-compatibility break: experimental features have always been excluded from our compatibility guarantees. What is new is making that explicit at the user-facing surface, so that no one is opting into experimental functionality without realizing it: experimental features come with no stability guarantees and may change in breaking ways even in non-breaking releases of the compiler.
Recorded in Metadata
Whether a contract was compiled with experimental mode enabled is now recorded in both JSON and CBOR metadata. The CBOR experimental field, which previously only signalled experimental pragmas in the source, has been broadened to cover this. This also closes a known gap: targeting an unreleased EVM version used to produce experimental bytecode without flipping the flag.
Experimental SSA CFG Code Generator
Solidity 0.8.35 ships an experimental new EVM backend for the IR pipeline. It generates bytecode from the program's SSA-form control-flow graphs (the "SSA CFGs", one per function), with a precomputed stack layout that the backend shuffles the EVM stack to match.
Why we are building it: the IR pipeline has two long-standing pain points, stack-too-deep errors and slow compilation, and an SSA-based backend addresses both. Stack-too-deep remained the most commonly reported recurring issue in our 2025 Developer Survey, and compilation via IR has long been measurably slower than the evmasm pipeline. The current Yul-to-EVM code transform relies on heuristics that struggle with deeply nested expressions and complex control flow, and the same algorithmic issues contribute to long compilation times. An SSA-based backend gives us a much stronger foundation for stack scheduling and compilation performance, and we see it as the realistic long-term path to addressing both.
If you want a deeper look at how the SSA CFG works, we covered it in a talk at Solidity Summit.
Enable the codegen with --experimental --via-ssa-cfg on the command line, or settings.experimental: true together with settings.viaSSACFG: true in Standard JSON. Both imply --via-ir.
This is an early experimental release. Several pieces are not yet in:
- Stack-to-memory spilling has not yet been ported to the SSA backend.
- Optimizer passes specific to the SSA CFG are still in development.
- Compilation-performance work, one of the long-term motivations, has not landed.
- Cases that exhaust the stack scheduler currently surface as internal compiler errors rather than graceful "stack too deep" or spilling diagnostics.
The codegen is exercised against the full external-contract semantic test suite on every PR, but it is not yet the default for --via-ir, and gas data alone will not be sufficient to promote it. Before this becomes the default we expect to put it through review, fuzzing, and likely an external audit.
Per the new experimental policy, only major changes affecting the SSA CFG codegen will be recorded in the changelog.
Deprecation Warnings for Upcoming 0.9.0 Keywords
Continuing the deprecation work started in 0.8.31, this release adds warnings for identifiers we plan to promote to keywords in 0.9.0. Where 0.8.31's deprecations were about features being removed, this batch is about names being claimed.
Solidity declarations using at, error, layout, leave, super, this, or transient will now emit a warning.
In Yul (standalone or inline assembly), leave will become a Yul keyword, and basefee, blobbasefee, blobhash, clz, mcopy, memoryguard, prevrandao, tload, and tstore will become Yul reserved identifiers. The latter are all Yul builtins, which we normally keep reserved; the growing list of exceptions is a quirk of the unusually long 0.8.x release cycle, since our backwards-compatibility policy holds them until 0.9.0.
These are warnings, not errors. Existing code continues to compile; you have a window to rename affected declarations before 0.9.0 turns the warnings into errors.
--revert-strings strip and Custom Errors
--revert-strings strip (revertStrings: "strip" in Standard JSON) is a gas-saving option: bytecode is smaller without revert reason strings, and reverts still happen. The implicit assumption was that returndata is a way to deliver a nice message to a user, not a piece of structured data that another contract should depend on.
require(condition, CustomError(...)) complicates that picture, because a custom error encodes structured data. Until 0.8.35, the IR pipeline (--via-ir) was stripping the custom-error argument of require along with strings, so a failed require reverted with empty error data instead of the encoded custom error. The evmasm pipeline behaved differently. The bug here is the discrepancy between pipelines: it could in principle be fixed either way, and we chose to keep the custom error rather than extend --revert-strings strip into a third meaning.
This only affected require(), not plain revert statements with a custom error, and only on the IR pipeline. It has been present since require(bool, error) was introduced in 0.8.26 and is fixed in 0.8.35.
ethdebug Output Reorganization
This release reorganizes the ethdebug output selection to be more granular and consistent with how other outputs are exposed. --ethdebug and --ethdebug-runtime are replaced by --ethdebug-resources, --ethdebug-compilation, --ethdebug-program, and --ethdebug-program-runtime, with analogous keys in Standard JSON. ethdebug outputs no longer force a full binary compilation, and ethdebug remains experimental, now gated behind --experimental like the other experimental features.
Full Changelog
Language Features
- General: Add a builtin that computes the base slot of a storage namespace using the erc7201 formula from ERC-7201.
- Name Resolver: Warn about identifiers selected for future promotion to Solidity or Yul keywords (at, error, layout, leave, super, transient, this).
- Yul Analyzer: Warn about identifiers selected for future promotion to Yul keywords and reserved identifiers (basefee, blobbasefee, blobhash, clz, leave, memoryguard, mcopy, prevrandao, tload, tstore).
Compiler Features
- Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via --assemble instead of treating it as equivalent to --strict-assembly.
- Commandline Interface: Introduce --experimental flag required for enabling the experimental mode.
- Commandline Interface: Replace the experimental --ethdebug and --ethdebug-runtime outputs with the more granular --ethdebug-resources, --ethdebug-compilation, --ethdebug-program and --ethdebug-program-runtime. Producing ethdebug/format/info/resources no longer forces full binary compilation.
- EVM: Introduce experimental EVM version @future.
- General: Improve performance of sanity checks throughout the compiler implementation.
- General: Introduce the SSA CFG codegen (experimental).
- General: Restrict the existing experimental features (generic-solidity, lsp, ethdebug, eof, evm, ast-import, evmasm-import, ir-ast, ssa-cfg) to experimental mode.
- Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing experimental field, which used to indicate only the presence of certain experimental pragmas in the source.
- Standard JSON Interface: Introduce settings.experimental setting required for enabling the experimental mode.
- Standard JSON Interface: Replace the experimental top-level ethdebug output with ethdebug.resources and ethdebug.compilation. Decouple ethdebug outputs from binary compilation so that requesting the ethdebug/format/info/resources schema artifacts does not trigger bytecode generation.
- Yul Optimizer: Improve performance of control flow side effects collector and function references resolver.
Bugfixes
- Yul: Fix incorrect serialization of Yul object names containing double quotes and escape sequences, producing output that could not be parsed as valid Yul.
- Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue.
- Yul IR Code Generation: Preserve custom error argument of require when stripping of revert strings is selected via --revert-strings strip.
How to Install/Upgrade?
To upgrade to the new version of the Solidity Compiler, please follow the installation instructions available in our documentation. You can download the release from GitHub: v0.8.35.
If you want to build from the source code, do not use the source archives generated automatically by GitHub. Instead, use the solidity_0.8.35.tar.gz source tarball or check out the v0.8.35 tag via git.
And last but not least, we would like to give a big thank you to all the contributors who helped make this release possible!
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.