From 0b20aca729fdb372d2055f5e0d33163b74110a1e Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 31 Jan 2023 17:53:35 -0600 Subject: [PATCH 01/44] fix compilation unit missing in source API --- slither/core/source_mapping/source_mapping.py | 36 ++++++++----------- slither/printers/summary/declaration.py | 28 +++++++-------- slither/utils/source_mapping.py | 5 ++- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index ee5211c7c..2a1266e22 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: # pylint: disable=too-many-instance-attributes class Source: - def __init__(self) -> None: + def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None: self.start: int = 0 self.length: int = 0 self.filename: Filename = Filename("", "", "", "") @@ -27,7 +27,7 @@ class Source: self.starting_column: int = 0 self.ending_column: int = 0 self.end: int = 0 - self.compilation_unit: Optional["SlitherCompilationUnit"] = None + self.compilation_unit = compilation_unit def to_json(self) -> Dict: return { @@ -51,17 +51,16 @@ class Source: filename_relative: str = self.filename.relative if self.filename.relative else "" return f"{markdown_root}{filename_relative}{lines}" - def to_detailled_str(self) -> str: + def to_detailed_str(self) -> str: lines = self._get_lines_str() filename_short: str = self.filename.short if self.filename.short else "" return f"{filename_short}{lines} ({self.starting_column} - {self.ending_column})" - def _get_lines_str(self, line_descr=""): - - # If the compilation unit was not initialized, it means that the set_offset was never called - # on the corresponding object, which should not happen - assert self.compilation_unit is not None + def span(self) -> str: + with open (self.filename.absolute, "r") as f: + return f.readlines()[self.start:self.end] + def _get_lines_str(self, line_descr=""): line_prefix = self.compilation_unit.core.line_prefix lines = self.lines @@ -105,6 +104,7 @@ def _compute_line( Not done in an efficient way """ + start_line, starting_column = compilation_unit.core.crytic_compile.get_line_from_offset( filename, start ) @@ -127,7 +127,7 @@ def _convert_source_mapping( position = re.findall("([0-9]*):([0-9]*):([-]?[0-9]*)", offset) if len(position) != 1: - return Source() + return Source(compilation_unit) s, l, f = position[0] s = int(s) @@ -135,7 +135,7 @@ def _convert_source_mapping( f = int(f) if f not in sourceUnits: - new_source = Source() + new_source = Source(compilation_unit) new_source.start = s new_source.length = l return new_source @@ -149,7 +149,7 @@ def _convert_source_mapping( (lines, starting_column, ending_column) = _compute_line(compilation_unit, filename, s, l) - new_source = Source() + new_source = Source(compilation_unit) new_source.start = s new_source.length = l new_source.filename = filename @@ -158,28 +158,22 @@ def _convert_source_mapping( new_source.starting_column = starting_column new_source.ending_column = ending_column new_source.end = new_source.start + l + return new_source class SourceMapping(Context, metaclass=ABCMeta): def __init__(self) -> None: super().__init__() - # self._source_mapping: Optional[Dict] = None - self.source_mapping: Source = Source() + self.source_mapping: Optional[Source] = None self.references: List[Source] = [] def set_offset( self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit" ) -> None: + assert compilation_unit if isinstance(offset, Source): - self.source_mapping.start = offset.start - self.source_mapping.length = offset.length - self.source_mapping.filename = offset.filename - self.source_mapping.is_dependency = offset.is_dependency - self.source_mapping.lines = offset.lines - self.source_mapping.starting_column = offset.starting_column - self.source_mapping.ending_column = offset.ending_column - self.source_mapping.end = offset.end + self.source_mapping = offset else: self.source_mapping = _convert_source_mapping(offset, compilation_unit) self.source_mapping.compilation_unit = compilation_unit diff --git a/slither/printers/summary/declaration.py b/slither/printers/summary/declaration.py index 5888a1f00..529aba5f0 100644 --- a/slither/printers/summary/declaration.py +++ b/slither/printers/summary/declaration.py @@ -20,37 +20,37 @@ class Declaration(AbstractPrinter): txt += "\n# Contracts\n" for contract in compilation_unit.contracts: txt += f"# {contract.name}\n" - txt += f"\t- Declaration: {get_definition(contract, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t- Implementation: {get_implementation(contract).to_detailled_str()}\n" + txt += f"\t- Declaration: {get_definition(contract, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t- Implementation: {get_implementation(contract).to_detailed_str()}\n" txt += ( - f"\t- References: {[x.to_detailled_str() for x in get_references(contract)]}\n" + f"\t- References: {[x.to_detailed_str() for x in get_references(contract)]}\n" ) txt += "\n\t## Function\n" for func in contract.functions: txt += f"\t\t- {func.canonical_name}\n" - txt += f"\t\t\t- Declaration: {get_definition(func, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += ( - f"\t\t\t- Implementation: {get_implementation(func).to_detailled_str()}\n" - ) - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(func)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(func, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t\t\t- Implementation: {get_implementation(func).to_detailed_str()}\n" + txt += f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(func)]}\n" txt += "\n\t## State variables\n" for var in contract.state_variables: txt += f"\t\t- {var.name}\n" - txt += f"\t\t\t- Declaration: {get_definition(var, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t\t\t- Implementation: {get_implementation(var).to_detailled_str()}\n" - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(var)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(var, compilation_unit.core.crytic_compile).to_detailed_str()}\n" + txt += f"\t\t\t- Implementation: {get_implementation(var).to_detailed_str()}\n" + txt += f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(var)]}\n" txt += "\n\t## Structures\n" for st in contract.structures: txt += f"\t\t- {st.name}\n" - txt += f"\t\t\t- Declaration: {get_definition(st, compilation_unit.core.crytic_compile).to_detailled_str()}\n" - txt += f"\t\t\t- Implementation: {get_implementation(st).to_detailled_str()}\n" - txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(st)]}\n" + txt += f"\t\t\t- Declaration: {get_definition(st, compilation_unit.core.crytic_compile).txt}\n" + txt += f"\t\t\t- Implementation: {get_implementation(st).to_detailed_str()}\n" + txt += ( + f"\t\t\t- References: {[x.to_detailed_str() for x in get_references(st)]}\n" + ) self.info(txt) res = self.generate_output(txt) diff --git a/slither/utils/source_mapping.py b/slither/utils/source_mapping.py index 26ad7c0d2..b117cd5f7 100644 --- a/slither/utils/source_mapping.py +++ b/slither/utils/source_mapping.py @@ -35,7 +35,7 @@ def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Sour target.source_mapping.filename, target.source_mapping.start + start_offset + len(pattern) ) - s = Source() + s = Source(target.source_mapping.compilation_unit) s.start = target.source_mapping.start + start_offset s.length = len(pattern) s.filename = target.source_mapping.filename @@ -44,8 +44,7 @@ def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Sour s.starting_column = starting_column s.ending_column = ending_column s.end = s.start + s.length - s.compilation_unit = target.compilation_unit - + s.txt = txt return s From 715826e12099db2a9715388292eaeb625a1b9c4a Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Fri, 3 Mar 2023 14:15:10 +0530 Subject: [PATCH 02/44] Update reentrancy_eth.py msg.sender --- slither/detectors/reentrancy/reentrancy_eth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/reentrancy/reentrancy_eth.py b/slither/detectors/reentrancy/reentrancy_eth.py index 73622cf54..ccb668837 100644 --- a/slither/detectors/reentrancy/reentrancy_eth.py +++ b/slither/detectors/reentrancy/reentrancy_eth.py @@ -38,7 +38,7 @@ Do not report reentrancies that don't involve Ether (see `reentrancy-no-eth`)""" ```solidity function withdrawBalance(){ // send userBalance[msg.sender] Ether to msg.sender - // if mgs.sender is a contract, it will call its fallback function + // if msg.sender is a contract, it will call its fallback function if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){ throw; } From a42c2cc0d1b8a4e4b34e55fb9166fe1cb3a48a15 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Wed, 8 Mar 2023 15:49:23 +0530 Subject: [PATCH 03/44] deregister_detector This function would be helpful to de-register a detector class from the list of detectors already registered with the slither object --- slither/slither.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/slither/slither.py b/slither/slither.py index 3e44944b3..1be371902 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -187,6 +187,15 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes for compilation_unit in self.compilation_units: instance = detector_class(compilation_unit, self, logger_detector) self._detectors.append(instance) + + def deregister_detector(self, detector_class: Type[AbstractDetector]) -> None: + """ + :param detector_class: Class inheriting from `AbstractDetector`. + """ + + for obj in self._detectors: + if type(obj) == detector_class : + self._detectors.remove(obj) def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: """ From 4e2f1ac3cc9858ebc1fbeaa538881a055acc64ec Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Wed, 8 Mar 2023 16:03:45 +0530 Subject: [PATCH 04/44] deregister_printer This function would be helpful to de-register a printer class from the list of _printers already registered with the slither object. --- slither/slither.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 3e44944b3..ef995adce 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -196,7 +196,17 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = printer_class(self, logger_printer) self._printers.append(instance) - + + def deregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: + """ + :param printer_class: Class inheriting from `AbstractPrinter`. + """ + + for obj in self._printers: + if type(obj) == printer_class : + self._printers.remove(obj) + return + def run_detectors(self) -> List[Dict]: """ :return: List of registered detectors results. From 611798c634ad078d9aec5b16fdb66acb081fb075 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Wed, 8 Mar 2023 16:10:57 +0530 Subject: [PATCH 05/44] update deregister_detector() return on removing the first hit itself, as there can't be multiple objects of the same detector class in the _detectors. --- slither/slither.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/slither.py b/slither/slither.py index 1be371902..98e173c20 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -196,6 +196,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes for obj in self._detectors: if type(obj) == detector_class : self._detectors.remove(obj) + return def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: """ From 181ee42e71e6d67d8c3d60b8560e06b8ad604325 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Wed, 8 Mar 2023 16:21:10 +0530 Subject: [PATCH 06/44] pylint: disable unidiomatic-typecheck --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index ef995adce..5453c186d 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -203,7 +203,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes """ for obj in self._printers: - if type(obj) == printer_class : + if type(obj) == printer_class : # pylint: disable=unidiomatic-typecheck self._printers.remove(obj) return From 646fb1e80c4f6b65c289a8a7af71fc3490f82fe7 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Wed, 8 Mar 2023 16:23:12 +0530 Subject: [PATCH 07/44] pylint: disable unidiomatic-typecheck --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 98e173c20..2fc078905 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -194,7 +194,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes """ for obj in self._detectors: - if type(obj) == detector_class : + if type(obj) == detector_class : # pylint: disable=unidiomatic-typecheck self._detectors.remove(obj) return From e48351339c120f7e339ef5cc9e79d3314140aab0 Mon Sep 17 00:00:00 2001 From: sidarth16 Date: Thu, 9 Mar 2023 12:01:49 +0530 Subject: [PATCH 08/44] black --- slither/slither.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/slither.py b/slither/slither.py index 5453c186d..eebec65aa 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -196,17 +196,17 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = printer_class(self, logger_printer) self._printers.append(instance) - + def deregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: """ :param printer_class: Class inheriting from `AbstractPrinter`. """ - + for obj in self._printers: - if type(obj) == printer_class : # pylint: disable=unidiomatic-typecheck + if type(obj) == printer_class: # pylint: disable=unidiomatic-typecheck self._printers.remove(obj) return - + def run_detectors(self) -> List[Dict]: """ :return: List of registered detectors results. From d5a84364b953d199b3dd2de178b9b0a43764865b Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Thu, 9 Mar 2023 12:06:13 +0530 Subject: [PATCH 09/44] black --- slither/slither.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/slither.py b/slither/slither.py index 2fc078905..2737450b6 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -187,14 +187,14 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes for compilation_unit in self.compilation_units: instance = detector_class(compilation_unit, self, logger_detector) self._detectors.append(instance) - + def deregister_detector(self, detector_class: Type[AbstractDetector]) -> None: """ :param detector_class: Class inheriting from `AbstractDetector`. """ for obj in self._detectors: - if type(obj) == detector_class : # pylint: disable=unidiomatic-typecheck + if type(obj) == detector_class: # pylint: disable=unidiomatic-typecheck self._detectors.remove(obj) return From 76d8321401a9a30a635359d9affbd64f69b524d3 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 9 Mar 2023 14:07:21 +0100 Subject: [PATCH 10/44] Improve parsing of contract's comment --- slither/core/declarations/contract.py | 27 +++++++++++++++++++ slither/solc_parsing/declarations/contract.py | 27 +++++++++++++++++-- tests/custom_comments/contract_comment.sol | 7 +++++ tests/test_features.py | 24 ++++++++++++++++- 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 tests/custom_comments/contract_comment.sol diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 2d2d10b04..95b05aa6b 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -110,6 +110,8 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods Dict["StateVariable", Set[Union["StateVariable", "Function"]]] ] = None + self._comments: Optional[str] = None + ################################################################################### ################################################################################### # region General's properties @@ -165,6 +167,31 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods def is_library(self, is_library: bool): self._is_library = is_library + @property + def comments(self) -> Optional[str]: + """ + Return the comments associated with the contract. + + When using comments, avoid strict text matching, as the solc behavior might change. + For example, for old solc version, the first space after the * is not kept, i.e: + + * @title Test Contract + * @dev Test comment + + Returns + - " @title Test Contract\n @dev Test comment" for newest versions + - "@title Test Contract\n@dev Test comment" for older versions + + + Returns: + the comment as a string + """ + return self._comments + + @comments.setter + def comments(self, comments: str): + self._comments = comments + # endregion ################################################################################### ################################################################################### diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 475c3fab2..e63dbe68f 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -780,12 +780,35 @@ class ContractSolc(CallerContextExpression): self._customErrorParsed = [] def _handle_comment(self, attributes: Dict) -> None: + """ + Save the contract comment in self.comments + And handle custom slither comments + + Args: + attributes: + + Returns: + + """ + # Old solc versions store the comment in attributes["documentation"] + # More recent ones store it in attributes["documentation"]["text"] if ( "documentation" in attributes and attributes["documentation"] is not None - and "text" in attributes["documentation"] + and ( + "text" in attributes["documentation"] + or isinstance(attributes["documentation"], str) + ) ): - candidates = attributes["documentation"]["text"].replace("\n", ",").split(",") + text = ( + attributes["documentation"] + if isinstance(attributes["documentation"], str) + else attributes["documentation"]["text"] + ) + self._contract.comments = text + + # Look for custom comments + candidates = text.replace("\n", ",").split(",") for candidate in candidates: if "@custom:security isDelegatecallProxy" in candidate: diff --git a/tests/custom_comments/contract_comment.sol b/tests/custom_comments/contract_comment.sol new file mode 100644 index 000000000..8f0fb5233 --- /dev/null +++ b/tests/custom_comments/contract_comment.sol @@ -0,0 +1,7 @@ +/** + * @title Test Contract + * @dev Test comment + */ +contract A{ + +} \ No newline at end of file diff --git a/tests/test_features.py b/tests/test_features.py index d29a5eb6a..b42b60616 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -31,7 +31,7 @@ def test_node() -> None: def test_collision() -> None: - + solc_select.switch_global_version("0.8.0", always_install=True) standard_json = SolcStandardJson() standard_json.add_source_file("./tests/collisions/a.sol") standard_json.add_source_file("./tests/collisions/b.sol") @@ -43,6 +43,7 @@ def test_collision() -> None: def test_cycle() -> None: + solc_select.switch_global_version("0.8.0", always_install=True) slither = Slither("./tests/test_cyclic_import/a.sol") _run_all_detectors(slither) @@ -74,6 +75,27 @@ def test_upgradeable_comments() -> None: assert v1.upgradeable_version == "version_1" +def test_contract_comments() -> None: + comments = " @title Test Contract\n @dev Test comment" + + solc_select.switch_global_version("0.8.10", always_install=True) + slither = Slither("./tests/custom_comments/contract_comment.sol") + compilation_unit = slither.compilation_units[0] + contract = compilation_unit.get_contract_from_name("A")[0] + + assert contract.comments == comments + + # Old solc versions have a different parsing of comments + # the initial space (after *) is also not kept on every line + comments = "@title Test Contract\n@dev Test comment" + solc_select.switch_global_version("0.5.16", always_install=True) + slither = Slither("./tests/custom_comments/contract_comment.sol") + compilation_unit = slither.compilation_units[0] + contract = compilation_unit.get_contract_from_name("A")[0] + + assert contract.comments == comments + + def test_using_for_top_level_same_name() -> None: solc_select.switch_global_version("0.8.15", always_install=True) slither = Slither("./tests/ast-parsing/using-for-3-0.8.0.sol") From 3850cf57e3e24bab2a9850463f24de51ed5a9823 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Thu, 9 Mar 2023 20:30:02 +0530 Subject: [PATCH 11/44] renaming to unregister_detector() Co-authored-by: alpharush <0xalpharush@protonmail.com> --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 2737450b6..6268c5505 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -188,7 +188,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = detector_class(compilation_unit, self, logger_detector) self._detectors.append(instance) - def deregister_detector(self, detector_class: Type[AbstractDetector]) -> None: + def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: """ :param detector_class: Class inheriting from `AbstractDetector`. """ From a9d399ff0219daf395253934a5958067b9a2f988 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 9 Mar 2023 21:22:18 +0100 Subject: [PATCH 12/44] Update README.md --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2dc6d3da1..2939d3de6 100644 --- a/README.md +++ b/README.md @@ -250,17 +250,19 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt - [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19 ### External publications -Title | Usage | Authors | Venue ---- | --- | --- | --- +Title | Usage | Authors | Venue | Code +--- | --- | --- | --- | --- [ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method) | AST-based analysis built on top of Slither | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 -[MPro: Combining Static and Symbolic Analysis forScalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf) | Leverage data dependency through Slither | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 +[MPro: Combining Static and Symbolic Analysis forScalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf) | Leverage data dependency through Slither | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 | [MPro](https://github.com/QuanZhang-William/M-Pro) [ETHPLOIT: From Fuzzing to Efficient Exploit Generation against Smart Contracts](https://wcventure.github.io/FuzzingPaper/Paper/SANER20_ETHPLOIT.pdf) | Leverage data dependency through Slither | Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma | SANER 20 [Verification of Ethereum Smart Contracts: A Model Checking Approach](http://www.ijmlc.org/vol10/977-AM0059.pdf) | Symbolic execution built on top of Slither’s CFG | Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan | IJMLC 20 -[Smart Contract Repair](https://arxiv.org/pdf/1912.05823.pdf) | Rely on Slither’s vulnerabilities detectors | Xiao Liang Yu, Omar Al-Bataineh, David Lo, Abhik Roychoudhury | TOSEM 20 +[Smart Contract Repair](https://arxiv.org/pdf/1912.05823.pdf) | Rely on Slither’s vulnerabilities detectors | Xiao Liang Yu, Omar Al-Bataineh, David Lo, Abhik Roychoudhury | TOSEM 20 | [SCRepair](https://github.com/xiaoly8/SCRepair/) [Demystifying Loops in Smart Contracts](https://www.microsoft.com/en-us/research/uploads/prod/2020/08/loops_solidity__camera_ready-5f3fec3f15c69.pdf) | Leverage data dependency through Slither | Ben Mariano, Yanju Chen, Yu Feng, Shuvendu Lahiri, Isil Dillig | ASE 20 [Trace-Based Dynamic Gas Estimation of Loops in Smart Contracts](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9268144) | Use Slither’s CFG to detect loops | Chunmiao Li, Shijie Nie, Yang Cao, Yijun Yu, Zhenjiang Hu | IEEE Open J. Comput. Soc. 1 (2020) -[SAILFISH: Vetting Smart Contract State-Inconsistency Bugs in Seconds](https://arxiv.org/pdf/2104.08638.pdf) | Rely on SlithIR to build a *storage dependency graph* | Priyanka Bose, Dipanjan Das, Yanju Chen, Yu Feng, Christopher Kruegel, and Giovanni Vigna | S&P 22 +[SAILFISH: Vetting Smart Contract State-Inconsistency Bugs in Seconds](https://arxiv.org/pdf/2104.08638.pdf) | Rely on SlithIR to build a *storage dependency graph* | Priyanka Bose, Dipanjan Das, Yanju Chen, Yu Feng, Christopher Kruegel, and Giovanni Vigna | S&P 22 | [Sailfish](https://github.com/ucsb-seclab/sailfish) [SolType: Refinement Types for Arithmetic Overflow in Solidity](https://arxiv.org/abs/2110.00677) | Use Slither as frontend to build refinement type system | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 [Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) +[MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) +[Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From 3691be0e02913f30ff2cf5ce57a741f404c7940f Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 9 Mar 2023 21:23:46 +0100 Subject: [PATCH 13/44] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2939d3de6..32e57ca61 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,6 @@ Title | Usage | Authors | Venue | Code [SolType: Refinement Types for Arithmetic Overflow in Solidity](https://arxiv.org/abs/2110.00677) | Use Slither as frontend to build refinement type system | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 [Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) -[Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) +[Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From 275be58a55dae59a936d2d7a33bf0a85d6900fc4 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:54:35 +0530 Subject: [PATCH 14/44] isinstance() --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 6268c5505..6f1bf61cd 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -194,7 +194,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes """ for obj in self._detectors: - if type(obj) == detector_class: # pylint: disable=unidiomatic-typecheck + if isinstance(obj, detector_class): self._detectors.remove(obj) return From 9b69da1cc84d2f51a33656414251dd521de6ba01 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:59:01 +0530 Subject: [PATCH 15/44] isinstance() --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index eebec65aa..795f8794b 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -203,7 +203,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes """ for obj in self._printers: - if type(obj) == printer_class: # pylint: disable=unidiomatic-typecheck + if isinstance(obj, printer_class): self._printers.remove(obj) return From 660ccb9751588f143f613bbe17ef4070d5a77d33 Mon Sep 17 00:00:00 2001 From: "S.Sidarth" <38394431+sidarth16@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:59:40 +0530 Subject: [PATCH 16/44] rename to unregister_printer() --- slither/slither.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 795f8794b..42f0346be 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -197,7 +197,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = printer_class(self, logger_printer) self._printers.append(instance) - def deregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: + def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: """ :param printer_class: Class inheriting from `AbstractPrinter`. """ From 7aba140c3d1d1014c9d91526aba515844a5e0065 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 10 Mar 2023 15:38:07 +0100 Subject: [PATCH 17/44] Test with legacy AST too --- tests/test_features.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_features.py b/tests/test_features.py index b42b60616..7c2db8a3e 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -95,6 +95,15 @@ def test_contract_comments() -> None: assert contract.comments == comments + # Test with legacy AST + comments = "@title Test Contract\n@dev Test comment" + solc_select.switch_global_version("0.5.16", always_install=True) + slither = Slither("./tests/custom_comments/contract_comment.sol", solc_force_legacy_json=True) + compilation_unit = slither.compilation_units[0] + contract = compilation_unit.get_contract_from_name("A")[0] + + assert contract.comments == comments + def test_using_for_top_level_same_name() -> None: solc_select.switch_global_version("0.8.15", always_install=True) From 12682c3094d3721466d34e45748a82b5c3bcce6b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 10 Mar 2023 09:34:58 -0600 Subject: [PATCH 18/44] make slither-read-storage dependencies explicit --- .github/workflows/read_storage.yml | 3 +-- setup.py | 3 ++- slither/tools/read_storage/read_storage.py | 31 ++++++++++------------ tests/test_read_storage.py | 13 ++++----- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/.github/workflows/read_storage.yml b/.github/workflows/read_storage.yml index 638a5c38c..85e399006 100644 --- a/.github/workflows/read_storage.yml +++ b/.github/workflows/read_storage.yml @@ -39,8 +39,7 @@ jobs: - name: Install python dependencies run: | - pip install ".[dev]" - pip install web3 + pip install ".[slither-read-storage]" solc-select install 0.8.1 solc-select install 0.8.10 solc-select use 0.8.1 diff --git a/setup.py b/setup.py index 3d2fa2a35..8e20af1f4 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,8 @@ setup( "solc-select>=v1.0.0b1", "openai", "pdoc", - ] + ], + "slither-read-storage": ["solc-select>=v1.0.0b1", "web3>=6.0.0b"], }, license="AGPL-3.0", long_description=long_description, diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index bb662c4d5..f6789bde1 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -3,20 +3,17 @@ import sys from math import floor from typing import Callable, Optional, Tuple, Union, List, Dict, Any -try: - from web3 import Web3 - from eth_typing.evm import ChecksumAddress - from eth_abi import decode_single, encode_abi - from eth_utils import keccak - from .utils import ( - get_offset_value, - get_storage_data, - coerce_type, - ) -except ImportError: - print("ERROR: in order to use slither-read-storage, you need to install web3") - print("$ pip3 install web3 --user\n") - sys.exit(-1) + +from web3 import Web3 +from eth_typing.evm import ChecksumAddress +from eth_abi import decode, encode +from eth_utils import keccak +from .utils import ( + get_offset_value, + get_storage_data, + coerce_type, +) + import dataclasses from slither.utils.myprettytable import MyPrettyTable @@ -92,7 +89,7 @@ class SlitherReadStorage: if not self.storage_address: raise ValueError if not self._checksum_address: - self._checksum_address = self.web3.toChecksumAddress(self.storage_address) + self._checksum_address = self.web3.to_checksum_address(self.storage_address) return self._checksum_address @property @@ -449,7 +446,7 @@ class SlitherReadStorage: if "int" in key_type: # without this eth_utils encoding fails key = int(key) key = coerce_type(key_type, key) - slot = keccak(encode_abi([key_type, "uint256"], [key, decode_single("uint256", slot)])) + slot = keccak(encode([key_type, "uint256"], [key, decode("uint256", slot)])) if isinstance(target_variable_type.type_to, UserDefinedType) and isinstance( target_variable_type.type_to.type, Structure @@ -471,7 +468,7 @@ class SlitherReadStorage: deep_key = int(deep_key) # If deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))) - slot = keccak(encode_abi([key_type, "bytes32"], [deep_key, slot])) + slot = keccak(encode([key_type, "bytes32"], [deep_key, slot])) # mapping(elem => mapping(elem => elem)) target_variable_type_type_to_type_to = target_variable_type.type_to.type_to diff --git a/tests/test_read_storage.py b/tests/test_read_storage.py index 67a89dae8..72e514e18 100644 --- a/tests/test_read_storage.py +++ b/tests/test_read_storage.py @@ -12,13 +12,10 @@ from deepdiff import DeepDiff from slither import Slither from slither.tools.read_storage import SlitherReadStorage -try: - from web3 import Web3 - from web3.contract import Contract -except ImportError: - print("ERROR: in order to use slither-read-storage, you need to install web3") - print("$ pip3 install web3 --user\n") - sys.exit(-1) + +from web3 import Web3 +from web3.contract import Contract + SLITHER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STORAGE_TEST_ROOT = os.path.join(SLITHER_ROOT, "tests", "storage-layout") @@ -98,7 +95,7 @@ def deploy_contract(w3, ganache, contract_bin, contract_abi) -> Contract: # pylint: disable=too-many-locals @pytest.mark.usefixtures("web3", "ganache") def test_read_storage(web3, ganache) -> None: - assert web3.isConnected() + assert web3.is_connected() bin_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.bin") abi_path = os.path.join(STORAGE_TEST_ROOT, "StorageLayout.abi") bytecode = get_source_file(bin_path) From 3861029145cf2b947f4918e8d6ba233b9ed3555a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 10 Mar 2023 09:53:14 -0600 Subject: [PATCH 19/44] inspect whether package is installed --- .github/workflows/read_storage.yml | 2 +- setup.py | 2 +- slither/tools/read_storage/read_storage.py | 30 +++++++++++--------- slither/tools/read_storage/utils/__init__.py | 6 +--- slither/tools/read_storage/utils/utils.py | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/read_storage.yml b/.github/workflows/read_storage.yml index 85e399006..6822d1034 100644 --- a/.github/workflows/read_storage.yml +++ b/.github/workflows/read_storage.yml @@ -39,7 +39,7 @@ jobs: - name: Install python dependencies run: | - pip install ".[slither-read-storage]" + pip install ".[read-storage]" solc-select install 0.8.1 solc-select install 0.8.10 solc-select use 0.8.1 diff --git a/setup.py b/setup.py index 8e20af1f4..2123f482b 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ setup( "openai", "pdoc", ], - "slither-read-storage": ["solc-select>=v1.0.0b1", "web3>=6.0.0b"], + "read-storage": ["solc-select>=v1.0.0b1", "web3>=6.0.0b"], }, license="AGPL-3.0", long_description=long_description, diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index f6789bde1..8bf83db02 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -1,27 +1,31 @@ +import importlib.util import logging import sys from math import floor -from typing import Callable, Optional, Tuple, Union, List, Dict, Any +from typing import Any, Callable, Dict, List, Optional, Tuple, Union +if importlib.util.find_spec("web3").loader is None: + print( + "Please install slither with `pip install slither-analyzer[read-storage]` to use slither-read-storage." + ) + sys.exit(-1) + +import dataclasses -from web3 import Web3 -from eth_typing.evm import ChecksumAddress from eth_abi import decode, encode +from eth_typing.evm import ChecksumAddress from eth_utils import keccak -from .utils import ( - get_offset_value, - get_storage_data, - coerce_type, -) - +from web3 import Web3 -import dataclasses -from slither.utils.myprettytable import MyPrettyTable -from slither.core.solidity_types.type import Type -from slither.core.solidity_types import ArrayType, ElementaryType, UserDefinedType, MappingType from slither.core.declarations import Contract, Structure +from slither.core.solidity_types import (ArrayType, ElementaryType, + MappingType, UserDefinedType) +from slither.core.solidity_types.type import Type from slither.core.variables.state_variable import StateVariable from slither.core.variables.structure_variable import StructureVariable +from slither.utils.myprettytable import MyPrettyTable + +from .utils import coerce_type, get_offset_value, get_storage_data logging.basicConfig() logger = logging.getLogger("Slither-read-storage") diff --git a/slither/tools/read_storage/utils/__init__.py b/slither/tools/read_storage/utils/__init__.py index 2fb43c8b8..9a624a4c7 100644 --- a/slither/tools/read_storage/utils/__init__.py +++ b/slither/tools/read_storage/utils/__init__.py @@ -1,5 +1 @@ -from .utils import ( - get_offset_value, - get_storage_data, - coerce_type, -) +from .utils import coerce_type, get_offset_value, get_storage_data diff --git a/slither/tools/read_storage/utils/utils.py b/slither/tools/read_storage/utils/utils.py index 3e51e2181..befd3d0e7 100644 --- a/slither/tools/read_storage/utils/utils.py +++ b/slither/tools/read_storage/utils/utils.py @@ -1,7 +1,7 @@ from typing import Union from eth_typing.evm import ChecksumAddress -from eth_utils import to_int, to_text, to_checksum_address +from eth_utils import to_checksum_address, to_int, to_text def get_offset_value(hex_bytes: bytes, offset: int, size: int) -> bytes: From d9fda0b85cc05ff97e164df9fccc2c3cdbb68de5 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 10 Mar 2023 10:01:30 -0600 Subject: [PATCH 20/44] make dev install read-storage deps --- .github/workflows/read_storage.yml | 2 +- setup.py | 2 +- tests/test_read_storage.py | 11 ++++------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/read_storage.yml b/.github/workflows/read_storage.yml index 6822d1034..b9ff687ff 100644 --- a/.github/workflows/read_storage.yml +++ b/.github/workflows/read_storage.yml @@ -39,7 +39,7 @@ jobs: - name: Install python dependencies run: | - pip install ".[read-storage]" + pip install ".[dev]" solc-select install 0.8.1 solc-select install 0.8.10 solc-select use 0.8.1 diff --git a/setup.py b/setup.py index 2123f482b..1ffee1589 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ setup( "pytest-xdist", "deepdiff", "numpy", - "solc-select>=v1.0.0b1", + "slither-analyzer[read-storage]", "openai", "pdoc", ], diff --git a/tests/test_read_storage.py b/tests/test_read_storage.py index 72e514e18..7aec6ff40 100644 --- a/tests/test_read_storage.py +++ b/tests/test_read_storage.py @@ -1,7 +1,6 @@ -import re -import os -import sys import json +import os +import re import shutil import subprocess from time import sleep @@ -9,13 +8,11 @@ from typing import Generator import pytest from deepdiff import DeepDiff -from slither import Slither -from slither.tools.read_storage import SlitherReadStorage - - from web3 import Web3 from web3.contract import Contract +from slither import Slither +from slither.tools.read_storage import SlitherReadStorage SLITHER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STORAGE_TEST_ROOT = os.path.join(SLITHER_ROOT, "tests", "storage-layout") From 6236e54b3e344f3d29bb8be8955fc83759c25652 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 10 Mar 2023 22:47:33 +0100 Subject: [PATCH 21/44] Improve top level functions format --- slither/printers/summary/slithir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/summary/slithir.py b/slither/printers/summary/slithir.py index 6f64d7624..be9ebc8f5 100644 --- a/slither/printers/summary/slithir.py +++ b/slither/printers/summary/slithir.py @@ -46,7 +46,7 @@ class PrinterSlithIR(AbstractPrinter): txt += f"\tModifier {modifier.canonical_name}\n" txt += _print_function(modifier) if compilation_unit.functions_top_level: - txt += "Top level functions" + txt += "Top level functions\n" for function in compilation_unit.functions_top_level: txt += f"\tFunction {function.canonical_name}\n" txt += _print_function(function) From f67c96b827b334ab20b585abb6464d5ad29b7233 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sun, 12 Mar 2023 23:06:26 -0500 Subject: [PATCH 22/44] update filter-paths help --- slither/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/__main__.py b/slither/__main__.py index 385dc608f..5d0dda9e0 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -514,7 +514,7 @@ def parse_args( group_misc.add_argument( "--filter-paths", - help="Comma-separated list of paths for which results will be excluded", + help="Regex filter to exclude detector results matching file path e.g. (mocks/|test/)", action="store", dest="filter_paths", default=defaults_flag_in_config["filter_paths"], From fc20b4362ff8fe59653c7da16fbbdcc56f1eda26 Mon Sep 17 00:00:00 2001 From: Benjamin Samuels <1222451+bsamuels453@users.noreply.github.com> Date: Wed, 22 Feb 2023 09:35:52 -0800 Subject: [PATCH 23/44] add abstract contract property --- slither/core/declarations/contract.py | 1 + slither/solc_parsing/declarations/contract.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 95b05aa6b..2b11d392d 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -85,6 +85,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods self._kind: Optional[str] = None self._is_interface: bool = False self._is_library: bool = False + self._is_abstract: bool = False self._signatures: Optional[List[str]] = None self._signatures_declared: Optional[List[str]] = None diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index e63dbe68f..35c45a70b 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -165,6 +165,9 @@ class ContractSolc(CallerContextExpression): self._contract.is_library = True self._contract.contract_kind = attributes["contractKind"] + if not self._contract.is_interface: + self._contract.is_abstract = not attributes["fullyImplemented"] + self._linearized_base_contracts = attributes["linearizedBaseContracts"] # self._contract.fullyImplemented = attributes["fullyImplemented"] From 94b42ee96fa20de72e23f282c244b5f4e169bc24 Mon Sep 17 00:00:00 2001 From: Benjamin Samuels <1222451+bsamuels453@users.noreply.github.com> Date: Mon, 6 Mar 2023 11:08:58 -0800 Subject: [PATCH 24/44] change prop name to is_fully_implemented --- slither/core/declarations/contract.py | 8 +++++++- slither/solc_parsing/declarations/contract.py | 4 +--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 2b11d392d..dbd81890c 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -85,7 +85,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods self._kind: Optional[str] = None self._is_interface: bool = False self._is_library: bool = False - self._is_abstract: bool = False + self._is_fully_implemented: bool = False self._signatures: Optional[List[str]] = None self._signatures_declared: Optional[List[str]] = None @@ -192,6 +192,12 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods @comments.setter def comments(self, comments: str): self._comments = comments + def is_fully_implemented(self) -> bool: + return self._is_fully_implemented + + @is_fully_implemented.setter + def is_fully_implemented(self, is_fully_implemented: bool): + self._is_fully_implemented = is_fully_implemented # endregion ################################################################################### diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 35c45a70b..8ee755fa1 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -164,9 +164,7 @@ class ContractSolc(CallerContextExpression): elif attributes["contractKind"] == "library": self._contract.is_library = True self._contract.contract_kind = attributes["contractKind"] - - if not self._contract.is_interface: - self._contract.is_abstract = not attributes["fullyImplemented"] + self._contract.is_fully_implemented = attributes["fullyImplemented"] self._linearized_base_contracts = attributes["linearizedBaseContracts"] # self._contract.fullyImplemented = attributes["fullyImplemented"] From c08cbee3ecef9925b0b923aacc5d1e83afc69619 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 10 Mar 2023 11:46:18 +0100 Subject: [PATCH 25/44] Add tests --- tests/function_features/abstract.sol | 5 +++++ tests/function_features/implicit_abstract.sol | 5 +++++ tests/test_features.py | 15 +++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/function_features/abstract.sol create mode 100644 tests/function_features/implicit_abstract.sol diff --git a/tests/function_features/abstract.sol b/tests/function_features/abstract.sol new file mode 100644 index 000000000..b29f683c4 --- /dev/null +++ b/tests/function_features/abstract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +abstract contract ExplicitAbstract{ + function f() virtual public; +} diff --git a/tests/function_features/implicit_abstract.sol b/tests/function_features/implicit_abstract.sol new file mode 100644 index 000000000..c46ccd821 --- /dev/null +++ b/tests/function_features/implicit_abstract.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.5.0; + +contract ImplicitAbstract{ + function f() public; +} \ No newline at end of file diff --git a/tests/test_features.py b/tests/test_features.py index 68a21a884..20393df38 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -202,3 +202,18 @@ def test_using_for_global_collision() -> None: compilation = CryticCompile(standard_json) sl = Slither(compilation) _run_all_detectors(sl) + + +def test_abstract_contract() -> None: + solc_select.switch_global_version("0.8.0", always_install=True) + slither = Slither("./tests/function_features/abstract.sol") + assert not slither.contracts[0].is_fully_implemented + + solc_select.switch_global_version("0.5.0", always_install=True) + slither = Slither("./tests/function_features/implicit_abstract.sol") + assert not slither.contracts[0].is_fully_implemented + + slither = Slither( + "./tests/function_features/implicit_abstract.sol", solc_force_legacy_json=True + ) + assert not slither.contracts[0].is_fully_implemented From 5a37d308bd82f348d820c37e870abc22d7160454 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 13 Mar 2023 13:35:51 -0500 Subject: [PATCH 26/44] fmt --- slither/core/declarations/contract.py | 1 + tests/test_features.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index dbd81890c..51363b9fc 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -192,6 +192,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods @comments.setter def comments(self, comments: str): self._comments = comments + def is_fully_implemented(self) -> bool: return self._is_fully_implemented diff --git a/tests/test_features.py b/tests/test_features.py index 20393df38..d93a4ca2f 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -210,7 +210,7 @@ def test_abstract_contract() -> None: assert not slither.contracts[0].is_fully_implemented solc_select.switch_global_version("0.5.0", always_install=True) - slither = Slither("./tests/function_features/implicit_abstract.sol") + slither = Slither("./tests/function_features/abstract.sol") assert not slither.contracts[0].is_fully_implemented slither = Slither( From dc28a1efacec296976a9fc9ac6fee3281eb58fd0 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 13 Mar 2023 13:44:27 -0500 Subject: [PATCH 27/44] fix merge mistake --- slither/core/declarations/contract.py | 1 + tests/test_features.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 51363b9fc..b6a0b3d24 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -193,6 +193,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods def comments(self, comments: str): self._comments = comments + @property def is_fully_implemented(self) -> bool: return self._is_fully_implemented diff --git a/tests/test_features.py b/tests/test_features.py index d93a4ca2f..20393df38 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -210,7 +210,7 @@ def test_abstract_contract() -> None: assert not slither.contracts[0].is_fully_implemented solc_select.switch_global_version("0.5.0", always_install=True) - slither = Slither("./tests/function_features/abstract.sol") + slither = Slither("./tests/function_features/implicit_abstract.sol") assert not slither.contracts[0].is_fully_implemented slither = Slither( From 9e79ec6e16c9ebcf5986c20f53c203368a30cd0a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 13 Mar 2023 13:55:32 -0500 Subject: [PATCH 28/44] select solc version for test_ternary_conversions --- tests/slithir/test_ternary_expressions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/slithir/test_ternary_expressions.py b/tests/slithir/test_ternary_expressions.py index 17cac6b2f..384a4677d 100644 --- a/tests/slithir/test_ternary_expressions.py +++ b/tests/slithir/test_ternary_expressions.py @@ -6,6 +6,7 @@ from slither.core.expressions import AssignmentOperation, TupleExpression # pylint: disable=too-many-nested-blocks def test_ternary_conversions() -> None: """This tests that true and false sons define the same number of variables that the father node declares""" + solc_select.switch_global_version("0.8.0", always_install=True) slither = Slither("./tests/slithir/ternary_expressions.sol") for contract in slither.contracts: for function in contract.functions: From ba6ef4584747c496313a47830f9577d10290ca88 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 13 Mar 2023 13:58:01 -0500 Subject: [PATCH 29/44] add import --- tests/slithir/test_ternary_expressions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/slithir/test_ternary_expressions.py b/tests/slithir/test_ternary_expressions.py index 384a4677d..a1f00eb4f 100644 --- a/tests/slithir/test_ternary_expressions.py +++ b/tests/slithir/test_ternary_expressions.py @@ -1,3 +1,4 @@ +from solc_select import solc_select from slither import Slither from slither.core.cfg.node import NodeType from slither.slithir.operations import Assignment From 517d36e315ab50b9a756e6bd2a8f4ec5db010b02 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 14 Mar 2023 08:56:52 -0500 Subject: [PATCH 30/44] add issue template for false neg. and positive --- .github/ISSUE_TEMPLATE/false_negative.yml | 61 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/false_positive.yml | 61 +++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/false_negative.yml create mode 100644 .github/ISSUE_TEMPLATE/false_positive.yml diff --git a/.github/ISSUE_TEMPLATE/false_negative.yml b/.github/ISSUE_TEMPLATE/false_negative.yml new file mode 100644 index 000000000..f07d389fa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/false_negative.yml @@ -0,0 +1,61 @@ +--- +body: + - + attributes: + value: | + Please check the issues tab to avoid duplicates. + Thanks for helping make Slither the best it can be! + type: markdown + - + attributes: + label: "What bug did Slither miss and which detector did you anticipate would catch it?" + id: what-happened + type: textarea + validations: + required: true + - + attributes: + label: Frequency + description: How often do you run across this false positive? + options: + - Very Frequently + - Occasionally + - Rarely + - Not sure + id: frequency + type: dropdown + validations: + required: true + - + attributes: + description: "It can be a github repo, etherscan link, or code snippet." + label: "Code example to reproduce the issue:" + placeholder: "`contract A {}`\n" + id: reproduce + type: textarea + validations: + required: true + - + attributes: + description: | + What version of slither are you running? + Run `slither --version` + label: "Version:" + id: version + type: textarea + validations: + required: true + - + attributes: + description: | + Please copy and paste the result output. This + will be automatically formatted into code, so no need for backticks. + render: shell + label: "Relevant log output:" + id: logs + type: textarea +description: "Slither missed a bug it should find." +labels: + - false-negative +name: False Negative" +title: "[False Negative]: " diff --git a/.github/ISSUE_TEMPLATE/false_positive.yml b/.github/ISSUE_TEMPLATE/false_positive.yml new file mode 100644 index 000000000..258a70dfb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/false_positive.yml @@ -0,0 +1,61 @@ +--- +body: + - + attributes: + value: | + Please check the issues tab to avoid duplicates. + Thanks for helping make Slither the best it can be! + type: markdown + - + attributes: + label: "Describe the false alarm that Slither raise and how you know it's inaccurate:" + id: what-happened + type: textarea + validations: + required: true + - + attributes: + label: Frequency + description: How often do you run across this false positive? + options: + - Very Frequently + - Occasionally + - Rarely + - Not sure + id: frequency + type: dropdown + validations: + required: true + - + attributes: + description: "It can be a github repo, etherscan link, or code snippet." + label: "Code example to reproduce the issue:" + placeholder: "`contract A {}`\n" + id: reproduce + type: textarea + validations: + required: true + - + attributes: + description: | + What version of slither are you running? + Run `slither --version` + label: "Version:" + id: version + type: textarea + validations: + required: true + - + attributes: + description: | + Please copy and paste the result output. This + will be automatically formatted into code, so no need for backticks. + render: shell + label: "Relevant log output:" + id: logs + type: textarea +description: "Slither warned of an issue that is not legitimate and does not need to be fixed." +labels: + - false-positive +name: "False Positive" +title: "[False-Positive]: " From 4a69025afb1b32f1e1ba5380034a79d2b57fd9e6 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 14 Mar 2023 08:58:10 -0500 Subject: [PATCH 31/44] Update .github/ISSUE_TEMPLATE/false_negative.yml --- .github/ISSUE_TEMPLATE/false_negative.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/false_negative.yml b/.github/ISSUE_TEMPLATE/false_negative.yml index f07d389fa..e11b6ca8d 100644 --- a/.github/ISSUE_TEMPLATE/false_negative.yml +++ b/.github/ISSUE_TEMPLATE/false_negative.yml @@ -16,7 +16,7 @@ body: - attributes: label: Frequency - description: How often do you run across this false positive? + description: How often do you run across this false negative? options: - Very Frequently - Occasionally From a31282b483d579ae84c56069e40aa92764843023 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 15 Mar 2023 11:12:10 -0500 Subject: [PATCH 32/44] make web3>=6.0.0 a dependency --- setup.py | 3 +-- slither/tools/read_storage/read_storage.py | 11 +---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 1ffee1589..0d26167b3 100644 --- a/setup.py +++ b/setup.py @@ -27,11 +27,10 @@ setup( "pytest-xdist", "deepdiff", "numpy", - "slither-analyzer[read-storage]", "openai", "pdoc", + "web3>=6.0.0", ], - "read-storage": ["solc-select>=v1.0.0b1", "web3>=6.0.0b"], }, license="AGPL-3.0", long_description=long_description, diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index 8bf83db02..387aa619a 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -1,15 +1,7 @@ -import importlib.util import logging -import sys from math import floor from typing import Any, Callable, Dict, List, Optional, Tuple, Union -if importlib.util.find_spec("web3").loader is None: - print( - "Please install slither with `pip install slither-analyzer[read-storage]` to use slither-read-storage." - ) - sys.exit(-1) - import dataclasses from eth_abi import decode, encode @@ -18,8 +10,7 @@ from eth_utils import keccak from web3 import Web3 from slither.core.declarations import Contract, Structure -from slither.core.solidity_types import (ArrayType, ElementaryType, - MappingType, UserDefinedType) +from slither.core.solidity_types import ArrayType, ElementaryType, MappingType, UserDefinedType from slither.core.solidity_types.type import Type from slither.core.variables.state_variable import StateVariable from slither.core.variables.structure_variable import StructureVariable From 547a8047f0d1b16ba02e72ef4076d666b18f9533 Mon Sep 17 00:00:00 2001 From: William Aaron Cheung Date: Wed, 15 Mar 2023 21:43:37 -0400 Subject: [PATCH 33/44] add bug revealing test for #1748 --- tests/test_ssa_generation.py | 40 ++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tests/test_ssa_generation.py b/tests/test_ssa_generation.py index f002ec4e1..00d2f23fd 100644 --- a/tests/test_ssa_generation.py +++ b/tests/test_ssa_generation.py @@ -27,6 +27,7 @@ from slither.slithir.operations import ( BinaryType, InternalCall, Index, + InitArray, ) from slither.slithir.utils.ssa import is_used_later from slither.slithir.variables import ( @@ -796,20 +797,20 @@ def test_memory_array(): uint val1; uint val2; } - + function test_array() internal { A[] memory a= new A[](4); // Create REF_0 -> a_1[2] accept_array_entry(a[2]); - + // Create REF_1 -> a_1[3] accept_array_entry(a[3]); - + A memory alocal; accept_array_entry(alocal); - + } - + // val_1 = ϕ(val_0, REF_0, REF_1, alocal_1) // val_0 is an unknown external value function accept_array_entry(A memory val) public returns (uint) { @@ -818,9 +819,9 @@ def test_memory_array(): // Create REF_2 -> val_1.val1 return b(val.val1); } - + function b(uint arg) public returns (uint){ - // arg_1 = ϕ(arg_0, zero_1, REF_2) + // arg_1 = ϕ(arg_0, zero_1, REF_2) return arg + 1; } }""" @@ -862,12 +863,12 @@ def test_storage_array(): uint val1; uint val2; } - + // NOTE(hbrodin): a is never written, should only become a_0. Same for astorage (astorage_0). Phi-nodes at entry - // should only add new versions of a state variable if it is actually written. + // should only add new versions of a state variable if it is actually written. A[] a; A astorage; - + function test_array() internal { accept_array_entry(a[2]); accept_array_entry(a[3]); @@ -877,7 +878,7 @@ def test_storage_array(): function accept_array_entry(A storage val) internal returns (uint) { // val is either a[2], a[3] or astorage_0. Ideally this could be identified. uint five = 5; - + // NOTE(hbrodin): If the following line is enabled, there would ideally be a phi-node representing writes // to either a or astorage. //val.val2 = 4; @@ -1059,3 +1060,20 @@ def test_issue_473(): # return is for second phi assert len(return_value.values) == 1 assert second_phi.lvalue in return_value.values + + +def test_issue_1748(): + source = """ + contract Contract { + uint[] arr; + function foo(uint i) public { + arr = [1]; + } + } + """ + with slither_from_source(source) as slither: + c = slither.get_contract_from_name("Contract")[0] + f = c.functions[0] + operations = f.slithir_operations + assign_op = operations[0] + assert isinstance(assign_op, InitArray) From 6eab0b27973590539663076a26a1b436c47392eb Mon Sep 17 00:00:00 2001 From: William Aaron Cheung Date: Wed, 15 Mar 2023 21:43:49 -0400 Subject: [PATCH 34/44] fix #1748 --- slither/visitors/slithir/expression_to_slithir.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index c150ee20b..3a975939a 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -220,6 +220,12 @@ class ExpressionToSlithIR(ExpressionVisitor): operation.set_expression(expression) self._result.append(operation) set_val(expression, left) + elif isinstance(left.type, ArrayType): + # Special case for init of array, when the right has only one element + operation = InitArray([right], left) + operation.set_expression(expression) + self._result.append(operation) + set_val(expression, left) else: operation = convert_assignment( left, right, expression.type, expression.expression_return_type From cd1ec36dadc82ee81824ce53b00aa8c92e4fed11 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 16 Mar 2023 14:25:23 -0500 Subject: [PATCH 35/44] include salt in NewContract op, add test infra --- .github/workflows/features.yml | 1 + slither/slithir/operations/high_level_call.py | 2 +- slither/slithir/operations/new_contract.py | 4 +- tests/slithir/operation_reads.sol | 17 +++++++ tests/slithir/test_operation_reads.py | 49 +++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/slithir/operation_reads.sol create mode 100644 tests/slithir/test_operation_reads.py diff --git a/.github/workflows/features.yml b/.github/workflows/features.yml index b11a137d9..2c112e0aa 100644 --- a/.github/workflows/features.yml +++ b/.github/workflows/features.yml @@ -50,6 +50,7 @@ jobs: pytest tests/test_features.py pytest tests/test_constant_folding.py pytest tests/slithir/test_ternary_expressions.py + pytest tests/slithir/test_operation_reads.py pytest tests/test_functions_ids.py pytest tests/test_function.py pytest tests/test_source_mapping.py diff --git a/slither/slithir/operations/high_level_call.py b/slither/slithir/operations/high_level_call.py index 93fb73bd4..a12917519 100644 --- a/slither/slithir/operations/high_level_call.py +++ b/slither/slithir/operations/high_level_call.py @@ -76,7 +76,7 @@ class HighLevelCall(Call, OperationWithLValue): def read(self) -> List[SourceMapping]: all_read = [self.destination, self.call_gas, self.call_value] + self._unroll(self.arguments) # remove None - return [x for x in all_read if x] + [self.destination] + return [x for x in all_read if x] @property def destination(self) -> SourceMapping: diff --git a/slither/slithir/operations/new_contract.py b/slither/slithir/operations/new_contract.py index 879d12df6..08ddbd960 100644 --- a/slither/slithir/operations/new_contract.py +++ b/slither/slithir/operations/new_contract.py @@ -52,7 +52,9 @@ class NewContract(Call, OperationWithLValue): # pylint: disable=too-many-instan @property def read(self) -> List[Any]: - return self._unroll(self.arguments) + all_read = [self.call_salt, self.call_value] + self._unroll(self.arguments) + # remove None + return [x for x in all_read if x] @property def contract_created(self) -> Contract: diff --git a/tests/slithir/operation_reads.sol b/tests/slithir/operation_reads.sol new file mode 100644 index 000000000..22adc2288 --- /dev/null +++ b/tests/slithir/operation_reads.sol @@ -0,0 +1,17 @@ + +contract Placeholder { + constructor() payable {} +} + +contract NewContract { + bytes32 internal constant state_variable_read = bytes32(0); + + function readAllStateVariables() external { + new Placeholder{salt: state_variable_read} (); + } + + function readAllLocalVariables() external { + bytes32 local_variable_read = bytes32(0); + new Placeholder{salt: local_variable_read} (); + } +} \ No newline at end of file diff --git a/tests/slithir/test_operation_reads.py b/tests/slithir/test_operation_reads.py new file mode 100644 index 000000000..aa183333f --- /dev/null +++ b/tests/slithir/test_operation_reads.py @@ -0,0 +1,49 @@ +from collections import namedtuple +from slither import Slither +from slither.slithir.operations import Operation, NewContract + + +def check_num_local_vars_read(function, slithir_op: Operation, num_reads_expected: int): + for node in function.nodes: + for operation in node.irs: + if isinstance(operation, slithir_op): + assert len(operation.read) == num_reads_expected + assert len(node.local_variables_read) == num_reads_expected + + +def check_num_states_vars_read(function, slithir_op: Operation, num_reads_expected: int): + for node in function.nodes: + for operation in node.irs: + if isinstance(operation, slithir_op): + assert len(operation.read) == num_reads_expected + assert len(node.state_variables_read) == num_reads_expected + + +OperationTest = namedtuple("OperationTest", "contract_name slithir_op") + +OPERATION_TEST = [OperationTest("NewContract", NewContract)] + + +def test_operation_reads() -> None: + """ + Every slithir operation has its own contract and reads all local and state variables in readAllLocalVariables and readAllStateVariables, respectively. + """ + slither = Slither("./tests/slithir/operation_reads.sol") + + for op_test in OPERATION_TEST: + print(op_test) + available = slither.get_contract_from_name(op_test.contract_name) + assert len(available) == 1 + target = available[0] + + num_state_variables = len(target.state_variables_ordered) + state_function = target.get_function_from_signature("readAllStateVariables()") + check_num_states_vars_read(state_function, op_test.slithir_op, num_state_variables) + + local_function = target.get_function_from_signature("readAllLocalVariables()") + num_local_vars = len(local_function.local_variables) + check_num_local_vars_read(local_function, op_test.slithir_op, num_local_vars) + + +if __name__ == "__main__": + test_operation_reads() From 20fbfd45dfbb01abe3af0e32a57407f822fa3c90 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 16 Mar 2023 22:19:01 -0500 Subject: [PATCH 36/44] fix evm printer --- slither/printers/summary/evm.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/printers/summary/evm.py b/slither/printers/summary/evm.py index 660d91204..7e949b515 100644 --- a/slither/printers/summary/evm.py +++ b/slither/printers/summary/evm.py @@ -21,8 +21,8 @@ def _extract_evm_info(slither): CFG = load_evm_cfg_builder() for contract in slither.contracts_derived: - contract_bytecode_runtime = contract.scope.bytecode_runtime(contract.name) - contract_srcmap_runtime = contract.scope.srcmap_runtime(contract.name) + contract_bytecode_runtime = contract.file_scope.bytecode_runtime(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) + contract_srcmap_runtime = contract.file_scope.srcmap_runtime(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) cfg = CFG(contract_bytecode_runtime) evm_info["cfg", contract.name] = cfg evm_info["mapping", contract.name] = generate_source_to_evm_ins_mapping( @@ -32,8 +32,8 @@ def _extract_evm_info(slither): contract.source_mapping.filename.absolute, ) - contract_bytecode_init = contract.scope.bytecode_init(contract.name) - contract_srcmap_init = contract.scope.srcmap_init(contract.name) + contract_bytecode_init = contract.file_scope.bytecode_init(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) + contract_srcmap_init = contract.file_scope.srcmap_init(contract.compilation_unit.crytic_compile_compilation_unit, contract.name) cfg_init = CFG(contract_bytecode_init) evm_info["cfg_init", contract.name] = cfg_init From d6adbca5199ccadbf2947f0601882d444f83bdff Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 16 Mar 2023 22:21:19 -0500 Subject: [PATCH 37/44] update printer tests --- scripts/ci_test_printers.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index e542286fe..f6eaf0fc8 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,11 +5,20 @@ cd tests/ast-parsing/compile || exit # Do not test the evm printer,as it needs a refactoring -ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,human-summary,inheritance,inheritance-graph,slithir,slithir-ssa,vars-and-auth,require,variable-order" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,human-summary,inheritance,inheritance-graph,slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" # Only test 0.5.17 to limit test time for file in *0.5.17-compact.zip; do - if ! slither "$file" --print "$ALL_PRINTERS" > /dev/null 2>&1 ; then + if ! slither "$file" --print "$ALL_PRINTERS" ; then + echo "Printer failed" + echo "$file" + exit 1 + fi +done + +# Only test 0.8.12 to limit test time +for file in *0.8.12-compact.zip; do + if ! slither "$file" --print "declaration" ; then echo "Printer failed" echo "$file" exit 1 From 9dccce3452bdeecd7b98778170a4d822c4fd37e8 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 17 Mar 2023 08:35:27 -0500 Subject: [PATCH 38/44] update linter.yml name --- .github/workflows/linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 4f029399e..bc9177802 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -22,7 +22,7 @@ concurrency: jobs: build: - name: Pylint + name: Superlinter runs-on: ubuntu-latest steps: From 400dfd6f082eeae3c36078d49f11f403304488d0 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 17 Mar 2023 14:47:12 +0100 Subject: [PATCH 39/44] Minor --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2168dd18f..22eed98fa 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt - [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19 ### External publications -Title | Usage | Authors | Venue | Code +Title | Usage | Authors | Venue | Code --- | --- | --- | --- | --- [ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method) | AST-based analysis built on top of Slither | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 [MPro: Combining Static and Symbolic Analysis forScalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf) | Leverage data dependency through Slither | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 | [MPro](https://github.com/QuanZhang-William/M-Pro) From 462396edccbf91adc45fa1da2702a99e1491327f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 17 Mar 2023 09:29:32 -0500 Subject: [PATCH 40/44] correct web3 to be required, not dev dep --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0d26167b3..f9d100afd 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ setup( "pycryptodome>=3.4.6", # "crytic-compile>=0.3.0", "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", + "web3>=6.0.0", ], extras_require={ "dev": [ @@ -29,7 +30,6 @@ setup( "numpy", "openai", "pdoc", - "web3>=6.0.0", ], }, license="AGPL-3.0", From b2240b885d1076d521557944138b28ed2afcb96a Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 17 Mar 2023 17:56:26 +0100 Subject: [PATCH 41/44] Update solc version recommendations --- .../detectors/attributes/incorrect_solc.py | 7 +-- .../dynamic_1.sol.0.5.16.IncorrectSolc.json | 10 ++++ .../dynamic_2.sol.0.5.16.IncorrectSolc.json | 10 ++++ .../static.sol.0.5.16.IncorrectSolc.json | 48 ++++++++++++++++++- .../dynamic_1.sol.0.6.11.IncorrectSolc.json | 10 ++++ .../dynamic_2.sol.0.6.11.IncorrectSolc.json | 10 ++++ .../static.sol.0.6.11.IncorrectSolc.json | 48 ++++++++++++++++++- .../dynamic_1.sol.0.7.6.IncorrectSolc.json | 10 ++++ .../dynamic_2.sol.0.7.6.IncorrectSolc.json | 10 ++++ .../0.7.6/static.sol.0.7.6.IncorrectSolc.json | 48 ++++++++++++++++++- 10 files changed, 203 insertions(+), 8 deletions(-) diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index fa9ffd88d..843ee5019 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -43,10 +43,7 @@ We also recommend avoiding complex `pragma` statement.""" # region wiki_recommendation WIKI_RECOMMENDATION = """ Deploy with any of the following Solidity versions: -- 0.5.16 - 0.5.17 -- 0.6.11 - 0.6.12 -- 0.7.5 - 0.7.6 -- 0.8.16 +- 0.8.18 The recommendations take into account: - Risks related to recent releases @@ -68,7 +65,7 @@ Consider using the latest version of Solidity for testing.""" ) # Indicates the allowed versions. Must be formatted in increasing order. - ALLOWED_VERSIONS = ["0.5.16", "0.5.17", "0.6.11", "0.6.12", "0.7.5", "0.7.6", "0.8.16"] + ALLOWED_VERSIONS = ["0.8.18"] # Indicates the versions that should not be used. BUGGY_VERSIONS = [ diff --git a/tests/detectors/solc-version/0.5.16/dynamic_1.sol.0.5.16.IncorrectSolc.json b/tests/detectors/solc-version/0.5.16/dynamic_1.sol.0.5.16.IncorrectSolc.json index 28381e3ca..599392dc8 100644 --- a/tests/detectors/solc-version/0.5.16/dynamic_1.sol.0.5.16.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.5.16/dynamic_1.sol.0.5.16.IncorrectSolc.json @@ -1,5 +1,15 @@ [ [ + { + "elements": [], + "description": "solc-0.5.16 is not recommended for deployment\n", + "markdown": "solc-0.5.16 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "94ddf430efb860e471a768a108c851848fa998e8a2c489c6fb23ed71d3ef4b09", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, { "elements": [ { diff --git a/tests/detectors/solc-version/0.5.16/dynamic_2.sol.0.5.16.IncorrectSolc.json b/tests/detectors/solc-version/0.5.16/dynamic_2.sol.0.5.16.IncorrectSolc.json index 19ab5889f..8eacb5663 100644 --- a/tests/detectors/solc-version/0.5.16/dynamic_2.sol.0.5.16.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.5.16/dynamic_2.sol.0.5.16.IncorrectSolc.json @@ -38,6 +38,16 @@ "check": "solc-version", "impact": "Informational", "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.5.16 is not recommended for deployment\n", + "markdown": "solc-0.5.16 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "94ddf430efb860e471a768a108c851848fa998e8a2c489c6fb23ed71d3ef4b09", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.5.16/static.sol.0.5.16.IncorrectSolc.json b/tests/detectors/solc-version/0.5.16/static.sol.0.5.16.IncorrectSolc.json index 5825bcacc..df4bac19d 100644 --- a/tests/detectors/solc-version/0.5.16/static.sol.0.5.16.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.5.16/static.sol.0.5.16.IncorrectSolc.json @@ -1,3 +1,49 @@ [ - [] + [ + { + "elements": [ + { + "type": "pragma", + "name": "0.5.16", + "source_mapping": { + "start": 0, + "length": 23, + "filename_relative": "tests/detectors/solc-version/0.5.16/static.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/solc-version/0.5.16/static.sol", + "is_dependency": false, + "lines": [ + 1 + ], + "starting_column": 1, + "ending_column": 24 + }, + "type_specific_fields": { + "directive": [ + "solidity", + "0.5", + ".16" + ] + } + } + ], + "description": "Pragma version0.5.16 (tests/detectors/solc-version/0.5.16/static.sol#1) allows old versions\n", + "markdown": "Pragma version[0.5.16](tests/detectors/solc-version/0.5.16/static.sol#L1) allows old versions\n", + "first_markdown_element": "tests/detectors/solc-version/0.5.16/static.sol#L1", + "id": "2407d991de90e57d2f6b6bdbc61bb939845a5c0bb2d82910ed4c49abff2ab6e3", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.5.16 is not recommended for deployment\n", + "markdown": "solc-0.5.16 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "94ddf430efb860e471a768a108c851848fa998e8a2c489c6fb23ed71d3ef4b09", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + } + ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.6.11/dynamic_1.sol.0.6.11.IncorrectSolc.json b/tests/detectors/solc-version/0.6.11/dynamic_1.sol.0.6.11.IncorrectSolc.json index b182c02c7..a71fa6406 100644 --- a/tests/detectors/solc-version/0.6.11/dynamic_1.sol.0.6.11.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.6.11/dynamic_1.sol.0.6.11.IncorrectSolc.json @@ -35,6 +35,16 @@ "check": "solc-version", "impact": "Informational", "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.6.11 is not recommended for deployment\n", + "markdown": "solc-0.6.11 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "bafd522d637977886f038e619ad47c1987efedc6c4c24515e6e27b23585535bd", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.6.11/dynamic_2.sol.0.6.11.IncorrectSolc.json b/tests/detectors/solc-version/0.6.11/dynamic_2.sol.0.6.11.IncorrectSolc.json index 4f844e25e..d6cac106b 100644 --- a/tests/detectors/solc-version/0.6.11/dynamic_2.sol.0.6.11.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.6.11/dynamic_2.sol.0.6.11.IncorrectSolc.json @@ -38,6 +38,16 @@ "check": "solc-version", "impact": "Informational", "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.6.11 is not recommended for deployment\n", + "markdown": "solc-0.6.11 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "bafd522d637977886f038e619ad47c1987efedc6c4c24515e6e27b23585535bd", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.6.11/static.sol.0.6.11.IncorrectSolc.json b/tests/detectors/solc-version/0.6.11/static.sol.0.6.11.IncorrectSolc.json index 5825bcacc..61ea21e16 100644 --- a/tests/detectors/solc-version/0.6.11/static.sol.0.6.11.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.6.11/static.sol.0.6.11.IncorrectSolc.json @@ -1,3 +1,49 @@ [ - [] + [ + { + "elements": [ + { + "type": "pragma", + "name": "0.6.11", + "source_mapping": { + "start": 0, + "length": 23, + "filename_relative": "tests/detectors/solc-version/0.6.11/static.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/solc-version/0.6.11/static.sol", + "is_dependency": false, + "lines": [ + 1 + ], + "starting_column": 1, + "ending_column": 24 + }, + "type_specific_fields": { + "directive": [ + "solidity", + "0.6", + ".11" + ] + } + } + ], + "description": "Pragma version0.6.11 (tests/detectors/solc-version/0.6.11/static.sol#1) allows old versions\n", + "markdown": "Pragma version[0.6.11](tests/detectors/solc-version/0.6.11/static.sol#L1) allows old versions\n", + "first_markdown_element": "tests/detectors/solc-version/0.6.11/static.sol#L1", + "id": "ad7b24eed22ac098a57ae02ade0ccffb4cb094e851effe93cad1d0a65b489816", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.6.11 is not recommended for deployment\n", + "markdown": "solc-0.6.11 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "bafd522d637977886f038e619ad47c1987efedc6c4c24515e6e27b23585535bd", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + } + ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.7.6/dynamic_1.sol.0.7.6.IncorrectSolc.json b/tests/detectors/solc-version/0.7.6/dynamic_1.sol.0.7.6.IncorrectSolc.json index aafb7b5d1..763302445 100644 --- a/tests/detectors/solc-version/0.7.6/dynamic_1.sol.0.7.6.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.7.6/dynamic_1.sol.0.7.6.IncorrectSolc.json @@ -1,5 +1,15 @@ [ [ + { + "elements": [], + "description": "solc-0.7.6 is not recommended for deployment\n", + "markdown": "solc-0.7.6 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "ddb8ee36d9dd69b14eab702506268f8f9ef3283777d042e197277e29407b386e", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, { "elements": [ { diff --git a/tests/detectors/solc-version/0.7.6/dynamic_2.sol.0.7.6.IncorrectSolc.json b/tests/detectors/solc-version/0.7.6/dynamic_2.sol.0.7.6.IncorrectSolc.json index 4aea32763..516f3142b 100644 --- a/tests/detectors/solc-version/0.7.6/dynamic_2.sol.0.7.6.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.7.6/dynamic_2.sol.0.7.6.IncorrectSolc.json @@ -38,6 +38,16 @@ "check": "solc-version", "impact": "Informational", "confidence": "High" + }, + { + "elements": [], + "description": "solc-0.7.6 is not recommended for deployment\n", + "markdown": "solc-0.7.6 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "ddb8ee36d9dd69b14eab702506268f8f9ef3283777d042e197277e29407b386e", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] ] \ No newline at end of file diff --git a/tests/detectors/solc-version/0.7.6/static.sol.0.7.6.IncorrectSolc.json b/tests/detectors/solc-version/0.7.6/static.sol.0.7.6.IncorrectSolc.json index 5825bcacc..426786fff 100644 --- a/tests/detectors/solc-version/0.7.6/static.sol.0.7.6.IncorrectSolc.json +++ b/tests/detectors/solc-version/0.7.6/static.sol.0.7.6.IncorrectSolc.json @@ -1,3 +1,49 @@ [ - [] + [ + { + "elements": [], + "description": "solc-0.7.6 is not recommended for deployment\n", + "markdown": "solc-0.7.6 is not recommended for deployment\n", + "first_markdown_element": "", + "id": "ddb8ee36d9dd69b14eab702506268f8f9ef3283777d042e197277e29407b386e", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + }, + { + "elements": [ + { + "type": "pragma", + "name": "0.7.6", + "source_mapping": { + "start": 0, + "length": 22, + "filename_relative": "tests/detectors/solc-version/0.7.6/static.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/solc-version/0.7.6/static.sol", + "is_dependency": false, + "lines": [ + 1 + ], + "starting_column": 1, + "ending_column": 23 + }, + "type_specific_fields": { + "directive": [ + "solidity", + "0.7", + ".6" + ] + } + } + ], + "description": "Pragma version0.7.6 (tests/detectors/solc-version/0.7.6/static.sol#1) allows old versions\n", + "markdown": "Pragma version[0.7.6](tests/detectors/solc-version/0.7.6/static.sol#L1) allows old versions\n", + "first_markdown_element": "tests/detectors/solc-version/0.7.6/static.sol#L1", + "id": "e7a5c0ee3d0af7a59907908f88499f79435e302745284c6279167a1cc209b4ed", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" + } + ] ] \ No newline at end of file From be68b6f948f7869299dcfc36e6f0eee54aad7087 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 17 Mar 2023 18:15:28 +0100 Subject: [PATCH 42/44] Improve error message --- slither/detectors/attributes/incorrect_solc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index 843ee5019..f63c045d8 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -59,7 +59,6 @@ Consider using the latest version of Solidity for testing.""" OLD_VERSION_TXT = "allows old versions" LESS_THAN_TXT = "uses lesser than" - TOO_RECENT_VERSION_TXT = "necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.16" BUGGY_VERSION_TXT = ( "is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)" ) @@ -67,6 +66,8 @@ Consider using the latest version of Solidity for testing.""" # Indicates the allowed versions. Must be formatted in increasing order. ALLOWED_VERSIONS = ["0.8.18"] + TOO_RECENT_VERSION_TXT = f"necessitates a version too recent to be trusted. Consider deploying with {'/'.join(ALLOWED_VERSIONS)} " + # Indicates the versions that should not be used. BUGGY_VERSIONS = [ "0.4.22", From fba4f7d08fd148d2a38dab4dc01637c14e4456f0 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 17 Mar 2023 18:18:38 +0100 Subject: [PATCH 43/44] Minor --- slither/detectors/attributes/incorrect_solc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index f63c045d8..73874cffc 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -66,7 +66,7 @@ Consider using the latest version of Solidity for testing.""" # Indicates the allowed versions. Must be formatted in increasing order. ALLOWED_VERSIONS = ["0.8.18"] - TOO_RECENT_VERSION_TXT = f"necessitates a version too recent to be trusted. Consider deploying with {'/'.join(ALLOWED_VERSIONS)} " + TOO_RECENT_VERSION_TXT = f"necessitates a version too recent to be trusted. Consider deploying with {'/'.join(ALLOWED_VERSIONS)}." # Indicates the versions that should not be used. BUGGY_VERSIONS = [ From efeea531db2e0f696116263295bf441756945801 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 17 Mar 2023 18:41:52 +0100 Subject: [PATCH 44/44] Update readme --- README.md | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 22eed98fa..bce20bfb0 100644 --- a/README.md +++ b/README.md @@ -151,26 +151,27 @@ Num | Detector | What it Detects | Impact | Confidence 61 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High 62 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High 63 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High -64 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High -65 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High -66 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High -67 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High -68 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High -69 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High -70 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High -71 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High -72 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High -73 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High -74 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High -75 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium -76 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium -77 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium -78 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium -79 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium -80 | `constable-states` | [State variables that could be declared constant](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) | Optimization | High -81 | `external-function` | [Public function that could be declared external](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) | Optimization | High -82 | `immutable-states` | [State variables that could be declared immutable](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable) | Optimization | High -83 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Vulnerabilities-Description#public-variable-read-in-external-context) | Optimization | High +64 | `cyclomatic-complexity` | [Detects functions with high (> 11) cyclomatic complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) | Informational | High +65 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High +66 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High +67 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High +68 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High +69 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High +70 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High +71 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High +72 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High +73 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High +74 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High +75 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High +76 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium +77 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium +78 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium +79 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium +80 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium +81 | `constable-states` | [State variables that could be declared constant](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) | Optimization | High +82 | `external-function` | [Public function that could be declared external](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) | Optimization | High +83 | `immutable-states` | [State variables that could be declared immutable](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable) | Optimization | High +84 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Vulnerabilities-Description#public-variable-read-in-external-context) | Optimization | High For more information, see - The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector