brownie
brownie copied to clipboard
Support "viaIR" solc option
Overview
with solidity 0.8.13, building with IR is no longer experimental. This can lead to smaller and more gas efficient contracts.
Specification
A quick (incomplete) change:
my-project $ git diff
diff --git a/brownie-config.yaml b/brownie-config.yaml
index ed34301..eae60df 100644
--- a/brownie-config.yaml
+++ b/brownie-config.yaml
@@ -12,6 +12,7 @@ compiler:
remappings:
- "@OpenZeppelin=OpenZeppelin/[email protected]/contracts"
+ viaIR: False
dependencies:
- OpenZeppelin/[email protected]
diff --git a/tests/taxes/test_taxes_eth.py b/tests/taxes/test_taxes_eth.py
index 0ce8a6e..b1cc1f8 100644
brownie $ git diff
diff --git a/brownie/project/compiler/__init__.py b/brownie/project/compiler/__init__.py
index b19f6b34..d05af226 100644
--- a/brownie/project/compiler/__init__.py
+++ b/brownie/project/compiler/__init__.py
@@ -58,6 +58,7 @@ def compile_and_format(
interface_sources: Optional[Dict[str, str]] = None,
remappings: Optional[list] = None,
optimizer: Optional[Dict] = None,
+ viaIR: Optional[bool] = None,
) -> Dict:
"""Compiles contracts and returns build data.
@@ -136,6 +137,7 @@ def compile_and_format(
interface_sources=interfaces,
remappings=remappings,
optimizer=optimizer,
+ viaIR=viaIR,
)
output_json = compile_from_input_json(input_json, silent, allow_paths)
@@ -153,6 +155,7 @@ def generate_input_json(
interface_sources: Optional[Dict[str, str]] = None,
remappings: Optional[list] = None,
optimizer: Optional[Dict] = None,
+ viaIR: Optional[bool] = None,
) -> Dict:
"""Formats contracts to the standard solc input json.
@@ -166,6 +169,7 @@ def generate_input_json(
interface_sources: dictionary of interfaces as {'path': "source code"}
remappings: list of solidity path remappings
optimizer: dictionary of solidity optimizer settings
+ viaIR: Change compilation pipeline to go through the Yul intermediate representation.
Returns: dict
"""
@@ -188,6 +192,8 @@ def generate_input_json(
if language == "Solidity":
input_json["settings"]["optimizer"] = optimizer
input_json["settings"]["remappings"] = _get_solc_remappings(remappings)
+ if viaIR is not None:
+ input_json["settings"]["viaIR"] = viaIR
input_json["sources"] = _sources_dict(contract_sources, language)
if interface_sources:
diff --git a/brownie/project/main.py b/brownie/project/main.py
index 7ab1f68b..6f459afc 100644
--- a/brownie/project/main.py
+++ b/brownie/project/main.py
@@ -108,6 +108,7 @@ class _ProjectBase:
allow_paths=allow_paths,
remappings=compiler_config["solc"].get("remappings", []),
optimizer=compiler_config["solc"].get("optimizer", None),
+ viaIR=compiler_config["solc"].get("viaIR", None),
)
finally:
os.chdir(cwd)
However, that fails with this error:
my-project $ brownie compile
Brownie v1.18.1 - Python development framework for Ethereum
Compiling contracts...
Solc version: 0.8.13
Optimizer: Enabled Runs: 2000
EVM Version: London
Generating build data...
- OpenZeppelin/[email protected]/Clones
- CloneFactory
File "/home/ski/code/brownie/brownie/_cli/__main__.py", line 64, in main
importlib.import_module(f"brownie._cli.{cmd}").main()
File "/home/ski/code/brownie/brownie/_cli/compile.py", line 50, in main
proj = project.load()
File "/home/ski/code/brownie/brownie/project/main.py", line 769, in load
return Project(name, project_path)
File "/home/ski/code/brownie/brownie/project/main.py", line 189, in __init__
self.load()
File "/home/ski/code/brownie/brownie/project/main.py", line 246, in load
self._compile(changed, self._compiler_config, False)
File "/home/ski/code/brownie/brownie/project/main.py", line 100, in _compile
build_json = compiler.compile_and_format(
File "/home/ski/code/brownie/brownie/project/compiler/__init__.py", line 144, in compile_and_format
build_json.update(generate_build_json(input_json, output_json, compiler_data, silent))
File "/home/ski/code/brownie/brownie/project/compiler/__init__.py", line 323, in generate_build_json
build_json[contract_alias] = solidity._get_unique_build_json(
File "/home/ski/code/brownie/brownie/project/compiler/solidity.py", line 260, in _get_unique_build_json
pc_map, statement_map, branch_map = _generate_coverage_data(
File "/home/ski/code/brownie/brownie/project/compiler/solidity.py", line 478, in _generate_coverage_data
fn_node = source_nodes[contract_id].children(
IndexError: list index out of range
I opened up a pull request addressing this issue, it seems that the « list index out of range » happens when brownie is building up coverage data with the viaIR setting activated in solc-c.
My best guest is that as mentioned in https://github.com/ethereum/solidity/blob/develop/docs/ir-breaking-changes.rst#internal-function-pointers the dispatch function pointer is causing trouble for brownie to match with function call in the specified source code offset range as the code as been completely rewritten by the optimizer in such way that correlation is not easy to manage.
The fix is about ignoring those jump where code could not be matched within the specified source code offset, the alternative would have been to match the whole contract instead.
Curious if this ever got fixed
Nop PR is still opened, no comments so far on this, I wonder how many are blocked by this issue.
PR got merged. You can test the code using the latest HEAD from the master branch of the eth-brownie repository and add viaIR: True
to your solc compiler option as below
$> cat brownie-config.yaml
[...]
compiler:
solc:
# viaIR option has been added in 0.8.13, you can adjust the version your need
version: 0.8.13
viaIR: True
When is this going to be available in a release?
You would have to wait for @iamdefinitelyahuman to ship a new package!
This has been fixed since #1572 and this issue can be closed!