brownie
brownie copied to clipboard
Using lib for * breaks compiler
Environment information
-
brownie
Version: 1.16.3 -
ganache-cli
Version: N/A -
solc
Version: 0.7.4 - Python Version: 3.9.1
- OS: linux
What was wrong?
when using a library in a solidity contract i used the syntax
using MerkleLib for *;
which throws the following confusing error:
Generating build data...
File "brownie/_cli/main.py", line 64, in main
importlib.import_module(f"brownie._cli.{cmd}").main()
File "brownie/_cli/compile.py", line 50, in main
proj = project.load()
File "brownie/project/main.py", line 745, in load
return Project(name, project_path)
File "brownie/project/main.py", line 180, in init
self.load()
File "brownie/project/main.py", line 235, in load
self._compile(changed, self._compiler_config, False)
File "brownie/project/main.py", line 92, in _compile
build_json = compiler.compile_and_format(
File "brownie/project/compiler/init.py", line 142, in compile_and_format
build_json.update(generate_build_json(input_json, output_json, compiler_data, silent))
File "brownie/project/compiler/init.py", line 287, in generate_build_json
source_nodes, statement_nodes, branch_nodes = solidity._get_nodes(output_json)
File "brownie/project/compiler/solidity.py", line 606, in _get_nodes
source_nodes = solcast.from_standard_output(output_json)
File "solcast/main.py", line 33, in from_standard_output
source_nodes = set_dependencies(source_nodes)
File "solcast/dependencies.py", line 18, in set_dependencies
contract.libraries = dict(
File "solcast/dependencies.py", line 19, in
If I change it to
using MerkleLib for bytes32;
it works. I'm pretty sure the * syntax is valid, because truffle accepts it, but it's probably better to be explicit in my contracts. But yeah probably the * syntax is being misinterpreted.
It's valid syntax right now but I'd recommend against using it if you don't have to. It's likely going to be deprecated in one of the future releases of the compiler: https://github.com/ethereum/solidity/issues/11882.
Ok, fair enough. It would probably be good to have a clear error message if you're not going to support it, tho
Having the same problem, is quite annoying actually.
I think I hit this when trying to load 0x153CdDD727e407Cb951f728F24bEB9A5FaaA8512:
>>> Contract("0x153CdDD727e407Cb951f728F24bEB9A5FaaA8512")
Fetching source of 0x153CdDD727e407Cb951f728F24bEB9A5FaaA8512 from api.etherscan.io...
File "<console>", line 1, in <module>
File "/home/ski/code/brownie/brownie/network/contract.py", line 898, in __init__
contract = self.from_explorer(
File "/home/ski/code/brownie/brownie/network/contract.py", line 1193, in from_explorer
build_json = compiler.compile_and_format(
File "/home/ski/code/brownie/brownie/project/compiler/__init__.py", line 142, 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 287, in generate_build_json
source_nodes, statement_nodes, branch_nodes = solidity._get_nodes(output_json)
File "/home/ski/code/brownie/brownie/project/compiler/solidity.py", line 606, in _get_nodes
source_nodes = solcast.from_standard_output(output_json)
File "solcast/main.py", line 33, in from_standard_output
source_nodes = set_dependencies(source_nodes)
File "solcast/dependencies.py", line 18, in set_dependencies
contract.libraries = dict(
File "solcast/dependencies.py", line 19, in <genexpr>
(_get_type_name(i.typeName), i.libraryName.name)
AttributeError: 'UsingForDirective' object has no attribute 'typeName'
Having the same issue with brownie & openzeppelin.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol
Has a using ShortStrings for *;
Which breaks the compiler
If this is valid Solidity syntax, I believe it should be supported by Brownie. Has anyone identified the cause?
in site-packages/solcast/dependencies.py there is this code:
# add immediate dependencies
for contract in contract_list:
contract.dependencies = set()
contract.libraries = dict(
(_get_type_name(i.typeName), i.libraryName.name)
for i in contract.nodes
if i.nodeType == "UsingForDirective"
)
In the case of using SomeLib for *;
, the nodeType is UsingForDirective, but i.typeName
does not exist, which triggers the crash.
I also reported the issue on OpenZeppelin side, https://github.com/OpenZeppelin/openzeppelin-contracts/issues/4322#issuecomment-1581557506, but arguably, it's more a brownie bug than an OpenZeppelin bug since it's valid solidity syntax.
is there a quick and dirty way to fix this?
looks like the problem is somewhere in https://github.com/iamdefinitelyahuman/py-solc-ast specifically grammar definitions https://github.com/iamdefinitelyahuman/py-solc-ast/blob/master/solcast/grammar.py UsingForDirective
instead of UsingForDeclaration
looks like the problem is somewhere in https://github.com/iamdefinitelyahuman/py-solc-ast specifically grammar definitions https://github.com/iamdefinitelyahuman/py-solc-ast/blob/master/solcast/grammar.py
UsingForDirective
instead ofUsingForDeclaration
this is wrong
in the ERC20Permit.sol (v4.9.3 of OpenZeppelin), there is the following statement:
using Counters for Counters.Counter;
which causes the same error
AttributeError: 'UsingForDirective' object has no attribute 'typeName'
is it the same issue or should I open a separate one?