Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ small.label {
}
</style>

## Unreleased

Features & improvements:

- added support for Solidity 0.8.35, including the `erc7201` builtin, `ast-id` debug annotations, the experimental `@future` EVM and SSA CFG pipeline, `yulCFGJson`, and Ethdebug standard JSON interfaces <small class="label">[core]</small>
- fixed compiler checksum verification when a stable release and prerelease share a version number <small class="label">[core]</small>

## 4.22.1 <small>(Mar 2, 2026)</small> { id="4.22.1" }

Fixes & improvements:
Expand Down
29 changes: 26 additions & 3 deletions docs/compilation.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ exclude_paths = ["node_modules", "venv", ".venv", "lib", "script", "test"]

## Via IR

The compiler can can generate bytecode by converting the sources to Yul first (`Solidity -> Yul -> EVM bytecode`) instead of the traditional `Solidity -> EVM bytecode` approach.
See the [Solidity documentation]() for more information.
The compiler can generate bytecode by converting the sources to Yul first (`Solidity -> Yul -> EVM bytecode`) instead of the traditional `Solidity -> EVM bytecode` approach.
See the [Solidity documentation](https://docs.soliditylang.org/en/latest/ir-breaking-changes.html) for more information.

By default, the `via_IR` config option is left unset, which leaves the decision to the compiler.
It can be enabled by setting the option to `true`:
Expand All @@ -86,9 +86,32 @@ via_IR = true
!!! note "`Stack too deep` errors"
One way to avoid `Stack too deep` errors is to enable `via_IR` and the optimizer.

## Solidity 0.8.35 experimental features

Solidity 0.8.35 introduced an explicit experimental mode, the experimental `@future` EVM target, and an experimental SSA CFG code generation pipeline. They can be enabled using:

```toml title="wake.toml"
[compiler.solc]
target_version = "0.8.35"
experimental = true
evm_version = "@future"
via_SSA_CFG = true
```

`via_SSA_CFG` implies `via_IR`. Both `via_SSA_CFG` and `@future` require experimental mode. Experimental compiler features do not provide the same backwards-compatibility guarantees as stable Solidity features.

Wake also supports the following Solidity 0.8.35 standard JSON additions through `wake.compiler.solc_frontend`:

- `settings.debug.debugInfo` accepts `ast-id` annotations and experimental `ethdebug` annotations;
- `yulCFGJson` exposes the control-flow graph of the SSA-form Yul code;
- `evm.bytecode.ethdebug` and `evm.deployedBytecode.ethdebug` expose Ethdebug programs for creation and deployed bytecode;
- `ethdebug.resources` and `ethdebug.compilation` expose global Ethdebug resources and compilation information.

Ethdebug is experimental, and its bytecode-level outputs can only be requested when compiling via IR. Requesting an Ethdebug output automatically enables the `ethdebug` debug annotation. Wake's IR also recognizes the Solidity 0.8.35 `erc7201` builtin used in storage layout expressions.

## Optimizer

Wake allows setting all optimizer options supported by the Solidity compiler (see the [Solidity documentation](https://docs.soliditylang.org/en/v0.8.22/using-the-compiler.html#input-description)).
Wake allows setting all optimizer options supported by the Solidity compiler (see the [Solidity documentation](https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description)).
By default, Wake leaves the `enabled` option unset, which leaves the decision to the compiler.
It can be enabled by setting the option to `true`:
```toml title="wake.toml"
Expand Down
6 changes: 5 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ Wake can be configured using configuration options loaded from multiple sources
[compiler.solc]
allow_paths = []
# evm_version (unset - let the compiler decide)
# experimental (unset - disabled by the compiler)
exclude_paths = ["node_modules", "venv", ".venv", "lib", "script", "test"]
include_paths = ["node_modules"]
remappings = []
# target_version (unset - use the latest version)
# via_IR (unset - let the compiler decide)
# via_SSA_CFG (unset - let the compiler decide)

[compiler.solc.optimizer]
# enabled (unset - let the compiler decide)
Expand Down Expand Up @@ -166,12 +168,14 @@ Additionally, detectors and printers may use this namespace to load needed API k
| Option | Description |
|:------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------|
| `allow_paths` | Allow paths passed to the `solc` executable |
| `evm_version` | EVM version as specified by the [Solidity docs](https://docs.soliditylang.org/en/latest/using-the-compiler.html#target-options) |
| `evm_version` | EVM version as specified by the [Solidity docs](https://docs.soliditylang.org/en/latest/using-the-compiler.html#target-options); `@future` requires Solidity 0.8.35+ and experimental mode |
| `experimental` | Enable Solidity experimental mode; supported by Solidity 0.8.35 and newer |
| `exclude_paths` | Files in these paths are not compiled unless imported from other non-excluded files |
| <nobr>`include_paths`</nobr> | Paths (along with the current working directory) where files from non-relative imports are searched |
| `remappings` | Compiler remappings as specified by the [Solidity docs](https://docs.soliditylang.org/en/latest/path-resolution.html#import-remapping) |
| <nobr>`target_version`</nobr> | Target `solc` version used to compile the project |
| `via_IR` | Compile the code via the Yul intermediate language (see the [Solidity docs](https://docs.soliditylang.org/en/latest/ir-breaking-changes.html)) |
| `via_SSA_CFG` | Compile through the experimental SSA CFG backend on Solidity 0.8.35+; implies `via_IR` and requires `experimental = true` |

!!! info
The `include_paths` option is the preferred way to handle imports of libraries. Remappings should be used only when `include_paths` cannot be used (e.g. when the import path differs from the system path of the imported file).
Expand Down
26 changes: 21 additions & 5 deletions docs/wake-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@
},
"evm_version": {
"type": "string",
"description": "Version of the EVM to compile for",
"enum": ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg", "istanbul", "berlin", "london", "paris", "shanghai", "cancun", "prague", "osaka"]
"description": "Version of the EVM to compile for; @future requires Solidity 0.8.35+ and experimental mode",
"enum": ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg", "istanbul", "berlin", "london", "paris", "shanghai", "cancun", "prague", "osaka", "@future"]
},
"experimental": {
"type": "boolean",
"description": "Enable Solidity compiler experimental mode (Solidity 0.8.35+)"
},
"exclude_paths": {
"type": "array",
Expand Down Expand Up @@ -104,6 +108,10 @@
"type": "boolean",
"description": "Use new IR-based compiler pipeline"
},
"via_SSA_CFG": {
"type": "boolean",
"description": "Use the experimental SSA CFG code generation pipeline (Solidity 0.8.35+); implies via_IR and requires experimental mode"
},
"metadata": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -460,8 +468,12 @@
},
"evm_version": {
"type": "string",
"description": "Version of the EVM to compile for",
"enum": ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg", "istanbul", "berlin", "london", "paris", "shanghai", "cancun", "prague", "osaka"]
"description": "Version of the EVM to compile for; @future requires Solidity 0.8.35+ and experimental mode",
"enum": ["homestead", "tangerineWhistle", "spuriousDragon", "byzantium", "constantinople", "petersburg", "istanbul", "berlin", "london", "paris", "shanghai", "cancun", "prague", "osaka", "@future"]
},
"experimental": {
"type": "boolean",
"description": "Enable Solidity compiler experimental mode (Solidity 0.8.35+)"
},
"optimizer": {
"type": "object",
Expand Down Expand Up @@ -500,6 +512,10 @@
"type": "boolean",
"description": "Use new IR-based compiler pipeline"
},
"via_SSA_CFG": {
"type": "boolean",
"description": "Use the experimental SSA CFG code generation pipeline (Solidity 0.8.35+); implies via_IR and requires experimental mode"
},
"metadata": {
"type": "object",
"properties": {
Expand All @@ -515,4 +531,4 @@
}
}
}
}
}
12 changes: 12 additions & 0 deletions tests/solidity_versions/solidity_0_8_35.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.35;

contract Solidity0835 layout at erc7201("wake.test.solidity-0.8.35") {
uint256 public value;

function assemblyValue() external pure returns (uint256 ret) {
assembly {
ret := 1
}
}
}
114 changes: 114 additions & 0 deletions tests/test_compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@

from wake.cli.__main__ import main
from wake.compiler import SolcOutputSelectionEnum, SolidityCompiler
from wake.compiler.solc_frontend import (
SolcFrontend,
SolcInputDebugInfoSettingsEnum,
SolcInputDebugSettings,
SolcInputOptimizerSettings,
SolcInputSettings,
)
from wake.config import WakeConfig
from wake.core.enums import EvmVersionEnum
from wake.core.solidity_version import SolidityVersion
from wake.ir import ContractDefinition, FunctionCall, InlineAssembly
from wake.ir.enums import FunctionTypeKind, GlobalSymbol, InlineAssemblyEvmVersion
from wake.utils import change_cwd

PYTEST_BUILD_PATH = Path.home() / ".tmpwake_rkDv61DDf7"
Expand Down Expand Up @@ -202,3 +213,106 @@ def test_compile_axelar(setup_project, config):
},
)
assert cli_result.exit_code == 0


@pytest.mark.slow
@pytest.mark.platform_dependent
def test_compile_solidity_0_8_35(tmp_path, monkeypatch):
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "config"))
monkeypatch.setenv("XDG_DATA_HOME", str(tmp_path / "data"))
source_path = (
Path(__file__).parent / "solidity_versions" / "solidity_0_8_35.sol"
).resolve()
project_root = Path(__file__).parent.parent.resolve()
config = WakeConfig.fromdict(
{
"compiler": {
"solc": {
"target_version": "0.8.35",
"experimental": True,
"evm_version": "@future",
"via_SSA_CFG": True,
"optimizer": {"enabled": True},
}
}
},
project_root_path=project_root,
)
compiler = SolidityCompiler(config)

build, errors = asyncio.run(
compiler.compile(
[source_path],
[SolcOutputSelectionEnum.ALL],
write_artifacts=False,
force_recompile=True,
)
)

assert errors == set()
source_unit = build.source_units[source_path]
inline_assembly = next(
node for node in source_unit if isinstance(node, InlineAssembly)
)
assert inline_assembly.evm_version == InlineAssemblyEvmVersion.FUTURE
contract = next(
declaration
for declaration in source_unit.declarations_iter()
if isinstance(declaration, ContractDefinition)
)
assert contract.storage_layout is not None
base_slot_expression = contract.storage_layout.base_slot_expression
assert isinstance(base_slot_expression, FunctionCall)
assert base_slot_expression.function_called == GlobalSymbol.ERC7201
assert base_slot_expression.expression.type.kind == FunctionTypeKind.ERC7201

frontend = SolcFrontend(config)
version = SolidityVersion.fromstring("0.8.35")
source = source_path.read_text()
ssa_output = asyncio.run(
frontend.compile(
{},
{"C.sol": source},
version,
SolcInputSettings(
experimental=True,
evm_version=EvmVersionEnum.FUTURE,
via_SSA_CFG=True,
optimizer=SolcInputOptimizerSettings(enabled=True),
output_selection={"*": {"*": [SolcOutputSelectionEnum.YUL_CFG_JSON]}},
),
)
)
assert ssa_output.contracts["C.sol"]["Solidity0835"].yul_CFG_json is not None

ethdebug_output = asyncio.run(
frontend.compile(
{},
{"C.sol": source},
version,
SolcInputSettings(
experimental=True,
via_IR=True,
debug=SolcInputDebugSettings(
debug_info=[
SolcInputDebugInfoSettingsEnum.AST_ID,
SolcInputDebugInfoSettingsEnum.ETHDEBUG,
]
),
optimizer=SolcInputOptimizerSettings(enabled=False),
output_selection={
"*": {
"*": [
SolcOutputSelectionEnum.EVM_BYTECODE_ETHDEBUG,
SolcOutputSelectionEnum.EVM_DEPLOYED_BYTECODE_ETHDEBUG,
SolcOutputSelectionEnum.ETHDEBUG_RESOURCES,
SolcOutputSelectionEnum.ETHDEBUG_COMPILATION,
]
}
},
),
)
)
assert ethdebug_output.ethdebug is not None
assert ethdebug_output.ethdebug["resources"] is not None
assert ethdebug_output.ethdebug["compilation"] is not None
29 changes: 29 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pydantic
import pytest

from wake.cli.init import write_config
from wake.config import WakeConfig
from wake.config.data_model import SolcRemapping
from wake.core.enums import EvmVersionEnum
Expand Down Expand Up @@ -82,6 +83,34 @@ def test_config_from_dict():
assert config.compiler.solc.target_version == SolidityVersion.fromstring("0.8.12")


def test_config_solidity_0_8_35_experimental(tmp_path):
config = WakeConfig.fromdict(
{
"compiler": {
"solc": {
"evm_version": "@future",
"experimental": True,
"target_version": "0.8.35",
"via_SSA_CFG": True,
}
}
},
project_root_path=tmp_path,
)

assert config.compiler.solc.evm_version == EvmVersionEnum.FUTURE
assert config.compiler.solc.experimental is True
assert config.compiler.solc.target_version == SolidityVersion.fromstring("0.8.35")
assert config.compiler.solc.via_SSA_CFG is True

write_config(config)
written_config = config.local_config_path.read_text()
assert 'evm_version = "@future"' in written_config
assert "experimental = true" in written_config
assert 'target_version = "0.8.35"' in written_config
assert "via_SSA_CFG = true" in written_config


@pytest.mark.platform_dependent
def test_config_global():
os.environ["XDG_CONFIG_HOME"] = str(sources_path / "containing_global_conf")
Expand Down
Loading