crytic / slither

Static Analyzer for Solidity and Vyper
https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/
GNU Affero General Public License v3.0
5.34k stars 970 forks source link

slither fails for specific brownie projects #1616

Open UsmannK opened 1 year ago

UsmannK commented 1 year ago

I think this is actually a bug in brownie, but I'm not sure.

Brownie doesn't output compilation artifacts for some solidity files. For example, a helper file that only has some free functions. When slither is crawling file imports, it looks for the helper file's compilation artifact and then doesn't find it, so it crashes.

Example repo where slither crashes: https://github.com/UsmannK/slither-brownie-test

Test.sol

import { magic_number } from "./Helper.sol";

contract Test {
    function test() public pure returns (uint256) {
        return magic_number();
    }
}

Helper.sol

function magic_number() pure returns (uint256) {
    return 0xdeadbeef;
}

Output

$ slither .         
Brownie v1.19.2 - Python development framework for Ethereum

Project has been compiled. Build artifacts saved at /Users/usmannkhan/Development/brownie-test/build/contracts

Traceback (most recent call last):
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 834, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 98, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 76, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/slither.py", line 112, in __init__
    parser.parse_top_level_from_loaded_json(ast, path)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 281, in parse_top_level_from_loaded_json
    get_imported_scope = self.compilation_unit.get_scope(import_directive.filename)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/core/compilation_unit.py", line 243, in get_scope
    filename = self._crytic_compile_compilation_unit.crytic_compile.filename_lookup(
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/crytic_compile/crytic_compile.py", line 182, in filename_lookup
    raise ValueError(f"{filename} does not exist")
ValueError: contracts/Helper.sol does not exist
Error in .
Traceback (most recent call last):
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 834, in main_impl
    ) = process_all(filename, args, detector_classes, printer_classes)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 98, in process_all
    ) = process_single(compilation, args, detector_classes, printer_classes)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/__main__.py", line 76, in process_single
    slither = Slither(target, ast_format=ast, **vars(args))
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/slither.py", line 112, in __init__
    parser.parse_top_level_from_loaded_json(ast, path)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 281, in parse_top_level_from_loaded_json
    get_imported_scope = self.compilation_unit.get_scope(import_directive.filename)
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/slither/core/compilation_unit.py", line 243, in get_scope
    filename = self._crytic_compile_compilation_unit.crytic_compile.filename_lookup(
  File "/Users/usmannkhan/.pyenv/versions/3.10.7/lib/python3.10/site-packages/crytic_compile/crytic_compile.py", line 182, in filename_lookup
    raise ValueError(f"{filename} does not exist")
ValueError: contracts/Helper.sol does not exist
UsmannK commented 1 year ago

You can see brownie only makes an artifact for the main file

$ find build
build
build/contracts
build/contracts/Test.json
build/interfaces
build/deployments

It might actually be the case that the Helper.sol artifact was inlined into the other one, I'm not sure.

0xalpharush commented 1 year ago

This may be related to https://github.com/eth-brownie/brownie/issues/941. Will look into it and if there's not a work around/ fix, we'll update the list of platform limitations https://github.com/crytic/crytic-compile/issues/267

qingkaishi commented 1 year ago

The same issue when I use slither . to compile notional-v2.