slither.slither
1import logging 2from typing import Union, List, Type, Dict, Optional 3 4from crytic_compile import CryticCompile, InvalidCompilation 5 6# pylint: disable= no-name-in-module 7from slither.core.compilation_unit import SlitherCompilationUnit 8from slither.core.slither_core import SlitherCore 9from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification 10from slither.exceptions import SlitherError 11from slither.printers.abstract_printer import AbstractPrinter 12from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc 13from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit 14from slither.utils.output import Output 15from slither.vyper_parsing.ast.ast import parse 16 17logger = logging.getLogger("Slither") 18logging.basicConfig() 19 20logger_detector = logging.getLogger("Detectors") 21logger_printer = logging.getLogger("Printers") 22 23 24def _check_common_things( 25 thing_name: str, cls: Type, base_cls: Type, instances_list: List[Type[AbstractDetector]] 26) -> None: 27 28 if not issubclass(cls, base_cls) or cls is base_cls: 29 raise SlitherError( 30 f"You can't register {cls!r} as a {thing_name}. You need to pass a class that inherits from {base_cls.__name__}" 31 ) 32 33 if any(type(obj) == cls for obj in instances_list): # pylint: disable=unidiomatic-typecheck 34 raise SlitherError(f"You can't register {cls!r} twice.") 35 36 37def _update_file_scopes( 38 sol_parser: SlitherCompilationUnitSolc, 39): # pylint: disable=too-many-branches 40 """ 41 Since all definitions in a file are exported by default, including definitions from its (transitive) dependencies, 42 we can identify all top level items that could possibly be referenced within the file from its exportedSymbols. 43 It is not as straightforward for user defined types and functions as well as aliasing. See add_accessible_scopes for more details. 44 """ 45 candidates = sol_parser.compilation_unit.scopes.values() 46 learned_something = False 47 # Because solc's import allows cycle in the import graph, iterate until we aren't adding new information to the scope. 48 while True: 49 for candidate in candidates: 50 learned_something |= candidate.add_accessible_scopes() 51 if not learned_something: 52 break 53 learned_something = False 54 55 for scope in candidates: 56 for refId in scope.exported_symbols: 57 if refId in sol_parser.contracts_by_id: 58 contract = sol_parser.contracts_by_id[refId] 59 scope.contracts[contract.name] = contract 60 elif refId in sol_parser.functions_by_id: 61 functions = sol_parser.functions_by_id[refId] 62 assert len(functions) == 1 63 scope.functions.add(functions[0]) 64 elif refId in sol_parser.imports_by_id: 65 import_directive = sol_parser.imports_by_id[refId] 66 scope.imports.add(import_directive) 67 elif refId in sol_parser.top_level_variables_by_id: 68 top_level_variable = sol_parser.top_level_variables_by_id[refId] 69 scope.variables[top_level_variable.name] = top_level_variable 70 elif refId in sol_parser.top_level_events_by_id: 71 top_level_event = sol_parser.top_level_events_by_id[refId] 72 scope.events.add(top_level_event) 73 elif refId in sol_parser.top_level_structures_by_id: 74 top_level_struct = sol_parser.top_level_structures_by_id[refId] 75 scope.structures[top_level_struct.name] = top_level_struct 76 elif refId in sol_parser.top_level_type_aliases_by_id: 77 top_level_type_alias = sol_parser.top_level_type_aliases_by_id[refId] 78 scope.type_aliases[top_level_type_alias.name] = top_level_type_alias 79 elif refId in sol_parser.top_level_enums_by_id: 80 top_level_enum = sol_parser.top_level_enums_by_id[refId] 81 scope.enums[top_level_enum.name] = top_level_enum 82 elif refId in sol_parser.top_level_errors_by_id: 83 top_level_custom_error = sol_parser.top_level_errors_by_id[refId] 84 scope.custom_errors.add(top_level_custom_error) 85 else: 86 logger.error( 87 f"Failed to resolved name for reference id {refId} in {scope.filename.absolute}." 88 ) 89 90 91class Slither( 92 SlitherCore 93): # pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,too-many-branches 94 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 95 """ 96 Args: 97 target (str | CryticCompile) 98 Keyword Args: 99 solc (str): solc binary location (default 'solc') 100 disable_solc_warnings (bool): True to disable solc warnings (default false) 101 solc_args (str): solc arguments (default '') 102 ast_format (str): ast format (default '--ast-compact-json') 103 filter_paths (list(str)): list of path to filter (default []) 104 triage_mode (bool): if true, switch to triage mode (default false) 105 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 106 generate_patches (bool): if true, patches are generated (json output only) 107 change_line_prefix (str): Change the line prefix (default #) 108 for the displayed source codes (i.e. file.sol#1). 109 110 """ 111 super().__init__() 112 113 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 114 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 115 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 116 117 self.line_prefix = kwargs.get("change_line_prefix", "#") 118 119 # Indicate if Codex related features should be used 120 self.codex_enabled = kwargs.get("codex", False) 121 self.codex_contracts = kwargs.get("codex_contracts", "all") 122 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 123 self.codex_temperature = kwargs.get("codex_temperature", 0) 124 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 125 self.codex_log = kwargs.get("codex_log", False) 126 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 127 128 self.no_fail = kwargs.get("no_fail", False) 129 130 self._parsers: List[SlitherCompilationUnitSolc] = [] 131 try: 132 if isinstance(target, CryticCompile): 133 crytic_compile = target 134 else: 135 crytic_compile = CryticCompile(target, **kwargs) 136 self._crytic_compile = crytic_compile 137 except InvalidCompilation as e: 138 # pylint: disable=raise-missing-from 139 raise SlitherError(f"Invalid compilation: \n{str(e)}") 140 for compilation_unit in crytic_compile.compilation_units.values(): 141 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 142 self._compilation_units.append(compilation_unit_slither) 143 144 if compilation_unit_slither.is_vyper: 145 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 146 for path, ast in compilation_unit.asts.items(): 147 ast_nodes = parse(ast["ast"]) 148 vyper_parser.parse_module(ast_nodes, path) 149 self._parsers.append(vyper_parser) 150 else: 151 # Solidity specific 152 assert compilation_unit_slither.is_solidity 153 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 154 self._parsers.append(sol_parser) 155 for path, ast in compilation_unit.asts.items(): 156 sol_parser.parse_top_level_items(ast, path) 157 self.add_source_code(path) 158 159 for contract in sol_parser._underlying_contract_to_parser: 160 if contract.name.startswith("SlitherInternalTopLevelContract"): 161 raise SlitherError( 162 # region multi-line-string 163 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 164 Please rename it, this name is reserved for Slither's internals""" 165 # endregion multi-line 166 ) 167 sol_parser._contracts_by_id[contract.id] = contract 168 sol_parser._compilation_unit.contracts.append(contract) 169 170 _update_file_scopes(sol_parser) 171 172 if kwargs.get("generate_patches", False): 173 self.generate_patches = True 174 175 self._markdown_root = kwargs.get("markdown_root", "") 176 177 self._detectors = [] 178 self._printers = [] 179 180 filter_paths = kwargs.get("filter_paths", []) 181 for p in filter_paths: 182 self.add_path_to_filter(p) 183 184 include_paths = kwargs.get("include_paths", []) 185 for p in include_paths: 186 self.add_path_to_include(p) 187 188 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 189 190 triage_mode = kwargs.get("triage_mode", False) 191 triage_database = kwargs.get("triage_database", "slither.db.json") 192 self._triage_mode = triage_mode 193 self._previous_results_filename = triage_database 194 195 printers_to_run = kwargs.get("printers_to_run", "") 196 if printers_to_run == "echidna": 197 self.skip_data_dependency = True 198 199 # Used in inheritance-graph printer 200 self.include_interfaces = kwargs.get("include_interfaces", False) 201 202 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) 203 204 def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: 205 for parser in self._parsers: 206 try: 207 parser.parse_contracts() 208 except Exception as e: 209 if self.no_fail: 210 continue 211 raise e 212 213 # skip_analyze is only used for testing 214 if not skip_analyze: 215 for parser in self._parsers: 216 try: 217 parser.analyze_contracts() 218 except Exception as e: 219 if self.no_fail: 220 continue 221 raise e 222 223 @property 224 def detectors(self): 225 return self._detectors 226 227 @property 228 def detectors_high(self): 229 return [d for d in self.detectors if d.IMPACT == DetectorClassification.HIGH] 230 231 @property 232 def detectors_medium(self): 233 return [d for d in self.detectors if d.IMPACT == DetectorClassification.MEDIUM] 234 235 @property 236 def detectors_low(self): 237 return [d for d in self.detectors if d.IMPACT == DetectorClassification.LOW] 238 239 @property 240 def detectors_informational(self): 241 return [d for d in self.detectors if d.IMPACT == DetectorClassification.INFORMATIONAL] 242 243 @property 244 def detectors_optimization(self): 245 return [d for d in self.detectors if d.IMPACT == DetectorClassification.OPTIMIZATION] 246 247 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 248 """ 249 :param detector_class: Class inheriting from `AbstractDetector`. 250 """ 251 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 252 253 for compilation_unit in self.compilation_units: 254 instance = detector_class(compilation_unit, self, logger_detector) 255 self._detectors.append(instance) 256 257 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 258 """ 259 :param detector_class: Class inheriting from `AbstractDetector`. 260 """ 261 262 for obj in self._detectors: 263 if isinstance(obj, detector_class): 264 self._detectors.remove(obj) 265 return 266 267 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 268 """ 269 :param printer_class: Class inheriting from `AbstractPrinter`. 270 """ 271 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 272 273 instance = printer_class(self, logger_printer) 274 self._printers.append(instance) 275 276 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 277 """ 278 :param printer_class: Class inheriting from `AbstractPrinter`. 279 """ 280 281 for obj in self._printers: 282 if isinstance(obj, printer_class): 283 self._printers.remove(obj) 284 return 285 286 def run_detectors(self) -> List[Dict]: 287 """ 288 :return: List of registered detectors results. 289 """ 290 291 self.load_previous_results() 292 results = [d.detect() for d in self._detectors] 293 294 self.write_results_to_hide() 295 return results 296 297 def run_printers(self) -> List[Output]: 298 """ 299 :return: List of registered printers outputs. 300 """ 301 302 return [p.output(self._crytic_compile.target).data for p in self._printers] 303 304 @property 305 def triage_mode(self) -> bool: 306 return self._triage_mode
92class Slither( 93 SlitherCore 94): # pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,too-many-branches 95 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 96 """ 97 Args: 98 target (str | CryticCompile) 99 Keyword Args: 100 solc (str): solc binary location (default 'solc') 101 disable_solc_warnings (bool): True to disable solc warnings (default false) 102 solc_args (str): solc arguments (default '') 103 ast_format (str): ast format (default '--ast-compact-json') 104 filter_paths (list(str)): list of path to filter (default []) 105 triage_mode (bool): if true, switch to triage mode (default false) 106 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 107 generate_patches (bool): if true, patches are generated (json output only) 108 change_line_prefix (str): Change the line prefix (default #) 109 for the displayed source codes (i.e. file.sol#1). 110 111 """ 112 super().__init__() 113 114 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 115 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 116 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 117 118 self.line_prefix = kwargs.get("change_line_prefix", "#") 119 120 # Indicate if Codex related features should be used 121 self.codex_enabled = kwargs.get("codex", False) 122 self.codex_contracts = kwargs.get("codex_contracts", "all") 123 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 124 self.codex_temperature = kwargs.get("codex_temperature", 0) 125 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 126 self.codex_log = kwargs.get("codex_log", False) 127 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 128 129 self.no_fail = kwargs.get("no_fail", False) 130 131 self._parsers: List[SlitherCompilationUnitSolc] = [] 132 try: 133 if isinstance(target, CryticCompile): 134 crytic_compile = target 135 else: 136 crytic_compile = CryticCompile(target, **kwargs) 137 self._crytic_compile = crytic_compile 138 except InvalidCompilation as e: 139 # pylint: disable=raise-missing-from 140 raise SlitherError(f"Invalid compilation: \n{str(e)}") 141 for compilation_unit in crytic_compile.compilation_units.values(): 142 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 143 self._compilation_units.append(compilation_unit_slither) 144 145 if compilation_unit_slither.is_vyper: 146 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 147 for path, ast in compilation_unit.asts.items(): 148 ast_nodes = parse(ast["ast"]) 149 vyper_parser.parse_module(ast_nodes, path) 150 self._parsers.append(vyper_parser) 151 else: 152 # Solidity specific 153 assert compilation_unit_slither.is_solidity 154 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 155 self._parsers.append(sol_parser) 156 for path, ast in compilation_unit.asts.items(): 157 sol_parser.parse_top_level_items(ast, path) 158 self.add_source_code(path) 159 160 for contract in sol_parser._underlying_contract_to_parser: 161 if contract.name.startswith("SlitherInternalTopLevelContract"): 162 raise SlitherError( 163 # region multi-line-string 164 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 165 Please rename it, this name is reserved for Slither's internals""" 166 # endregion multi-line 167 ) 168 sol_parser._contracts_by_id[contract.id] = contract 169 sol_parser._compilation_unit.contracts.append(contract) 170 171 _update_file_scopes(sol_parser) 172 173 if kwargs.get("generate_patches", False): 174 self.generate_patches = True 175 176 self._markdown_root = kwargs.get("markdown_root", "") 177 178 self._detectors = [] 179 self._printers = [] 180 181 filter_paths = kwargs.get("filter_paths", []) 182 for p in filter_paths: 183 self.add_path_to_filter(p) 184 185 include_paths = kwargs.get("include_paths", []) 186 for p in include_paths: 187 self.add_path_to_include(p) 188 189 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 190 191 triage_mode = kwargs.get("triage_mode", False) 192 triage_database = kwargs.get("triage_database", "slither.db.json") 193 self._triage_mode = triage_mode 194 self._previous_results_filename = triage_database 195 196 printers_to_run = kwargs.get("printers_to_run", "") 197 if printers_to_run == "echidna": 198 self.skip_data_dependency = True 199 200 # Used in inheritance-graph printer 201 self.include_interfaces = kwargs.get("include_interfaces", False) 202 203 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) 204 205 def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: 206 for parser in self._parsers: 207 try: 208 parser.parse_contracts() 209 except Exception as e: 210 if self.no_fail: 211 continue 212 raise e 213 214 # skip_analyze is only used for testing 215 if not skip_analyze: 216 for parser in self._parsers: 217 try: 218 parser.analyze_contracts() 219 except Exception as e: 220 if self.no_fail: 221 continue 222 raise e 223 224 @property 225 def detectors(self): 226 return self._detectors 227 228 @property 229 def detectors_high(self): 230 return [d for d in self.detectors if d.IMPACT == DetectorClassification.HIGH] 231 232 @property 233 def detectors_medium(self): 234 return [d for d in self.detectors if d.IMPACT == DetectorClassification.MEDIUM] 235 236 @property 237 def detectors_low(self): 238 return [d for d in self.detectors if d.IMPACT == DetectorClassification.LOW] 239 240 @property 241 def detectors_informational(self): 242 return [d for d in self.detectors if d.IMPACT == DetectorClassification.INFORMATIONAL] 243 244 @property 245 def detectors_optimization(self): 246 return [d for d in self.detectors if d.IMPACT == DetectorClassification.OPTIMIZATION] 247 248 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 249 """ 250 :param detector_class: Class inheriting from `AbstractDetector`. 251 """ 252 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 253 254 for compilation_unit in self.compilation_units: 255 instance = detector_class(compilation_unit, self, logger_detector) 256 self._detectors.append(instance) 257 258 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 259 """ 260 :param detector_class: Class inheriting from `AbstractDetector`. 261 """ 262 263 for obj in self._detectors: 264 if isinstance(obj, detector_class): 265 self._detectors.remove(obj) 266 return 267 268 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 269 """ 270 :param printer_class: Class inheriting from `AbstractPrinter`. 271 """ 272 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 273 274 instance = printer_class(self, logger_printer) 275 self._printers.append(instance) 276 277 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 278 """ 279 :param printer_class: Class inheriting from `AbstractPrinter`. 280 """ 281 282 for obj in self._printers: 283 if isinstance(obj, printer_class): 284 self._printers.remove(obj) 285 return 286 287 def run_detectors(self) -> List[Dict]: 288 """ 289 :return: List of registered detectors results. 290 """ 291 292 self.load_previous_results() 293 results = [d.detect() for d in self._detectors] 294 295 self.write_results_to_hide() 296 return results 297 298 def run_printers(self) -> List[Output]: 299 """ 300 :return: List of registered printers outputs. 301 """ 302 303 return [p.output(self._crytic_compile.target).data for p in self._printers] 304 305 @property 306 def triage_mode(self) -> bool: 307 return self._triage_mode
Slither static analyzer
95 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 96 """ 97 Args: 98 target (str | CryticCompile) 99 Keyword Args: 100 solc (str): solc binary location (default 'solc') 101 disable_solc_warnings (bool): True to disable solc warnings (default false) 102 solc_args (str): solc arguments (default '') 103 ast_format (str): ast format (default '--ast-compact-json') 104 filter_paths (list(str)): list of path to filter (default []) 105 triage_mode (bool): if true, switch to triage mode (default false) 106 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 107 generate_patches (bool): if true, patches are generated (json output only) 108 change_line_prefix (str): Change the line prefix (default #) 109 for the displayed source codes (i.e. file.sol#1). 110 111 """ 112 super().__init__() 113 114 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 115 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 116 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 117 118 self.line_prefix = kwargs.get("change_line_prefix", "#") 119 120 # Indicate if Codex related features should be used 121 self.codex_enabled = kwargs.get("codex", False) 122 self.codex_contracts = kwargs.get("codex_contracts", "all") 123 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 124 self.codex_temperature = kwargs.get("codex_temperature", 0) 125 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 126 self.codex_log = kwargs.get("codex_log", False) 127 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 128 129 self.no_fail = kwargs.get("no_fail", False) 130 131 self._parsers: List[SlitherCompilationUnitSolc] = [] 132 try: 133 if isinstance(target, CryticCompile): 134 crytic_compile = target 135 else: 136 crytic_compile = CryticCompile(target, **kwargs) 137 self._crytic_compile = crytic_compile 138 except InvalidCompilation as e: 139 # pylint: disable=raise-missing-from 140 raise SlitherError(f"Invalid compilation: \n{str(e)}") 141 for compilation_unit in crytic_compile.compilation_units.values(): 142 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 143 self._compilation_units.append(compilation_unit_slither) 144 145 if compilation_unit_slither.is_vyper: 146 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 147 for path, ast in compilation_unit.asts.items(): 148 ast_nodes = parse(ast["ast"]) 149 vyper_parser.parse_module(ast_nodes, path) 150 self._parsers.append(vyper_parser) 151 else: 152 # Solidity specific 153 assert compilation_unit_slither.is_solidity 154 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 155 self._parsers.append(sol_parser) 156 for path, ast in compilation_unit.asts.items(): 157 sol_parser.parse_top_level_items(ast, path) 158 self.add_source_code(path) 159 160 for contract in sol_parser._underlying_contract_to_parser: 161 if contract.name.startswith("SlitherInternalTopLevelContract"): 162 raise SlitherError( 163 # region multi-line-string 164 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 165 Please rename it, this name is reserved for Slither's internals""" 166 # endregion multi-line 167 ) 168 sol_parser._contracts_by_id[contract.id] = contract 169 sol_parser._compilation_unit.contracts.append(contract) 170 171 _update_file_scopes(sol_parser) 172 173 if kwargs.get("generate_patches", False): 174 self.generate_patches = True 175 176 self._markdown_root = kwargs.get("markdown_root", "") 177 178 self._detectors = [] 179 self._printers = [] 180 181 filter_paths = kwargs.get("filter_paths", []) 182 for p in filter_paths: 183 self.add_path_to_filter(p) 184 185 include_paths = kwargs.get("include_paths", []) 186 for p in include_paths: 187 self.add_path_to_include(p) 188 189 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 190 191 triage_mode = kwargs.get("triage_mode", False) 192 triage_database = kwargs.get("triage_database", "slither.db.json") 193 self._triage_mode = triage_mode 194 self._previous_results_filename = triage_database 195 196 printers_to_run = kwargs.get("printers_to_run", "") 197 if printers_to_run == "echidna": 198 self.skip_data_dependency = True 199 200 # Used in inheritance-graph printer 201 self.include_interfaces = kwargs.get("include_interfaces", False) 202 203 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
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_args (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) change_line_prefix (str): Change the line prefix (default #) for the displayed source codes (i.e. file.sol#1).
248 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 249 """ 250 :param detector_class: Class inheriting from `AbstractDetector`. 251 """ 252 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 253 254 for compilation_unit in self.compilation_units: 255 instance = detector_class(compilation_unit, self, logger_detector) 256 self._detectors.append(instance)
Parameters
- detector_class: Class inheriting from
AbstractDetector
.
258 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 259 """ 260 :param detector_class: Class inheriting from `AbstractDetector`. 261 """ 262 263 for obj in self._detectors: 264 if isinstance(obj, detector_class): 265 self._detectors.remove(obj) 266 return
Parameters
- detector_class: Class inheriting from
AbstractDetector
.
268 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 269 """ 270 :param printer_class: Class inheriting from `AbstractPrinter`. 271 """ 272 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 273 274 instance = printer_class(self, logger_printer) 275 self._printers.append(instance)
Parameters
- printer_class: Class inheriting from
AbstractPrinter
.
277 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 278 """ 279 :param printer_class: Class inheriting from `AbstractPrinter`. 280 """ 281 282 for obj in self._printers: 283 if isinstance(obj, printer_class): 284 self._printers.remove(obj) 285 return
Parameters
- printer_class: Class inheriting from
AbstractPrinter
.
287 def run_detectors(self) -> List[Dict]: 288 """ 289 :return: List of registered detectors results. 290 """ 291 292 self.load_previous_results() 293 results = [d.detect() for d in self._detectors] 294 295 self.write_results_to_hide() 296 return results
Returns
List of registered detectors results.
298 def run_printers(self) -> List[Output]: 299 """ 300 :return: List of registered printers outputs. 301 """ 302 303 return [p.output(self._crytic_compile.target).data for p in self._printers]
Returns
List of registered printers outputs.
Inherited Members
- slither.core.slither_core.SlitherCore
- sarif_input
- sarif_triage
- skip_data_dependency
- compilation_units
- add_compilation_unit
- contracts
- contracts_derived
- get_contract_from_name
- source_code
- filename
- add_source_code
- markdown_root
- print_functions
- offset_to_objects
- offset_to_references
- offset_to_implementations
- offset_to_definitions
- parse_ignore_comments
- has_ignore_comment
- valid_result
- load_previous_results
- load_previous_results_from_sarif
- write_results_to_hide
- save_results_to_hide
- add_path_to_filter
- add_path_to_include
- crytic_compile
- generate_patches
- disallow_partial
- skip_assembly
- show_ignore_findings