eth-brownie / brownie

A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine.
https://eth-brownie.readthedocs.io
MIT License
2.65k stars 553 forks source link

KeyError: None when compiling contract. #1238

Open Grazfather opened 3 years ago

Grazfather commented 3 years ago

Environment information

What was wrong?

❯ ~/.local/bin/brownie compile
Brownie v1.16.3 - Python development framework for Ethereum

  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 746, in load
    return Project(name, project_path)
  File "brownie/project/main.py", line 180, in __init__
    self.load()
  File "brownie/project/main.py", line 214, in load
    self._build._add_contract(build_json)
  File "brownie/project/build.py", line 61, in _add_contract
    self._generate_revert_map(
  File "brownie/project/build.py", line 79, in _generate_revert_map
    path_str = source_map[data["path"]]
KeyError: None

How can it be fixed?

Looks like the Royalties contract has this opcode setup weird

"268": {
    "dev": "Cannot send ether to nonpayable function",
    "fn": "<unknown>",
    "offset": null,
    "op": "REVERT",
    "path": null
},

the "path": null is why we get a key None.

This is where the error happens:

    def _generate_revert_map(self, pcMap: Dict, source_map: Dict, language: str) -> None:
        # Adds a contract's dev revert strings to the revert map and it's pcMap
        marker = "//" if language == "Solidity" else "#"
        for pc, data in (
            (k, v)
            for k, v in pcMap.items()
            if v["op"] in ("REVERT", "INVALID") or "jump_revert" in v
        ):
            if "path" not in data:
                continue
            path_str = source_map[data["path"]]

Basically: path IS in data, but its value is None, which isn't a key in source_map.

I am working around the issue with this:

            # if "path" not in data:
                # continue
            if not data.get("path"):
                continue
            path_str = source_map[data["path"]]

Attached the contract in question. RecordLabel.txt

elizabethdinella commented 2 years ago

Any way to get around this without modifying the Brownie source? Perhaps in the config?