Example #1
0
    def _compile_solidity(self):
        try:
            options = []
            if self.allow_paths:
                options.append(F"--allow-paths {self.allow_paths}")
                
            com = CryticCompile(self.source, solc_remaps=self.remap, solc_args=' '.join(options))
            contracts = self._extract_bin_obj(com)

            libs = com.contracts_names.difference(com.contracts_names_without_libraries)
            if libs:
                return self._link_libraries(self.source, libs)
            
            return contracts
        except InvalidCompilation as err:
            if not self.compilation_err:
                logging.critical("Solidity compilation failed. Please use -ce flag to see the detail.")
                if global_params.WEB:
                    six.print_({"error": "Solidity compilation failed."})
            else:
                logging.critical("solc output:\n" + self.source)
                logging.critical(err)
                logging.critical("Solidity compilation failed.")
                if global_params.WEB:
                    six.print_({"error": err})
            exit(1)
Example #2
0
    def __init__(self, target, **kwargs):
        '''
            Args:
                target (str | list(json) | CryticCompile)
            Keyword Args:
                solc (str): solc binary location (default 'solc')
                disable_solc_warnings (bool): True to disable solc warnings (default false)
                solc_arguments (str): solc arguments (default '')
                ast_format (str): ast format (default '--ast-compact-json')
                filter_paths (list(str)): list of path to filter (default [])
                triage_mode (bool): if true, switch to triage mode (default false)
                exclude_dependencies (bool): if true, exclude results that are only related to dependencies
                generate_patches (bool): if true, patches are generated (json output only)

                truffle_ignore (bool): ignore truffle.js presence (default false)
                truffle_build_directory (str): build truffle directory (default 'build/contracts')
                truffle_ignore_compile (bool): do not run truffle compile (default False)
                truffle_version (str): use a specific truffle version (default None)

                embark_ignore (bool): ignore embark.js presence (default false)
                embark_ignore_compile (bool): do not run embark build (default False)
                embark_overwrite_config (bool): overwrite original config file (default false)

        '''
        # list of files provided (see --splitted option)
        if isinstance(target, list):
            self._init_from_list(target)
        elif isinstance(target, str) and target.endswith('.json'):
            self._init_from_raw_json(target)
        else:
            super(Slither, self).__init__('')
            try:
                if isinstance(target, CryticCompile):
                    crytic_compile = target
                else:
                    crytic_compile = CryticCompile(target, **kwargs)
                self._crytic_compile = crytic_compile
            except InvalidCompilation as e:
                raise SlitherError('Invalid compilation: \n' + str(e))
            for path, ast in crytic_compile.asts.items():
                self._parse_contracts_from_loaded_json(ast, path)
                self._add_source_code(path)

        if kwargs.get('generate_patches', False):
            self.generate_patches = True

        self._detectors = []
        self._printers = []

        filter_paths = kwargs.get('filter_paths', [])
        for p in filter_paths:
            self.add_path_to_filter(p)

        self._exclude_dependencies = kwargs.get('exclude_dependencies', False)

        triage_mode = kwargs.get('triage_mode', False)
        self._triage_mode = triage_mode

        self._analyze_contracts()
Example #3
0
    def __init__(self, contract, **kwargs):
        '''
            Args:
                contract (str| list(json))
            Keyword Args:
                solc (str): solc binary location (default 'solc')
                disable_solc_warnings (bool): True to disable solc warnings (default false)
                solc_argeuments (str): solc arguments (default '')
                ast_format (str): ast format (default '--ast-compact-json')
                filter_paths (list(str)): list of path to filter (default [])
                triage_mode (bool): if true, switch to triage mode (default false)

                truffle_ignore (bool): ignore truffle.js presence (default false)
                truffle_build_directory (str): build truffle directory (default 'build/contracts')
                truffle_ignore_compile (bool): do not run truffle compile (default False)
                truffle_version (str): use a specific truffle version (default None)

                embark_ignore (bool): ignore embark.js presence (default false)
                embark_ignore_compile (bool): do not run embark build (default False)
                embark_overwrite_config (bool): overwrite original config file (default false)

        '''

        truffle_ignore = kwargs.get('truffle_ignore', False)
        embark_ignore = kwargs.get('embark_ignore', False)

        # list of files provided (see --splitted option)
        if isinstance(contract, list):
            self._init_from_list(contract)
        elif contract.endswith('.json'):
            self._init_from_raw_json(contract)
        else:
            super(Slither, self).__init__('')
            try:
                cryticCompile = CryticCompile(contract, **kwargs)
                self._crytic_compile = cryticCompile
            except InvalidCompilation as e:
                logger.error('Invalid compilation')
                logger.error(e)
                exit(-1)
            for path, ast in cryticCompile.asts.items():

                self._parse_contracts_from_loaded_json(ast, path)
                with open(path) as f:
                    self.source_code[path] = f.read()

        self._detectors = []
        self._printers = []

        filter_paths = kwargs.get('filter_paths', [])
        for p in filter_paths:
            self.add_path_to_filter(p)

        triage_mode = kwargs.get('triage_mode', False)
        self._triage_mode = triage_mode

        self._analyze_contracts()
Example #4
0
    def _link_libraries(self, filename, libs):
        options = []
        for idx, lib in enumerate(libs):
            lib_address = "0x" + hex(idx+1)[2:].zfill(40)
            options.append("--libraries %s:%s" % (lib, lib_address))
        if self.allow_paths:
            options.append(F"--allow-paths {self.allow_paths}")
        com = CryticCompile(target=self.source, solc_args=' '.join(options), solc_remaps=self.remap)

        return self._extract_bin_obj(com)
Example #5
0
def _generate_compile(test_item: Item, skip_existing=False):
    flavor = "legacy" if test_item.is_legacy else "compact"
    test_file = os.path.join(TEST_ROOT, f"{test_item.test_id}-{test_item.base_ver}.sol")
    expected_file = os.path.join(
        TEST_ROOT, "compile", f"{test_item.test_id}-{test_item.solc_ver}-{flavor}.zip"
    )

    if skip_existing:
        if os.path.isfile(expected_file):
            return

    set_solc(test_item)

    cc = CryticCompile(test_file, solc_force_legacy_json=test_item.is_legacy)
    print(f"Compiled to {expected_file}")
    save_to_zip([cc], expected_file)
Example #6
0
def load_from_zip(target: str) -> List["CryticCompile"]:
    """
    Load a file from a zip
    :param target:
    :return:
    """
    from crytic_compile.crytic_compile import CryticCompile

    compilations = []
    with ZipFile(target, "r") as file_desc:
        for project in file_desc.namelist():
            compilations.append(
                CryticCompile(str(file_desc.read(project)),
                              compile_force_framework="archive"))

    return compilations
Example #7
0
def main() -> None:

    l = logging.getLogger("evm-cfg-builder")
    l.setLevel(logging.INFO)
    args = parse_args()

    cp: Optional[cProfile.Profile] = None
    if args.perf:
        cp = cProfile.Profile()
        cp.enable()

    if is_supported(args.filename):
        filename = args.filename
        del args.filename
        try:
            cryticCompile = CryticCompile(filename, **vars(args))
            for key, compilation_unit in cryticCompile.compilation_units.items(
            ):
                for contract in compilation_unit.contracts_names:
                    bytecode_init = compilation_unit.bytecode_init(contract)
                    if bytecode_init:
                        for signature, hash_id in compilation_unit.hashes(
                                contract).items():
                            known_hashes[hash_id] = signature
                        logger.info(f"Analyze {contract}")
                        _run(bytecode_init,
                             f"{key}-{filename}-{contract}-init", args)
                        runtime_bytecode = compilation_unit.bytecode_runtime(
                            contract)
                        if runtime_bytecode:
                            _run(runtime_bytecode,
                                 f"{key}-{filename}-{contract}-runtime", args)
                        else:
                            logger.info("Runtime bytecode not available")
        except InvalidCompilation as e:
            logger.error(e)

    else:
        with open(args.filename, "rb") as f:
            bytecode = f.read()
        logger.info(f"Analyze {args.filename}")
        _run(bytecode, args.filename, args)

    if args.perf and cp:
        cp.disable()
        stats = pstats.Stats(cp).sort_stats("cumtime")
        stats.print_stats()
Example #8
0
def load_from_zip(target: str) -> List["CryticCompile"]:
    """Load a file from a zip

    Args:
        target (str): path to the

    Returns:
        List[CryticCompile]: List of loaded projects
    """
    # pylint: disable=import-outside-toplevel
    from crytic_compile.crytic_compile import CryticCompile

    compilations = []
    with ZipFile(target, "r") as file_desc:
        for project in file_desc.namelist():
            compilations.append(
                CryticCompile(_to_str(file_desc.read(project)),
                              compile_force_framework="Archive"))

    return compilations
Example #9
0
def _generate_compile(test_item: Test, skip_existing=False):
    for version, flavor in test_item.versions_with_flavors:
        test_file = os.path.join(TEST_ROOT, test_item.test_file)
        expected_file = os.path.join(
            TEST_ROOT, "compile",
            f"{test_item.test_file}-{version}-{flavor}.zip")

        if skip_existing:
            if os.path.isfile(expected_file):
                continue

        set_solc(version)
        print(f"Compiled to {expected_file}")
        cc = CryticCompile(test_file,
                           solc_force_legacy_json=flavor == "legacy")

        # pylint: disable=no-member
        Path(expected_file).parents[0].mkdir(parents=True, exist_ok=True)

        save_to_zip([cc], expected_file)
Example #10
0
def main():

    l = logging.getLogger('evm-cfg-builder')
    l.setLevel(logging.INFO)
    args = parse_args()

    if args.perf:
        cp = cProfile.Profile()
        cp.enable()

    if is_supported(args.filename):
        filename = args.filename
        del args.filename
        try:
            cryticCompile = CryticCompile(filename, **vars(args))
            for contract in cryticCompile.contracts_names:
                bytecode_init = cryticCompile.bytecode_init(contract)
                if bytecode_init:
                    for signature, hash in cryticCompile.hashes(contract).items():
                        known_hashes[hash] = signature
                    logger.info(f'Analyze {contract}')
                    _run(bytecode_init, f'{filename}-{contract}-init', args)
                    runtime_bytecode = cryticCompile.bytecode_runtime(contract)
                    if runtime_bytecode:
                        _run(runtime_bytecode,  f'{filename}-{contract}-runtime', args)
                    else:
                        logger.info('Runtime bytecode not available')
        except InvalidCompilation as e:
            logger.error(e)

    else:
        with open(args.filename, 'rb') as f:
            bytecode = f.read()
        logger.info(f'Analyze {args.filename}')
        _run(bytecode, args.filename, args)

    if args.perf:
        cp.disable()
        stats = pstats.Stats(cp).sort_stats("cumtime")
        stats.print_stats()
Example #11
0
def complie_solc(source,
                 contract_name,
                 compiler_version,
                 remappings='',
                 solc_args=''):
    """Function is used to compile solidity contract and return its trimmed bytecode.

    :param source: Path to contract file
    :param contract_name: Name of the contract whose bytecode is required
    :param compiler_version: Compiler version requirement of the contract file
    :param remappings: String containing library remappings required to compile contract
    :param solc_args: String containing additional compiler argument flags
    :return: Trimmed bytecode of the contract
    """
    try:
        com = CryticCompile(source,
                            solc_remaps=remappings,
                            solc_solcs_select=compiler_version,
                            solc_args=solc_args)
        return trim_bytecode(com.bytecode_runtime(contract_name),
                             compiler_version)
    except InvalidCompilation as e:
        logging.exception(e)
        return None
Example #12
0
    def __init__(self, target, **kwargs):
        """
        Args:
            target (str | list(json) | CryticCompile)
        Keyword Args:
            solc (str): solc binary location (default 'solc')
            disable_solc_warnings (bool): True to disable solc warnings (default false)
            solc_arguments (str): solc arguments (default '')
            ast_format (str): ast format (default '--ast-compact-json')
            filter_paths (list(str)): list of path to filter (default [])
            triage_mode (bool): if true, switch to triage mode (default false)
            exclude_dependencies (bool): if true, exclude results that are only related to dependencies
            generate_patches (bool): if true, patches are generated (json output only)

            truffle_ignore (bool): ignore truffle.js presence (default false)
            truffle_build_directory (str): build truffle directory (default 'build/contracts')
            truffle_ignore_compile (bool): do not run truffle compile (default False)
            truffle_version (str): use a specific truffle version (default None)

            embark_ignore (bool): ignore embark.js presence (default false)
            embark_ignore_compile (bool): do not run embark build (default False)
            embark_overwrite_config (bool): overwrite original config file (default false)

        """
        super().__init__()
        self._parser: FortressSolc  #  This could be another parser, like FortressVyper, interface needs to be determined

        self._disallow_partial: bool = kwargs.get("disallow_partial", False)
        self._skip_assembly: bool = kwargs.get("skip_assembly", False)

        # list of files provided (see --splitted option)
        if isinstance(target, list):
            self._init_from_list(target)
        elif isinstance(target, str) and target.endswith(".json"):
            self._init_from_raw_json(target)
        else:
            self._parser = FortressSolc("", self)
            try:
                if isinstance(target, CryticCompile):
                    crytic_compile = target
                else:
                    crytic_compile = CryticCompile(target, **kwargs)
                self._crytic_compile = crytic_compile
            except InvalidCompilation as e:
                # pylint: disable=raise-missing-from
                raise FortressError(f"Invalid compilation: \n{str(e)}")
            for path, ast in crytic_compile.asts.items():
                self._parser.parse_contracts_from_loaded_json(ast, path)
                self.add_source_code(path)

        if kwargs.get("generate_patches", False):
            self.generate_patches = True

        self._markdown_root = kwargs.get("markdown_root", "")

        self._detectors = []
        self._printers = []

        filter_paths = kwargs.get("filter_paths", [])
        for p in filter_paths:
            self.add_path_to_filter(p)

        self._exclude_dependencies = kwargs.get("exclude_dependencies", False)

        triage_mode = kwargs.get("triage_mode", False)
        self._triage_mode = triage_mode

        self._parser.parse_contracts()

        # skip_analyze is only used for testing
        if not kwargs.get("skip_analyze", False):
            self._parser.analyze_contracts()
Example #13
0
    def __init__(self, target: Union[str, CryticCompile], **kwargs):
        """
        Args:
            target (str | CryticCompile)
        Keyword Args:
            solc (str): solc binary location (default 'solc')
            disable_solc_warnings (bool): True to disable solc warnings (default false)
            solc_arguments (str): solc arguments (default '')
            ast_format (str): ast format (default '--ast-compact-json')
            filter_paths (list(str)): list of path to filter (default [])
            triage_mode (bool): if true, switch to triage mode (default false)
            exclude_dependencies (bool): if true, exclude results that are only related to dependencies
            generate_patches (bool): if true, patches are generated (json output only)

            truffle_ignore (bool): ignore truffle.js presence (default false)
            truffle_build_directory (str): build truffle directory (default 'build/contracts')
            truffle_ignore_compile (bool): do not run truffle compile (default False)
            truffle_version (str): use a specific truffle version (default None)

            embark_ignore (bool): ignore embark.js presence (default false)
            embark_ignore_compile (bool): do not run embark build (default False)
            embark_overwrite_config (bool): overwrite original config file (default false)

        """
        super().__init__()

        self._disallow_partial: bool = kwargs.get("disallow_partial", False)
        self._skip_assembly: bool = kwargs.get("skip_assembly", False)
        self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False)

        self._parsers: List[SlitherCompilationUnitSolc] = []
        try:
            if isinstance(target, CryticCompile):
                crytic_compile = target
            else:
                crytic_compile = CryticCompile(target, **kwargs)
            self._crytic_compile = crytic_compile
        except InvalidCompilation as e:
            # pylint: disable=raise-missing-from
            raise SlitherError(f"Invalid compilation: \n{str(e)}")
        for compilation_unit in crytic_compile.compilation_units.values():
            compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit)
            self._compilation_units.append(compilation_unit_slither)
            parser = SlitherCompilationUnitSolc(compilation_unit_slither)
            self._parsers.append(parser)
            for path, ast in compilation_unit.asts.items():
                parser.parse_top_level_from_loaded_json(ast, path)
                self.add_source_code(path)

            _update_file_scopes(compilation_unit_slither.scopes.values())

        if kwargs.get("generate_patches", False):
            self.generate_patches = True

        self._markdown_root = kwargs.get("markdown_root", "")

        self._detectors = []
        self._printers = []

        filter_paths = kwargs.get("filter_paths", [])
        for p in filter_paths:
            self.add_path_to_filter(p)

        self._exclude_dependencies = kwargs.get("exclude_dependencies", False)

        triage_mode = kwargs.get("triage_mode", False)
        self._triage_mode = triage_mode

        for parser in self._parsers:
            parser.parse_contracts()

        # skip_analyze is only used for testing
        if not kwargs.get("skip_analyze", False):
            for parser in self._parsers:
                parser.analyze_contracts()