From 0ee1c64959e339387b25dfb83dc3fce6bff7e548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Tue, 8 Nov 2022 17:14:01 -0300 Subject: [PATCH 001/338] fail-on: rework feature This adds a new `fail_on` config option that can be changed with a mutually exclusive group of argument flags. It also decouples the exclude_* and fail_on flags, so you can do things like `fail_on: pedantic` while disabling optimization findings. Additionally, this adds some new code to detect the old-style config options, migrate their settings, and alert the user. Fixes #1458 --- slither/__main__.py | 78 +++++++++++++++++++---------------- slither/utils/command_line.py | 50 ++++++++++++++++++++-- 2 files changed, 88 insertions(+), 40 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 70357586e..a2402fb60 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -28,6 +28,8 @@ from slither.utils.output import output_to_json, output_to_zip, output_to_sarif, from slither.utils.output_capture import StandardOutputCapture from slither.utils.colors import red, set_colorization_enabled from slither.utils.command_line import ( + FailOnLevel, + migrate_config_options, output_detectors, output_results_to_markdown, output_detectors_json, @@ -220,22 +222,22 @@ def choose_detectors( detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT) return detectors_to_run - if args.exclude_optimization and not args.fail_pedantic: + if args.exclude_optimization: detectors_to_run = [ d for d in detectors_to_run if d.IMPACT != DetectorClassification.OPTIMIZATION ] - if args.exclude_informational and not args.fail_pedantic: + if args.exclude_informational: detectors_to_run = [ d for d in detectors_to_run if d.IMPACT != DetectorClassification.INFORMATIONAL ] - if args.exclude_low and not args.fail_low: + if args.exclude_low: detectors_to_run = [d for d in detectors_to_run if d.IMPACT != DetectorClassification.LOW] - if args.exclude_medium and not args.fail_medium: + if args.exclude_medium: detectors_to_run = [ d for d in detectors_to_run if d.IMPACT != DetectorClassification.MEDIUM ] - if args.exclude_high and not args.fail_high: + if args.exclude_high: detectors_to_run = [d for d in detectors_to_run if d.IMPACT != DetectorClassification.HIGH] if args.detectors_to_exclude: detectors_to_run = [ @@ -401,41 +403,44 @@ def parse_args( default=defaults_flag_in_config["exclude_high"], ) - group_detector.add_argument( + fail_on_group = group_detector.add_mutually_exclusive_group() + fail_on_group.add_argument( "--fail-pedantic", - help="Return the number of findings in the exit code", - action="store_true", - default=defaults_flag_in_config["fail_pedantic"], + help="Fail if any findings are detected", + action="store_const", + dest="fail_on", + const=FailOnLevel.PEDANTIC, ) - - group_detector.add_argument( - "--no-fail-pedantic", - help="Do not return the number of findings in the exit code. Opposite of --fail-pedantic", - dest="fail_pedantic", - action="store_false", - required=False, - ) - - group_detector.add_argument( + fail_on_group.add_argument( "--fail-low", - help="Fail if low or greater impact finding is detected", - action="store_true", - default=defaults_flag_in_config["fail_low"], + help="Fail if any low or greater impact findings are detected", + action="store_const", + dest="fail_on", + const=FailOnLevel.LOW, ) - - group_detector.add_argument( + fail_on_group.add_argument( "--fail-medium", - help="Fail if medium or greater impact finding is detected", - action="store_true", - default=defaults_flag_in_config["fail_medium"], + help="Fail if any medium or greater impact findings are detected", + action="store_const", + dest="fail_on", + const=FailOnLevel.MEDIUM, ) - - group_detector.add_argument( + fail_on_group.add_argument( "--fail-high", - help="Fail if high impact finding is detected", - action="store_true", - default=defaults_flag_in_config["fail_high"], + help="Fail if any high impact findings are detected", + action="store_const", + dest="fail_on", + const=FailOnLevel.HIGH, + ) + fail_on_group.add_argument( + "--fail-none", + "--no-fail-pedantic", + help="Do not return the number of findings in the exit code", + action="store_const", + dest="fail_on", + const=FailOnLevel.NONE, ) + fail_on_group.set_defaults(fail_on=FailOnLevel.PEDANTIC) group_detector.add_argument( "--show-ignored-findings", @@ -910,17 +915,18 @@ def main_impl( stats = pstats.Stats(cp).sort_stats("cumtime") stats.print_stats() - if args.fail_high: + fail_on = FailOnLevel(args.fail_on) + if fail_on == FailOnLevel.HIGH: fail_on_detection = any(result["impact"] == "High" for result in results_detectors) - elif args.fail_medium: + elif fail_on == FailOnLevel.MEDIUM: fail_on_detection = any( result["impact"] in ["Medium", "High"] for result in results_detectors ) - elif args.fail_low: + elif fail_on == FailOnLevel.LOW: fail_on_detection = any( result["impact"] in ["Low", "Medium", "High"] for result in results_detectors ) - elif args.fail_pedantic: + elif fail_on == FailOnLevel.PEDANTIC: fail_on_detection = bool(results_detectors) else: fail_on_detection = False diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index c2fef5eca..a650960f5 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -1,4 +1,5 @@ import argparse +import enum import json import os import re @@ -27,6 +28,15 @@ JSON_OUTPUT_TYPES = [ "list-printers", ] + +class FailOnLevel(enum.Enum): + PEDANTIC = "pedantic" + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + NONE = "none" + + # Those are the flags shared by the command line and the config file defaults_flag_in_config = { "detectors_to_run": "all", @@ -38,10 +48,7 @@ defaults_flag_in_config = { "exclude_low": False, "exclude_medium": False, "exclude_high": False, - "fail_pedantic": True, - "fail_low": False, - "fail_medium": False, - "fail_high": False, + "fail_on": FailOnLevel.PEDANTIC.value, "json": None, "sarif": None, "json-types": ",".join(DEFAULT_JSON_OUTPUT_TYPES), @@ -57,6 +64,13 @@ defaults_flag_in_config = { **DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, } +deprecated_flags = { + "fail_pedantic": True, + "fail_low": False, + "fail_medium": False, + "fail_high": False, +} + def read_config_file(args: argparse.Namespace) -> None: # No config file was provided as an argument @@ -73,6 +87,12 @@ def read_config_file(args: argparse.Namespace) -> None: with open(args.config_file, encoding="utf8") as f: config = json.load(f) for key, elem in config.items(): + if key in deprecated_flags: + logger.info( + yellow(f"{args.config_file} has a deprecated key: {key} : {elem}") + ) + migrate_config_options(args, key, elem) + continue if key not in defaults_flag_in_config: logger.info( yellow(f"{args.config_file} has an unknown key: {key} : {elem}") @@ -87,6 +107,28 @@ def read_config_file(args: argparse.Namespace) -> None: logger.error(yellow("Falling back to the default settings...")) +def migrate_config_options(args: argparse.Namespace, key: str, elem): + if key.startswith("fail_") and getattr(args, "fail_on") == defaults_flag_in_config["fail_on"]: + if key == "fail_pedantic": + pedantic_setting = elem + fail_on = pedantic_setting and FailOnLevel.PEDANTIC or FailOnLevel.NONE + setattr(args, "fail_on", fail_on) + logger.info( + "Migrating fail_pedantic: {} as fail_on: {}".format(pedantic_setting, fail_on.value) + ) + elif key == "fail_low" and elem == True: + logger.info("Migrating fail_low: true -> fail_on: low") + setattr(args, "fail_on", FailOnLevel.LOW) + elif key == "fail_medium" and elem == True: + logger.info("Migrating fail_medium: true -> fail_on: medium") + setattr(args, "fail_on", FailOnLevel.MEDIUM) + elif key == "fail_high" and elem == True: + logger.info("Migrating fail_high: true -> fail_on: high") + setattr(args, "fail_on", FailOnLevel.HIGH) + else: + logger.warn(yellow("Key {} was deprecated but no migration was provided".format(key))) + + def output_to_markdown( detector_classes: List[Type[AbstractDetector]], printer_classes: List[Type[AbstractPrinter]], From 0e2f085d82259e4761242dd298cb755e08fa80ea Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 23 Feb 2023 13:25:03 +0100 Subject: [PATCH 002/338] Support user defined operators --- slither/core/solidity_types/type_alias.py | 5 +- .../declarations/using_for_top_level.py | 43 +++++++++----- .../expressions/expression_parsing.py | 58 +++++++++++++++---- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/slither/core/solidity_types/type_alias.py b/slither/core/solidity_types/type_alias.py index 5b9ea0a37..a9010c7d9 100644 --- a/slither/core/solidity_types/type_alias.py +++ b/slither/core/solidity_types/type_alias.py @@ -1,10 +1,11 @@ -from typing import TYPE_CHECKING, Tuple +from typing import TYPE_CHECKING, Tuple, Dict from slither.core.children.child_contract import ChildContract from slither.core.declarations.top_level import TopLevel from slither.core.solidity_types import Type, ElementaryType if TYPE_CHECKING: + from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations import Contract from slither.core.scope.scope import FileScope @@ -43,6 +44,8 @@ class TypeAliasTopLevel(TypeAlias, TopLevel): def __init__(self, underlying_type: Type, name: str, scope: "FileScope") -> None: super().__init__(underlying_type, name) self.file_scope: "FileScope" = scope + # operators redefined + self.operators: Dict[str, "FunctionTopLevel"] = {} def __str__(self) -> str: return self.name diff --git a/slither/solc_parsing/declarations/using_for_top_level.py b/slither/solc_parsing/declarations/using_for_top_level.py index b16fadc40..e20fb3bcf 100644 --- a/slither/solc_parsing/declarations/using_for_top_level.py +++ b/slither/solc_parsing/declarations/using_for_top_level.py @@ -55,22 +55,29 @@ class UsingForTopLevelSolc(CallerContextExpression): # pylint: disable=too-few- self._propagate_global(type_name) else: for f in self._functions: - full_name_split = f["function"]["name"].split(".") - if len(full_name_split) == 1: + # User defined operator + if "operator" in f: # Top level function - function_name: str = full_name_split[0] - self._analyze_top_level_function(function_name, type_name) - elif len(full_name_split) == 2: - # It can be a top level function behind an aliased import - # or a library function - first_part = full_name_split[0] - function_name = full_name_split[1] - self._check_aliased_import(first_part, function_name, type_name) + function_name: str = f["definition"]["name"] + operator: str = f["operator"] + self._analyze_operator(operator, function_name, type_name) else: - # MyImport.MyLib.a we don't care of the alias - library_name_str = full_name_split[1] - function_name = full_name_split[2] - self._analyze_library_function(library_name_str, function_name, type_name) + full_name_split = f["function"]["name"].split(".") + if len(full_name_split) == 1: + # Top level function + function_name: str = full_name_split[0] + self._analyze_top_level_function(function_name, type_name) + elif len(full_name_split) == 2: + # It can be a top level function behind an aliased import + # or a library function + first_part = full_name_split[0] + function_name = full_name_split[1] + self._check_aliased_import(first_part, function_name, type_name) + else: + # MyImport.MyLib.a we don't care of the alias + library_name_str = full_name_split[1] + function_name = full_name_split[2] + self._analyze_library_function(library_name_str, function_name, type_name) def _check_aliased_import( self, @@ -96,6 +103,14 @@ class UsingForTopLevelSolc(CallerContextExpression): # pylint: disable=too-few- self._propagate_global(type_name) break + def _analyze_operator( + self, operator: str, function_name: str, type_name: TypeAliasTopLevel + ) -> None: + for tl_function in self.compilation_unit.functions_top_level: + if tl_function.name == function_name: + type_name.operators[operator] = tl_function + break + def _analyze_library_function( self, library_name: str, diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index ea433a921..0727d2a16 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -1,6 +1,6 @@ import logging import re -from typing import Union, Dict, TYPE_CHECKING +from typing import Union, Dict, TYPE_CHECKING, List, Any import slither.core.expressions.type_conversion from slither.core.declarations.solidity_variables import ( @@ -236,6 +236,24 @@ if TYPE_CHECKING: pass +def _user_defined_op_call( + caller_context: CallerContextExpression, src, function_id: int, args: List[Any], type_call: str +) -> CallExpression: + var, was_created = find_variable(None, caller_context, function_id) + + if was_created: + var.set_offset(src, caller_context.compilation_unit) + + identifier = Identifier(var) + identifier.set_offset(src, caller_context.compilation_unit) + + var.references.append(identifier.source_mapping) + + call = CallExpression(identifier, args, type_call) + call.set_offset(src, caller_context.compilation_unit) + return call + + def parse_expression(expression: Dict, caller_context: CallerContextExpression) -> "Expression": # pylint: disable=too-many-nested-blocks,too-many-statements """ @@ -274,16 +292,24 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression) if name == "UnaryOperation": if is_compact_ast: attributes = expression - else: - attributes = expression["attributes"] - assert "prefix" in attributes - operation_type = UnaryOperationType.get_type(attributes["operator"], attributes["prefix"]) - - if is_compact_ast: expression = parse_expression(expression["subExpression"], caller_context) else: + attributes = expression["attributes"] assert len(expression["children"]) == 1 expression = parse_expression(expression["children"][0], caller_context) + assert "prefix" in attributes + + # Use of user defined operation + if "function" in attributes: + return _user_defined_op_call( + caller_context, + src, + attributes["function"], + [expression], + attributes["typeDescriptions"]["typeString"], + ) + + operation_type = UnaryOperationType.get_type(attributes["operator"], attributes["prefix"]) unary_op = UnaryOperation(expression, operation_type) unary_op.set_offset(src, caller_context.compilation_unit) return unary_op @@ -291,17 +317,25 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression) if name == "BinaryOperation": if is_compact_ast: attributes = expression - else: - attributes = expression["attributes"] - operation_type = BinaryOperationType.get_type(attributes["operator"]) - - if is_compact_ast: left_expression = parse_expression(expression["leftExpression"], caller_context) right_expression = parse_expression(expression["rightExpression"], caller_context) else: assert len(expression["children"]) == 2 + attributes = expression["attributes"] left_expression = parse_expression(expression["children"][0], caller_context) right_expression = parse_expression(expression["children"][1], caller_context) + + # Use of user defined operation + if "function" in attributes: + return _user_defined_op_call( + caller_context, + src, + attributes["function"], + [left_expression, right_expression], + attributes["typeDescriptions"]["typeString"], + ) + + operation_type = BinaryOperationType.get_type(attributes["operator"]) binary_op = BinaryOperation(left_expression, right_expression, operation_type) binary_op.set_offset(src, caller_context.compilation_unit) return binary_op From 5edc3c280e9683e42d8beff5cbe23e5f32529015 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 10 Mar 2023 21:41:16 +0100 Subject: [PATCH 003/338] Add tests --- ...ed_operators-0.8.19.sol-0.8.19-compact.zip | Bin 0 -> 5844 bytes ...d_operators-0.8.19.sol-0.8.19-compact.json | 13 +++++ .../user_defined_operators-0.8.19.sol | 48 +++++++++++++++++ tests/test_ast_parsing.py | 1 + tests/test_features.py | 51 ++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 tests/ast-parsing/compile/user_defined_operators-0.8.19.sol-0.8.19-compact.zip create mode 100644 tests/ast-parsing/expected/user_defined_operators-0.8.19.sol-0.8.19-compact.json create mode 100644 tests/ast-parsing/user_defined_operators-0.8.19.sol diff --git a/tests/ast-parsing/compile/user_defined_operators-0.8.19.sol-0.8.19-compact.zip b/tests/ast-parsing/compile/user_defined_operators-0.8.19.sol-0.8.19-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..7159a1486165e875e77b28cb8132456dbea5a367 GIT binary patch literal 5844 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\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", + "add_op(Int,Int)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "lib_call(Int)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "neg_usertype(Int)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", + "neg_int(int256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "eq_op(Int,Int)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/user_defined_operators-0.8.19.sol b/tests/ast-parsing/user_defined_operators-0.8.19.sol new file mode 100644 index 000000000..e4df845fb --- /dev/null +++ b/tests/ast-parsing/user_defined_operators-0.8.19.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.8.19; + +type Int is int; +using {add as +, eq as ==, add, neg as -, Lib.f} for Int global; + +function add(Int a, Int b) pure returns (Int) { + return Int.wrap(Int.unwrap(a) + Int.unwrap(b)); +} + +function eq(Int a, Int b) pure returns (bool) { + return true; +} + +function neg(Int a) pure returns (Int) { + return a; +} + +library Lib { + function f(Int r) internal {} +} + +contract T { + function add_function_call(Int b, Int c) public returns(Int) { + Int res = add(b,c); + return res; + } + + function add_op(Int b, Int c) public returns(Int) { + return b + c; + } + + function lib_call(Int b) public { + return b.f(); + } + + function neg_usertype(Int b) public returns(Int) { + Int res = -b; + return res; + } + + function neg_int(int b) public returns(int) { + return -b; + } + + function eq_op(Int b, Int c) public returns(bool) { + return b == c; + } +} diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py index c783f827f..945fde505 100644 --- a/tests/test_ast_parsing.py +++ b/tests/test_ast_parsing.py @@ -444,6 +444,7 @@ ALL_TESTS = [ Test("yul-top-level-0.8.0.sol", ["0.8.0"]), Test("complex_imports/import_aliases_issue_1319/test.sol", ["0.5.12"]), Test("yul-state-constant-access.sol", ["0.8.16"]), + Test("user_defined_operators-0.8.19.sol", ["0.8.19"]), ] # create the output folder if needed try: diff --git a/tests/test_features.py b/tests/test_features.py index d29a5eb6a..db0314b3f 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -160,3 +160,54 @@ def test_arithmetic_usage() -> None: assert { f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0]) } == {"2b4bc73cf59d486dd9043e840b5028b679354dd9", "e4ecd4d0fda7e762d29aceb8425f2c5d4d0bf962"} + + +def test_user_defined_operators() -> None: + solc_select.switch_global_version("0.8.19", always_install=True) + slither = Slither("./tests/ast-parsing/user_defined_operators-0.8.19.sol") + contract_t = slither.get_contract_from_name("T")[0] + add_function_call = contract_t.get_function_from_full_name("add_function_call(Int,Int)") + ok = False + for ir in add_function_call.all_slithir_operations(): + if isinstance(ir, InternalCall) and ir.function_name == "add": + ok = True + if not ok: + assert False + + add_op = contract_t.get_function_from_full_name("add_op(Int,Int)") + ok = False + for ir in add_op.all_slithir_operations(): + if isinstance(ir, InternalCall) and ir.function_name == "add": + ok = True + if not ok: + assert False + + lib_call = contract_t.get_function_from_full_name("lib_call(Int)") + ok = False + for ir in lib_call.all_slithir_operations(): + if isinstance(ir, LibraryCall) and ir.destination == "Lib" and ir.function_name == "f": + ok = True + if not ok: + assert False + + neg_usertype = contract_t.get_function_from_full_name("neg_usertype(Int)") + ok = False + for ir in neg_usertype.all_slithir_operations(): + if isinstance(ir, InternalCall) and ir.function_name == "neg": + ok = True + if not ok: + assert False + + neg_int = contract_t.get_function_from_full_name("neg_int(int256)") + ok = True + for ir in neg_int.all_slithir_operations(): + if isinstance(ir, InternalCall): + ok = False + if not ok: + assert False + + eq_op = contract_t.get_function_from_full_name("eq_op(Int,Int)") + for ir in eq_op.all_slithir_operations(): + if isinstance(ir, InternalCall) and ir.function_name == "eq": + return + assert False From 64abf06e0a8ef3e74fcdcc7c0956921dbc2cb4c4 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 10 Mar 2023 21:53:32 +0100 Subject: [PATCH 004/338] Run pylint --- tests/test_features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_features.py b/tests/test_features.py index 297023b4c..c6b670d35 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -203,7 +203,7 @@ def test_using_for_global_collision() -> None: sl = Slither(compilation) _run_all_detectors(sl) - +# pylint: disable=too-many-branches def test_user_defined_operators() -> None: solc_select.switch_global_version("0.8.19", always_install=True) slither = Slither("./tests/ast-parsing/user_defined_operators-0.8.19.sol") From cc650f5683490342e38b92d6e681d44b07e706e5 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 10 Mar 2023 22:04:50 +0100 Subject: [PATCH 005/338] Black --- tests/test_features.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_features.py b/tests/test_features.py index c6b670d35..748f1df9e 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -203,6 +203,7 @@ def test_using_for_global_collision() -> None: sl = Slither(compilation) _run_all_detectors(sl) + # pylint: disable=too-many-branches def test_user_defined_operators() -> None: solc_select.switch_global_version("0.8.19", always_install=True) From 4b6dd02ac8072b7e8ff0f9401c29c808c27d6499 Mon Sep 17 00:00:00 2001 From: webthethird Date: Thu, 30 Mar 2023 16:06:38 -0500 Subject: [PATCH 006/338] Find contracts tainted by inheriting a tainted contract and functions that call tainted functions --- slither/utils/upgradeability.py | 38 +++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 947c4652a..1f5ef380c 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -204,6 +204,7 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon ) """ tainted_contracts = {} + tainted_list = [] for func in funcs: for contract, target in func.all_high_level_calls(): @@ -227,12 +228,10 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon and not (target.is_constant or target.is_immutable) ): tainted_contracts[contract.name]["variables"].append(target) - tainted_contracts = { - item - for item in tainted_contracts.items() - if len(item[1]["variables"]) > 0 and len(item[1]["functions"]) > 0 - } for c in tainted_contracts.items(): + if len(c[1]["functions"]) == 0 and len(c[1]["variables"]) == 0: + continue + tainted_list.append(c[1]) contract = c[1]["contract"] variables = c[1]["variables"] for var in variables: @@ -245,7 +244,34 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon f.is_constructor or f.is_fallback or f.is_receive ): tainted_contracts[contract.name]["functions"].append(f) - return list(tainted_contracts.values()) + return tainted_list + + +def tainted_inheriting_contracts( + tainted_contracts: List[TaintedExternalContract], + contracts: List[Contract] = None +) -> List[TaintedExternalContract]: + for tainted in tainted_contracts: + contract = tainted['contract'] + if contracts is None: + contracts = contract.compilation_unit.contracts + for c in contracts: + inheritance = [i.name for i in c.inheritance] + if contract.name in inheritance and c.name not in tainted_contracts: + new_taint = TaintedExternalContract( + contract=c, functions=[], variables=[] + ) + for f in c.functions_declared: + internal_calls = f.all_internal_calls() + if ( + any(str(call) == str(t) for t in tainted['functions'] for call in internal_calls) + or any(str(var) == str(t) for t in tainted['variables'] + for var in f.all_state_variables_read() + f.all_state_variables_written()) + ): + new_taint['functions'].append(f) + if len(new_taint['functions']) > 0: + tainted_contracts.append(new_taint) + return tainted_contracts def get_missing_vars(v1: Contract, v2: Contract) -> List[StateVariable]: From 0deff18d01e73783072ba7483efe713a2ad7f57c Mon Sep 17 00:00:00 2001 From: webthethird Date: Thu, 30 Mar 2023 16:16:23 -0500 Subject: [PATCH 007/338] Add docstring to `tainted_inheriting_contracts` --- slither/utils/upgradeability.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 1f5ef380c..8cf7595cf 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -251,6 +251,18 @@ def tainted_inheriting_contracts( tainted_contracts: List[TaintedExternalContract], contracts: List[Contract] = None ) -> List[TaintedExternalContract]: + """ + Takes a list of TaintedExternalContract obtained from tainted_external_contracts, and finds any contracts which + inherit a tainted contract, as well as any functions that call tainted functions or read tainted variables in + the inherited contract. + Args: + tainted_contracts: the list obtained from `tainted_external_contracts` or `compare`. + contracts: (optional) the list of contracts to check for inheritance. If not provided, defaults to + `contract.compilation_unit.contracts` for each contract in tainted_contracts. + + Returns: + An updated list of TaintedExternalContract, including all from the input list. + """ for tainted in tainted_contracts: contract = tainted['contract'] if contracts is None: From 5967958c71e58cc3fcd7cacecf162f8fb0916385 Mon Sep 17 00:00:00 2001 From: webthethird Date: Thu, 30 Mar 2023 16:18:27 -0500 Subject: [PATCH 008/338] Black --- slither/utils/upgradeability.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 8cf7595cf..2fa20f0f4 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -248,8 +248,7 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon def tainted_inheriting_contracts( - tainted_contracts: List[TaintedExternalContract], - contracts: List[Contract] = None + tainted_contracts: List[TaintedExternalContract], contracts: List[Contract] = None ) -> List[TaintedExternalContract]: """ Takes a list of TaintedExternalContract obtained from tainted_external_contracts, and finds any contracts which @@ -264,24 +263,24 @@ def tainted_inheriting_contracts( An updated list of TaintedExternalContract, including all from the input list. """ for tainted in tainted_contracts: - contract = tainted['contract'] + contract = tainted["contract"] if contracts is None: contracts = contract.compilation_unit.contracts for c in contracts: inheritance = [i.name for i in c.inheritance] if contract.name in inheritance and c.name not in tainted_contracts: - new_taint = TaintedExternalContract( - contract=c, functions=[], variables=[] - ) + new_taint = TaintedExternalContract(contract=c, functions=[], variables=[]) for f in c.functions_declared: internal_calls = f.all_internal_calls() - if ( - any(str(call) == str(t) for t in tainted['functions'] for call in internal_calls) - or any(str(var) == str(t) for t in tainted['variables'] - for var in f.all_state_variables_read() + f.all_state_variables_written()) + if any( + str(call) == str(t) for t in tainted["functions"] for call in internal_calls + ) or any( + str(var) == str(t) + for t in tainted["variables"] + for var in f.all_state_variables_read() + f.all_state_variables_written() ): - new_taint['functions'].append(f) - if len(new_taint['functions']) > 0: + new_taint["functions"].append(f) + if len(new_taint["functions"]) > 0: tainted_contracts.append(new_taint) return tainted_contracts From 675dbea4334386d2a343652483296ae8c30c08a1 Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 09:32:08 -0500 Subject: [PATCH 009/338] Get tainted variables in `tainted_inheriting_contracts` in addition to tainted functions --- slither/utils/upgradeability.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 2fa20f0f4..805da9905 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -280,7 +280,20 @@ def tainted_inheriting_contracts( for var in f.all_state_variables_read() + f.all_state_variables_written() ): new_taint["functions"].append(f) + for var in f.all_state_variables_read() + f.all_state_variables_written(): + if not (var in tainted["variables"] or var in new_taint["variables"]): + new_taint["variables"].append(var) if len(new_taint["functions"]) > 0: + for var in new_taint["variables"]: + read_write = set( + contract.get_functions_reading_from_variable(var) + + contract.get_functions_writing_to_variable(var) + ) + for f in read_write: + if f not in tainted["functions"] + new_taint["functions"] and not ( + f.is_constructor or f.is_fallback or f.is_receive + ): + new_taint["functions"].append(f) tainted_contracts.append(new_taint) return tainted_contracts From d88bba49856fe6a823aaf7855916751e2478b5b2 Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 09:38:25 -0500 Subject: [PATCH 010/338] Fix too many values to unpack in test_upgradeability_util.py --- tests/unit/utils/test_upgradeability_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index 7d6fb82da..a291d5680 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -22,7 +22,7 @@ def test_upgrades_compare() -> None: sl = Slither(os.path.join(TEST_DATA_DIR, "TestUpgrades-0.8.2.sol")) v1 = sl.get_contract_from_name("ContractV1")[0] v2 = sl.get_contract_from_name("ContractV2")[0] - missing_vars, new_vars, tainted_vars, new_funcs, modified_funcs, tainted_funcs = compare(v1, v2) + missing_vars, new_vars, tainted_vars, new_funcs, modified_funcs, tainted_funcs, tainted_contracts = compare(v1, v2) assert len(missing_vars) == 0 assert new_vars == [v2.get_state_variable_from_name("stateC")] assert tainted_vars == [ From cba0dc95111b85d0896e870531dc86255c9fd923 Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 10:13:07 -0500 Subject: [PATCH 011/338] Add python types --- slither/utils/upgradeability.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 805da9905..0bf01b373 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -203,8 +203,8 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon variables: List[Variable] ) """ - tainted_contracts = {} - tainted_list = [] + tainted_contracts: dict[str, TaintedExternalContract] = {} + tainted_list: list[TaintedExternalContract] = [] for func in funcs: for contract, target in func.all_high_level_calls(): From 386c3e14a36aa8007d0b911e46d622c89abe3f2e Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 10:31:43 -0500 Subject: [PATCH 012/338] Pylint and black --- slither/utils/upgradeability.py | 56 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 0bf01b373..1c2869da6 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -266,35 +266,39 @@ def tainted_inheriting_contracts( contract = tainted["contract"] if contracts is None: contracts = contract.compilation_unit.contracts + contracts = [ + c + for c in contracts + if c.name not in tainted_contracts and c.name in [i.name for i in c.inheritance] + ] for c in contracts: - inheritance = [i.name for i in c.inheritance] - if contract.name in inheritance and c.name not in tainted_contracts: - new_taint = TaintedExternalContract(contract=c, functions=[], variables=[]) - for f in c.functions_declared: - internal_calls = f.all_internal_calls() - if any( - str(call) == str(t) for t in tainted["functions"] for call in internal_calls - ) or any( - str(var) == str(t) - for t in tainted["variables"] - for var in f.all_state_variables_read() + f.all_state_variables_written() + new_taint = TaintedExternalContract(contract=c, functions=[], variables=[]) + for f in c.functions_declared: + internal_calls = f.all_internal_calls() + if any( + str(call) == str(t) for t in tainted["functions"] for call in internal_calls + ) or any( + str(var) == str(t) + for t in tainted["variables"] + for var in f.all_state_variables_read() + f.all_state_variables_written() + ): + new_taint["functions"].append(f) + for f in new_taint["functions"]: + for var in f.all_state_variables_read() + f.all_state_variables_written(): + if not (var in tainted["variables"] or var in new_taint["variables"]): + new_taint["variables"].append(var) + for var in new_taint["variables"]: + read_write = set( + contract.get_functions_reading_from_variable(var) + + contract.get_functions_writing_to_variable(var) + ) + for f in read_write: + if f not in tainted["functions"] + new_taint["functions"] and not ( + f.is_constructor or f.is_fallback or f.is_receive ): new_taint["functions"].append(f) - for var in f.all_state_variables_read() + f.all_state_variables_written(): - if not (var in tainted["variables"] or var in new_taint["variables"]): - new_taint["variables"].append(var) - if len(new_taint["functions"]) > 0: - for var in new_taint["variables"]: - read_write = set( - contract.get_functions_reading_from_variable(var) - + contract.get_functions_writing_to_variable(var) - ) - for f in read_write: - if f not in tainted["functions"] + new_taint["functions"] and not ( - f.is_constructor or f.is_fallback or f.is_receive - ): - new_taint["functions"].append(f) - tainted_contracts.append(new_taint) + if len(new_taint["functions"]) > 0: + tainted_contracts.append(new_taint) return tainted_contracts From 20f5825fb6bed64d15a2988c8423ebb226a3c143 Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 11:37:05 -0500 Subject: [PATCH 013/338] Pylint and black --- tests/unit/utils/test_upgradeability_util.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index a291d5680..8dfbccc61 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -22,8 +22,16 @@ def test_upgrades_compare() -> None: sl = Slither(os.path.join(TEST_DATA_DIR, "TestUpgrades-0.8.2.sol")) v1 = sl.get_contract_from_name("ContractV1")[0] v2 = sl.get_contract_from_name("ContractV2")[0] - missing_vars, new_vars, tainted_vars, new_funcs, modified_funcs, tainted_funcs, tainted_contracts = compare(v1, v2) - assert len(missing_vars) == 0 + ( + missing_vars, + new_vars, + tainted_vars, + new_funcs, + modified_funcs, + tainted_funcs, + tainted_contracts, + ) = compare(v1, v2) + assert len(missing_vars) == len(tainted_contracts) == 0 assert new_vars == [v2.get_state_variable_from_name("stateC")] assert tainted_vars == [ v2.get_state_variable_from_name("stateB"), From f585d2bb862a8e5a3046c1df3576cbdacacbaa1d Mon Sep 17 00:00:00 2001 From: webthethird Date: Fri, 31 Mar 2023 14:06:13 -0500 Subject: [PATCH 014/338] Add TODO --- slither/utils/upgradeability.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 1c2869da6..1e5b20a69 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -17,6 +17,7 @@ from slither.core.solidity_types import ( from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple from slither.core.variables.state_variable import StateVariable +from slither.slithir.variables import TemporaryVariable from slither.analyses.data_dependency.data_dependency import get_dependencies from slither.core.variables.variable import Variable from slither.core.expressions import ( @@ -208,6 +209,8 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon for func in funcs: for contract, target in func.all_high_level_calls(): + if contract.is_library: + continue if contract.name not in tainted_contracts: tainted_contracts[contract.name] = TaintedExternalContract( contract=contract, functions=[], variables=[] @@ -406,7 +409,7 @@ def encode_ir_for_compare(ir: Operation) -> str: if isinstance(ir, Assignment): return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" if isinstance(ir, Index): - return f"index({ntype(ir.index_type)})" + return f"index({ntype(ir.variable_right.type)})" if isinstance(ir, Member): return "member" # .format(ntype(ir._type)) if isinstance(ir, Length): @@ -531,6 +534,7 @@ def get_proxy_implementation_var(proxy: Contract) -> Optional[Variable]: try: delegate = next(var for var in dependencies if isinstance(var, StateVariable)) except StopIteration: + # TODO: Handle cases where get_dependencies doesn't return any state variables. return delegate return delegate From 2b330a198f71015fcd67e15401675ead04e9f288 Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 3 Apr 2023 14:01:44 -0500 Subject: [PATCH 015/338] Tweak how tainted variables are handled --- slither/utils/upgradeability.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 1e5b20a69..35921c843 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -129,7 +129,7 @@ def compare( new_modified_functions.append(function) new_functions.append(function) new_modified_function_vars += ( - function.state_variables_read + function.state_variables_written + function.all_state_variables_written() ) elif not function.is_constructor_variables and is_function_modified( orig_function, function @@ -137,7 +137,7 @@ def compare( new_modified_functions.append(function) modified_functions.append(function) new_modified_function_vars += ( - function.state_variables_read + function.state_variables_written + function.all_state_variables_written() ) # Find all unmodified functions that call a modified function or read/write the @@ -155,7 +155,7 @@ def compare( tainted_vars = [ var for var in set(new_modified_function_vars) - if var in function.variables_read_or_written + if var in function.all_state_variables_read() + function.all_state_variables_written() and not var.is_constant and not var.is_immutable ] @@ -166,7 +166,8 @@ def compare( for var in order_vars2: read_by = v2.get_functions_reading_from_variable(var) written_by = v2.get_functions_writing_to_variable(var) - if v1.get_state_variable_from_name(var.name) is None: + # if v1.get_state_variable_from_name(var.name) is None: + if next((v for v in v1.state_variables_ordered if v.name == var.name), None) is None: new_variables.append(var) elif any( func in read_by or func in written_by From da045d6db1d25767ae9658ace6a40e94588da074 Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:08:27 -0500 Subject: [PATCH 016/338] Make TaintedExternalContract a regular class and add TaintedFunction and TaintedVariable classes --- slither/utils/upgradeability.py | 182 +++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 47 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 35921c843..7316b480d 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -1,4 +1,4 @@ -from typing import Optional, Tuple, List, Union, TypedDict +from typing import Optional, Tuple, List, Union from slither.core.declarations import ( Contract, Structure, @@ -17,7 +17,6 @@ from slither.core.solidity_types import ( from slither.core.variables.local_variable import LocalVariable from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple from slither.core.variables.state_variable import StateVariable -from slither.slithir.variables import TemporaryVariable from slither.analyses.data_dependency.data_dependency import get_dependencies from slither.core.variables.variable import Variable from slither.core.expressions import ( @@ -64,10 +63,63 @@ from slither.slithir.variables import ( from slither.tools.read_storage.read_storage import SlotInfo, SlitherReadStorage -class TaintedExternalContract(TypedDict): - contract: Contract - functions: List[Function] - variables: List[Variable] +class TaintedFunction: + def __init__(self, f: "Function") -> None: + self._function: Function = f + self._tainted_by: List[Union[Function, StateVariable]] = [] + + @property + def function(self) -> Function: + return self._function + + @property + def tainted_by(self) -> List[Union[Function, StateVariable]]: + return self._tainted_by + + def add_tainted_by(self, f: Union[Function, StateVariable]): + self._tainted_by.append(f) + + +class TaintedVariable: + def __init__(self, v: "StateVariable") -> None: + self._variable: StateVariable = v + self._tainted_by: List[Function] = [] + + @property + def variable(self) -> StateVariable: + return self._variable + + @property + def tainted_by(self) -> List[Function]: + return self._tainted_by + + def add_tainted_by(self, f: Function): + self._tainted_by.append(f) + + +class TaintedExternalContract: + def __init__(self, contract: "Contract") -> None: + self._contract: Contract = contract + self._tainted_functions: List[TaintedFunction] = [] + self._tainted_variables: List[TaintedVariable] = [] + + @property + def contract(self) -> Contract: + return self._contract + + @property + def tainted_functions(self) -> List[TaintedFunction]: + return self._tainted_functions + + def add_tainted_function(self, f: TaintedFunction): + self._tainted_functions.append(f) + + @property + def tainted_variables(self) -> List[TaintedVariable]: + return self._tainted_variables + + def add_tainted_variable(self, v: TaintedVariable): + self._tainted_variables.append(v) # pylint: disable=too-many-locals @@ -128,17 +180,13 @@ def compare( if sig not in func_sigs1: new_modified_functions.append(function) new_functions.append(function) - new_modified_function_vars += ( - function.all_state_variables_written() - ) + new_modified_function_vars += function.all_state_variables_written() elif not function.is_constructor_variables and is_function_modified( orig_function, function ): new_modified_functions.append(function) modified_functions.append(function) - new_modified_function_vars += ( - function.all_state_variables_written() - ) + new_modified_function_vars += function.all_state_variables_written() # Find all unmodified functions that call a modified function or read/write the # same state variable(s) as a new/modified function, i.e., tainted functions @@ -213,41 +261,52 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon if contract.is_library: continue if contract.name not in tainted_contracts: - tainted_contracts[contract.name] = TaintedExternalContract( - contract=contract, functions=[], variables=[] - ) + tainted_contracts[contract.name] = TaintedExternalContract(contract) if ( isinstance(target, Function) and target not in funcs - and target not in tainted_contracts[contract.name]["functions"] + and target + not in (f.function for f in tainted_contracts[contract.name].tainted_functions) and not (target.is_constructor or target.is_fallback or target.is_receive) ): - tainted_contracts[contract.name]["functions"].append(target) + tainted_function = TaintedFunction(target) + tainted_function.add_tainted_by(func) + tainted_contracts[contract.name].add_tainted_function(tainted_function) for var in target.all_state_variables_written(): - if var not in tainted_contracts[contract.name]["variables"]: - tainted_contracts[contract.name]["variables"].append(var) + if var not in ( + v.variable for v in tainted_contracts[contract.name].tainted_variables + ): + tainted_var = TaintedVariable(var) + tainted_var.add_tainted_by(target) + tainted_contracts[contract.name].add_tainted_variable(tainted_var) elif ( - isinstance(target, Variable) - and target not in tainted_contracts[contract.name]["variables"] + isinstance(target, StateVariable) + and target + not in (v.variable for v in tainted_contracts[contract.name].tainted_variables) and not (target.is_constant or target.is_immutable) ): + tainted_var = TaintedVariable(target) + tainted_var.add_tainted_by(func) tainted_contracts[contract.name]["variables"].append(target) - for c in tainted_contracts.items(): - if len(c[1]["functions"]) == 0 and len(c[1]["variables"]) == 0: - continue - tainted_list.append(c[1]) - contract = c[1]["contract"] - variables = c[1]["variables"] + for c in tainted_contracts.values(): + # if len(c.tainted_functions) == 0 and len(c.tainted_variables) == 0: + # continue + tainted_list.append(c) + contract = c.contract + variables = c.tainted_variables for var in variables: + var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) + contract.get_functions_writing_to_variable(var) ) for f in read_write: - if f not in tainted_contracts[contract.name]["functions"] and not ( - f.is_constructor or f.is_fallback or f.is_receive - ): - tainted_contracts[contract.name]["functions"].append(f) + if f not in ( + t.function for t in tainted_contracts[contract.name].tainted_functions + ) and not (f.is_constructor or f.is_fallback or f.is_receive): + tainted_func = TaintedFunction(f) + tainted_func.add_tainted_by(var) + c.add_tainted_function(tainted_func) return tainted_list @@ -267,41 +326,70 @@ def tainted_inheriting_contracts( An updated list of TaintedExternalContract, including all from the input list. """ for tainted in tainted_contracts: - contract = tainted["contract"] + contract = tainted.contract if contracts is None: contracts = contract.compilation_unit.contracts contracts = [ c for c in contracts - if c.name not in tainted_contracts and c.name in [i.name for i in c.inheritance] + if c.name not in [t.contract.name for t in tainted_contracts] + and c.name in [i.name for i in c.inheritance] ] for c in contracts: - new_taint = TaintedExternalContract(contract=c, functions=[], variables=[]) + new_taint = TaintedExternalContract(c) for f in c.functions_declared: internal_calls = f.all_internal_calls() if any( - str(call) == str(t) for t in tainted["functions"] for call in internal_calls + call == t.function for t in tainted.tainted_functions for call in internal_calls ) or any( - str(var) == str(t) - for t in tainted["variables"] + var == t.variable + for t in tainted.tainted_variables for var in f.all_state_variables_read() + f.all_state_variables_written() ): - new_taint["functions"].append(f) - for f in new_taint["functions"]: + tainted_func = TaintedFunction(f) + tainted_by = next( + ( + t.function + for t in tainted.tainted_functions + for call in internal_calls + if str(call) == str(t.function) + ), + next( + ( + t.variable + for t in tainted.tainted_variables + for var in f.all_state_variables_read() + + f.all_state_variables_written() + if var == t.variable + ), + None, + ), + ) + tainted_func.add_tainted_by(tainted_by) + new_taint.add_tainted_function(tainted_func) + for f in new_taint.tainted_functions: + f = f.function for var in f.all_state_variables_read() + f.all_state_variables_written(): - if not (var in tainted["variables"] or var in new_taint["variables"]): - new_taint["variables"].append(var) - for var in new_taint["variables"]: + if var not in ( + v.variable for v in tainted.tainted_variables + new_taint.tainted_variables + ): + tainted_var = TaintedVariable(var) + tainted_var.add_tainted_by(f) + new_taint.add_tainted_variable(tainted_var) + for var in new_taint.tainted_variables: + var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) + contract.get_functions_writing_to_variable(var) ) for f in read_write: - if f not in tainted["functions"] + new_taint["functions"] and not ( - f.is_constructor or f.is_fallback or f.is_receive - ): - new_taint["functions"].append(f) - if len(new_taint["functions"]) > 0: + if f not in ( + t.function for t in tainted.tainted_functions + new_taint.tainted_functions + ) and not (f.is_constructor or f.is_fallback or f.is_receive): + tainted_func = TaintedFunction(f) + tainted_func.add_tainted_by(var) + new_taint.add_tainted_function(tainted_func) + if len(new_taint.tainted_functions) > 0: tainted_contracts.append(new_taint) return tainted_contracts From d1b34b64e70da0ce3904408664a91dc02f206d53 Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:09:46 -0500 Subject: [PATCH 017/338] Avoid string comparison --- slither/utils/upgradeability.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 7316b480d..df782ef6f 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -352,7 +352,7 @@ def tainted_inheriting_contracts( t.function for t in tainted.tainted_functions for call in internal_calls - if str(call) == str(t.function) + if call == t.function ), next( ( From 85c22f491e56f7aaa15d69606000e89bc6c0271b Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:22:30 -0500 Subject: [PATCH 018/338] Avoid re-defining `contracts` in `tainted_inheriting_contracts` --- slither/utils/upgradeability.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index df782ef6f..3be47676a 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -327,15 +327,16 @@ def tainted_inheriting_contracts( """ for tainted in tainted_contracts: contract = tainted.contract + check_contracts = contracts if contracts is None: - contracts = contract.compilation_unit.contracts - contracts = [ + check_contracts = contract.compilation_unit.contracts + check_contracts = [ c - for c in contracts + for c in check_contracts if c.name not in [t.contract.name for t in tainted_contracts] and c.name in [i.name for i in c.inheritance] ] - for c in contracts: + for c in check_contracts: new_taint = TaintedExternalContract(c) for f in c.functions_declared: internal_calls = f.all_internal_calls() From 38acd93bd2f03d2885343847e534709736343b48 Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:31:02 -0500 Subject: [PATCH 019/338] Add inline comments --- slither/utils/upgradeability.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 3be47676a..568cb7195 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -247,10 +247,10 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon funcs: a list of Function objects to search for external calls. Returns: - TaintedExternalContract(TypedDict) ( + TaintedExternalContract() ( contract: Contract, - functions: List[Function], - variables: List[Variable] + tainted_functions: List[TaintedFunction], + tainted_variables: List[TaintedVariable] ) """ tainted_contracts: dict[str, TaintedExternalContract] = {} @@ -259,8 +259,10 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon for func in funcs: for contract, target in func.all_high_level_calls(): if contract.is_library: + # Not interested in library calls continue if contract.name not in tainted_contracts: + # A contract may be tainted by multiple function calls - only make one TaintedExternalContract object tainted_contracts[contract.name] = TaintedExternalContract(contract) if ( isinstance(target, Function) @@ -269,10 +271,12 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon not in (f.function for f in tainted_contracts[contract.name].tainted_functions) and not (target.is_constructor or target.is_fallback or target.is_receive) ): + # Found a high-level call to a new tainted function tainted_function = TaintedFunction(target) tainted_function.add_tainted_by(func) tainted_contracts[contract.name].add_tainted_function(tainted_function) for var in target.all_state_variables_written(): + # Consider as tainted all variables written by the tainted function if var not in ( v.variable for v in tainted_contracts[contract.name].tainted_variables ): @@ -285,16 +289,16 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon not in (v.variable for v in tainted_contracts[contract.name].tainted_variables) and not (target.is_constant or target.is_immutable) ): + # Found a new high-level call to a public state variable getter tainted_var = TaintedVariable(target) tainted_var.add_tainted_by(func) tainted_contracts[contract.name]["variables"].append(target) for c in tainted_contracts.values(): - # if len(c.tainted_functions) == 0 and len(c.tainted_variables) == 0: - # continue tainted_list.append(c) contract = c.contract variables = c.tainted_variables for var in variables: + # For each tainted variable, consider as tainted any function that reads or writes to it var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) @@ -330,6 +334,7 @@ def tainted_inheriting_contracts( check_contracts = contracts if contracts is None: check_contracts = contract.compilation_unit.contracts + # We are only interested in checking contracts that inherit a tainted contract check_contracts = [ c for c in check_contracts @@ -339,6 +344,7 @@ def tainted_inheriting_contracts( for c in check_contracts: new_taint = TaintedExternalContract(c) for f in c.functions_declared: + # Search for functions that call an inherited tainted function or access an inherited tainted variable internal_calls = f.all_internal_calls() if any( call == t.function for t in tainted.tainted_functions for call in internal_calls @@ -348,6 +354,7 @@ def tainted_inheriting_contracts( for var in f.all_state_variables_read() + f.all_state_variables_written() ): tainted_func = TaintedFunction(f) + # Given that at least one of the `any` conditions was met, find which one is the taint source tainted_by = next( ( t.function @@ -369,8 +376,9 @@ def tainted_inheriting_contracts( tainted_func.add_tainted_by(tainted_by) new_taint.add_tainted_function(tainted_func) for f in new_taint.tainted_functions: + # For each newly found tainted function, consider as tainted any variable it writes to f = f.function - for var in f.all_state_variables_read() + f.all_state_variables_written(): + for var in f.all_state_variables_written(): if var not in ( v.variable for v in tainted.tainted_variables + new_taint.tainted_variables ): @@ -378,6 +386,7 @@ def tainted_inheriting_contracts( tainted_var.add_tainted_by(f) new_taint.add_tainted_variable(tainted_var) for var in new_taint.tainted_variables: + # For each newly found tainted variable, consider as tainted any function that reads or writes to it var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) From 98a5cf012d1eff1896ac28017c7eabbe5e696d0d Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:33:58 -0500 Subject: [PATCH 020/338] Use canonical_name in comparisons --- slither/utils/upgradeability.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 568cb7195..6351eb6cb 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -347,9 +347,11 @@ def tainted_inheriting_contracts( # Search for functions that call an inherited tainted function or access an inherited tainted variable internal_calls = f.all_internal_calls() if any( - call == t.function for t in tainted.tainted_functions for call in internal_calls + call.canonical_name == t.function.canonical_name + for t in tainted.tainted_functions + for call in internal_calls ) or any( - var == t.variable + var.canonical_name == t.variable.canonical_name for t in tainted.tainted_variables for var in f.all_state_variables_read() + f.all_state_variables_written() ): @@ -360,7 +362,7 @@ def tainted_inheriting_contracts( t.function for t in tainted.tainted_functions for call in internal_calls - if call == t.function + if call.canonical_name == t.function.canonical_name ), next( ( @@ -368,7 +370,7 @@ def tainted_inheriting_contracts( for t in tainted.tainted_variables for var in f.all_state_variables_read() + f.all_state_variables_written() - if var == t.variable + if var.canonical_name == t.variable.canonical_name ), None, ), From 1e7397965a523fd14eb4a270d4634e037acd3c0a Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 12:50:41 -0500 Subject: [PATCH 021/338] Fix expected tainted funcs, since we changed what's considered tainted --- tests/unit/utils/test_upgradeability_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index 8dfbccc61..88adcf00f 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -40,7 +40,6 @@ def test_upgrades_compare() -> None: assert new_funcs == [v2.get_function_from_signature("i()")] assert modified_funcs == [v2.get_function_from_signature("checkB()")] assert tainted_funcs == [ - v2.get_function_from_signature("g(uint256)"), v2.get_function_from_signature("h()"), ] From 178960f655d35dfde99d1c1a7e8e2b5521dfbfd1 Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 15:09:54 -0500 Subject: [PATCH 022/338] Simplify by removing `TaintedFunction` and `TaintedVariable` classes --- slither/utils/upgradeability.py | 120 +++++++------------------------- 1 file changed, 25 insertions(+), 95 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 6351eb6cb..2a8347ddb 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -63,62 +63,28 @@ from slither.slithir.variables import ( from slither.tools.read_storage.read_storage import SlotInfo, SlitherReadStorage -class TaintedFunction: - def __init__(self, f: "Function") -> None: - self._function: Function = f - self._tainted_by: List[Union[Function, StateVariable]] = [] - - @property - def function(self) -> Function: - return self._function - - @property - def tainted_by(self) -> List[Union[Function, StateVariable]]: - return self._tainted_by - - def add_tainted_by(self, f: Union[Function, StateVariable]): - self._tainted_by.append(f) - - -class TaintedVariable: - def __init__(self, v: "StateVariable") -> None: - self._variable: StateVariable = v - self._tainted_by: List[Function] = [] - - @property - def variable(self) -> StateVariable: - return self._variable - - @property - def tainted_by(self) -> List[Function]: - return self._tainted_by - - def add_tainted_by(self, f: Function): - self._tainted_by.append(f) - - class TaintedExternalContract: def __init__(self, contract: "Contract") -> None: self._contract: Contract = contract - self._tainted_functions: List[TaintedFunction] = [] - self._tainted_variables: List[TaintedVariable] = [] + self._tainted_functions: List[Function] = [] + self._tainted_variables: List[Variable] = [] @property def contract(self) -> Contract: return self._contract @property - def tainted_functions(self) -> List[TaintedFunction]: + def tainted_functions(self) -> List[Function]: return self._tainted_functions - def add_tainted_function(self, f: TaintedFunction): + def add_tainted_function(self, f: Function): self._tainted_functions.append(f) @property - def tainted_variables(self) -> List[TaintedVariable]: + def tainted_variables(self) -> List[Variable]: return self._tainted_variables - def add_tainted_variable(self, v: TaintedVariable): + def add_tainted_variable(self, v: Variable): self._tainted_variables.append(v) @@ -268,49 +234,40 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon isinstance(target, Function) and target not in funcs and target - not in (f.function for f in tainted_contracts[contract.name].tainted_functions) + not in (f for f in tainted_contracts[contract.name].tainted_functions) and not (target.is_constructor or target.is_fallback or target.is_receive) ): # Found a high-level call to a new tainted function - tainted_function = TaintedFunction(target) - tainted_function.add_tainted_by(func) - tainted_contracts[contract.name].add_tainted_function(tainted_function) + tainted_contracts[contract.name].add_tainted_function(target) for var in target.all_state_variables_written(): # Consider as tainted all variables written by the tainted function if var not in ( - v.variable for v in tainted_contracts[contract.name].tainted_variables + v for v in tainted_contracts[contract.name].tainted_variables ): - tainted_var = TaintedVariable(var) - tainted_var.add_tainted_by(target) - tainted_contracts[contract.name].add_tainted_variable(tainted_var) + tainted_contracts[contract.name].add_tainted_variable(var) elif ( isinstance(target, StateVariable) - and target - not in (v.variable for v in tainted_contracts[contract.name].tainted_variables) + and target not in (v for v in tainted_contracts[contract.name].tainted_variables) and not (target.is_constant or target.is_immutable) ): # Found a new high-level call to a public state variable getter - tainted_var = TaintedVariable(target) - tainted_var.add_tainted_by(func) - tainted_contracts[contract.name]["variables"].append(target) + tainted_contracts[contract.name].add_tainted_variable(target) for c in tainted_contracts.values(): tainted_list.append(c) contract = c.contract variables = c.tainted_variables for var in variables: # For each tainted variable, consider as tainted any function that reads or writes to it - var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) + contract.get_functions_writing_to_variable(var) ) for f in read_write: - if f not in ( - t.function for t in tainted_contracts[contract.name].tainted_functions - ) and not (f.is_constructor or f.is_fallback or f.is_receive): - tainted_func = TaintedFunction(f) - tainted_func.add_tainted_by(var) - c.add_tainted_function(tainted_func) + if ( + f not in tainted_contracts[contract.name].tainted_functions + and not (f.is_constructor or f.is_fallback or f.is_receive) + ): + c.add_tainted_function(f) return tainted_list @@ -339,7 +296,7 @@ def tainted_inheriting_contracts( c for c in check_contracts if c.name not in [t.contract.name for t in tainted_contracts] - and c.name in [i.name for i in c.inheritance] + and contract.name in [i.name for i in c.inheritance] ] for c in check_contracts: new_taint = TaintedExternalContract(c) @@ -347,60 +304,33 @@ def tainted_inheriting_contracts( # Search for functions that call an inherited tainted function or access an inherited tainted variable internal_calls = f.all_internal_calls() if any( - call.canonical_name == t.function.canonical_name + call.canonical_name == t.canonical_name for t in tainted.tainted_functions for call in internal_calls ) or any( - var.canonical_name == t.variable.canonical_name + var.canonical_name == t.canonical_name for t in tainted.tainted_variables for var in f.all_state_variables_read() + f.all_state_variables_written() ): - tainted_func = TaintedFunction(f) - # Given that at least one of the `any` conditions was met, find which one is the taint source - tainted_by = next( - ( - t.function - for t in tainted.tainted_functions - for call in internal_calls - if call.canonical_name == t.function.canonical_name - ), - next( - ( - t.variable - for t in tainted.tainted_variables - for var in f.all_state_variables_read() - + f.all_state_variables_written() - if var.canonical_name == t.variable.canonical_name - ), - None, - ), - ) - tainted_func.add_tainted_by(tainted_by) - new_taint.add_tainted_function(tainted_func) + new_taint.add_tainted_function(f) for f in new_taint.tainted_functions: # For each newly found tainted function, consider as tainted any variable it writes to - f = f.function for var in f.all_state_variables_written(): if var not in ( - v.variable for v in tainted.tainted_variables + new_taint.tainted_variables + v for v in tainted.tainted_variables + new_taint.tainted_variables ): - tainted_var = TaintedVariable(var) - tainted_var.add_tainted_by(f) - new_taint.add_tainted_variable(tainted_var) + new_taint.add_tainted_variable(var) for var in new_taint.tainted_variables: # For each newly found tainted variable, consider as tainted any function that reads or writes to it - var = var.variable read_write = set( contract.get_functions_reading_from_variable(var) + contract.get_functions_writing_to_variable(var) ) for f in read_write: if f not in ( - t.function for t in tainted.tainted_functions + new_taint.tainted_functions + t for t in tainted.tainted_functions + new_taint.tainted_functions ) and not (f.is_constructor or f.is_fallback or f.is_receive): - tainted_func = TaintedFunction(f) - tainted_func.add_tainted_by(var) - new_taint.add_tainted_function(tainted_func) + new_taint.add_tainted_function(f) if len(new_taint.tainted_functions) > 0: tainted_contracts.append(new_taint) return tainted_contracts From 3bcefac1c87d9b4fbead106ca25f8ed115b720f7 Mon Sep 17 00:00:00 2001 From: webthethird Date: Tue, 4 Apr 2023 15:10:19 -0500 Subject: [PATCH 023/338] Black --- slither/utils/upgradeability.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 2a8347ddb..29edfec0f 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -233,17 +233,14 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon if ( isinstance(target, Function) and target not in funcs - and target - not in (f for f in tainted_contracts[contract.name].tainted_functions) + and target not in (f for f in tainted_contracts[contract.name].tainted_functions) and not (target.is_constructor or target.is_fallback or target.is_receive) ): # Found a high-level call to a new tainted function tainted_contracts[contract.name].add_tainted_function(target) for var in target.all_state_variables_written(): # Consider as tainted all variables written by the tainted function - if var not in ( - v for v in tainted_contracts[contract.name].tainted_variables - ): + if var not in (v for v in tainted_contracts[contract.name].tainted_variables): tainted_contracts[contract.name].add_tainted_variable(var) elif ( isinstance(target, StateVariable) @@ -263,9 +260,8 @@ def tainted_external_contracts(funcs: List[Function]) -> List[TaintedExternalCon + contract.get_functions_writing_to_variable(var) ) for f in read_write: - if ( - f not in tainted_contracts[contract.name].tainted_functions - and not (f.is_constructor or f.is_fallback or f.is_receive) + if f not in tainted_contracts[contract.name].tainted_functions and not ( + f.is_constructor or f.is_fallback or f.is_receive ): c.add_tainted_function(f) return tainted_list From de311b5ab57e7affec6d262c4db457a144ed903e Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 6 Apr 2023 18:50:59 +0200 Subject: [PATCH 024/338] Improve echidna printer perf --- slither/core/slither_core.py | 2 + slither/printers/guidance/echidna.py | 80 ++++++++++--------- slither/slither.py | 7 +- .../slither_compilation_unit_solc.py | 4 +- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 798008707..29db9f23a 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -96,6 +96,8 @@ class SlitherCore(Context): # If true, partial analysis is allowed self.no_fail = False + self.skip_data_dependency = False + @property def compilation_units(self) -> List[SlitherCompilationUnit]: return list(self._compilation_units) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index acbf5b015..60fcd6b0f 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -1,4 +1,5 @@ import json +import re from collections import defaultdict from typing import Dict, List, Set, Tuple, NamedTuple, Union @@ -43,9 +44,9 @@ def _get_name(f: Union[Function, Variable]) -> str: return f.solidity_signature -def _extract_payable(slither: SlitherCore) -> Dict[str, List[str]]: +def _extract_payable(contracts) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} - for contract in slither.contracts: + for contract in contracts: payable_functions = [_get_name(f) for f in contract.functions_entry_points if f.payable] if payable_functions: ret[contract.name] = payable_functions @@ -53,10 +54,10 @@ def _extract_payable(slither: SlitherCore) -> Dict[str, List[str]]: def _extract_solidity_variable_usage( - slither: SlitherCore, sol_var: SolidityVariable + contracts, sol_var: SolidityVariable ) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} - for contract in slither.contracts: + for contract in contracts: functions_using_sol_var = [] for f in contract.functions_entry_points: for v in f.all_solidity_variables_read(): @@ -114,9 +115,9 @@ def _is_constant(f: Function) -> bool: # pylint: disable=too-many-branches return True -def _extract_constant_functions(slither: SlitherCore) -> Dict[str, List[str]]: +def _extract_constant_functions(contracts) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} - for contract in slither.contracts: + for contract in contracts: cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)] cst_functions += [ v.solidity_signature for v in contract.state_variables if v.visibility in ["public"] @@ -126,9 +127,9 @@ def _extract_constant_functions(slither: SlitherCore) -> Dict[str, List[str]]: return ret -def _extract_assert(slither: SlitherCore) -> Dict[str, List[str]]: +def _extract_assert(contracts) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} - for contract in slither.contracts: + for contract in contracts: functions_using_assert = [] for f in contract.functions_entry_points: for v in f.all_solidity_calls(): @@ -223,13 +224,13 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n def _extract_constants( - slither: SlitherCore, + contracts, ) -> Tuple[Dict[str, Dict[str, List]], Dict[str, Dict[str, Dict]]]: # contract -> function -> [ {"value": value, "type": type} ] ret_cst_used: Dict[str, Dict[str, List[ConstantValue]]] = defaultdict(dict) # contract -> function -> binary_operand -> [ {"value": value, "type": type ] ret_cst_used_in_binary: Dict[str, Dict[str, Dict[str, List[ConstantValue]]]] = defaultdict(dict) - for contract in slither.contracts: + for contract in contracts: for function in contract.functions_entry_points: all_cst_used: List = [] all_cst_used_in_binary: Dict = defaultdict(list) @@ -255,11 +256,11 @@ def _extract_constants( def _extract_function_relations( - slither: SlitherCore, + contracts, ) -> Dict[str, Dict[str, Dict[str, List[str]]]]: # contract -> function -> [functions] ret: Dict[str, Dict[str, Dict[str, List[str]]]] = defaultdict(dict) - for contract in slither.contracts: + for contract in contracts: ret[contract.name] = defaultdict(dict) written = { _get_name(function): function.all_state_variables_written() @@ -283,14 +284,14 @@ def _extract_function_relations( return ret -def _have_external_calls(slither: SlitherCore) -> Dict[str, List[str]]: +def _have_external_calls(contracts) -> Dict[str, List[str]]: """ Detect the functions with external calls :param slither: :return: """ ret: Dict[str, List[str]] = defaultdict(list) - for contract in slither.contracts: + for contract in contracts: for function in contract.functions_entry_points: if function.all_high_level_calls() or function.all_low_level_calls(): ret[contract.name].append(_get_name(function)) @@ -299,14 +300,14 @@ def _have_external_calls(slither: SlitherCore) -> Dict[str, List[str]]: return ret -def _use_balance(slither: SlitherCore) -> Dict[str, List[str]]: +def _use_balance(contracts) -> Dict[str, List[str]]: """ Detect the functions with external calls :param slither: :return: """ ret: Dict[str, List[str]] = defaultdict(list) - for contract in slither.contracts: + for contract in contracts: for function in contract.functions_entry_points: for ir in function.all_slithir_operations(): if isinstance(ir, SolidityCall) and ir.function == SolidityFunction( @@ -318,25 +319,25 @@ def _use_balance(slither: SlitherCore) -> Dict[str, List[str]]: return ret -def _with_fallback(slither: SlitherCore) -> Set[str]: +def _with_fallback(contracts) -> Set[str]: ret: Set[str] = set() - for contract in slither.contracts: + for contract in contracts: for function in contract.functions_entry_points: if function.is_fallback: ret.add(contract.name) return ret -def _with_receive(slither: SlitherCore) -> Set[str]: +def _with_receive(contracts) -> Set[str]: ret: Set[str] = set() - for contract in slither.contracts: + for contract in contracts: for function in contract.functions_entry_points: if function.is_receive: ret.add(contract.name) return ret -def _call_a_parameter(slither: SlitherCore) -> Dict[str, List[Dict]]: +def _call_a_parameter(slither: SlitherCore, contracts) -> Dict[str, List[Dict]]: """ Detect the functions with external calls :param slither: @@ -344,7 +345,7 @@ def _call_a_parameter(slither: SlitherCore) -> Dict[str, List[Dict]]: """ # contract -> [ (function, idx, interface_called) ] ret: Dict[str, List[Dict]] = defaultdict(list) - for contract in slither.contracts: # pylint: disable=too-many-nested-blocks + for contract in contracts: # pylint: disable=too-many-nested-blocks for function in contract.functions_entry_points: try: for ir in function.all_slithir_operations(): @@ -390,40 +391,43 @@ class Echidna(AbstractPrinter): _filename(string) """ - payable = _extract_payable(self.slither) + filter = r"mock(s)?|test(s)?" + contracts = [c for c in self.slither.contracts if not re.search(filter, c.file_scope.filename.absolute, re.IGNORECASE)] + + payable = _extract_payable(contracts) timestamp = _extract_solidity_variable_usage( - self.slither, SolidityVariableComposed("block.timestamp") + contracts, SolidityVariableComposed("block.timestamp") ) block_number = _extract_solidity_variable_usage( - self.slither, SolidityVariableComposed("block.number") + contracts, SolidityVariableComposed("block.number") ) msg_sender = _extract_solidity_variable_usage( - self.slither, SolidityVariableComposed("msg.sender") + contracts, SolidityVariableComposed("msg.sender") ) msg_gas = _extract_solidity_variable_usage( - self.slither, SolidityVariableComposed("msg.gas") + contracts, SolidityVariableComposed("msg.gas") ) - assert_usage = _extract_assert(self.slither) - cst_functions = _extract_constant_functions(self.slither) - (cst_used, cst_used_in_binary) = _extract_constants(self.slither) + assert_usage = _extract_assert(contracts) + cst_functions = _extract_constant_functions(contracts) + (cst_used, cst_used_in_binary) = _extract_constants(contracts) - functions_relations = _extract_function_relations(self.slither) + functions_relations = _extract_function_relations(contracts) constructors = { contract.name: contract.constructor.full_name - for contract in self.slither.contracts + for contract in contracts if contract.constructor } - external_calls = _have_external_calls(self.slither) + external_calls = _have_external_calls(contracts) - call_parameters = _call_a_parameter(self.slither) + #call_parameters = _call_a_parameter(self.slither, contracts) - use_balance = _use_balance(self.slither) + use_balance = _use_balance(contracts) - with_fallback = list(_with_fallback(self.slither)) + with_fallback = list(_with_fallback(contracts)) - with_receive = list(_with_receive(self.slither)) + with_receive = list(_with_receive(contracts)) d = { "payable": payable, @@ -438,7 +442,7 @@ class Echidna(AbstractPrinter): "functions_relations": functions_relations, "constructors": constructors, "have_external_calls": external_calls, - "call_a_parameter": call_parameters, + #"call_a_parameter": call_parameters, "use_balance": use_balance, "solc_versions": [unit.solc_version for unit in self.slither.compilation_units], "with_fallback": with_fallback, diff --git a/slither/slither.py b/slither/slither.py index 85f852e1d..ca0df5f71 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -132,7 +132,12 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes triage_mode = kwargs.get("triage_mode", False) self._triage_mode = triage_mode - self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) + + printers_to_run = kwargs.get("printers_to_run", "") + if printers_to_run == "echidna": + self.skip_data_dependency = True + + self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index b1c2387f0..bdbd0bb94 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -526,8 +526,8 @@ Please rename it, this name is reserved for Slither's internals""" if not self._parsed: raise SlitherException("Parse the contract before running analyses") self._convert_to_slithir() - - compute_dependency(self._compilation_unit) + if not self._compilation_unit.core.skip_data_dependency: + compute_dependency(self._compilation_unit) self._compilation_unit.compute_storage_layout() self._analyzed = True From ae7f0b2f052afbbde1684d988d636936105e84fe Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 10 Apr 2023 11:47:56 -0500 Subject: [PATCH 025/338] Only check internal calls to Functions --- slither/utils/upgradeability.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 29edfec0f..1bff3c153 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -298,7 +298,7 @@ def tainted_inheriting_contracts( new_taint = TaintedExternalContract(c) for f in c.functions_declared: # Search for functions that call an inherited tainted function or access an inherited tainted variable - internal_calls = f.all_internal_calls() + internal_calls = [c for c in f.all_internal_calls() if isinstance(c, Function)] if any( call.canonical_name == t.canonical_name for t in tainted.tainted_functions From ca82da060358664b79b197d1446209cde584590c Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 17 Apr 2023 12:32:02 -0500 Subject: [PATCH 026/338] Update compare docstring --- slither/utils/upgradeability.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 1bff3c153..b6915b4f2 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -115,6 +115,7 @@ def compare( new-functions: list[Function], modified-functions: list[Function], tainted-functions: list[Function] + tainted-contracts: list[TaintedExternalContract] """ order_vars1 = [ From 853051ebf473fa77dfb1029170c5f034ad02ea99 Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 17 Apr 2023 13:53:05 -0500 Subject: [PATCH 027/338] Reduce tainted variables to only written --- slither/utils/upgradeability.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index b6915b4f2..516855130 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -177,15 +177,13 @@ def compare( if len(modified_calls) > 0 or len(tainted_vars) > 0: tainted_functions.append(function) - # Find all new or tainted variables, i.e., variables that are read or written by a new/modified/tainted function + # Find all new or tainted variables, i.e., variables that are written by a new/modified/tainted function for var in order_vars2: - read_by = v2.get_functions_reading_from_variable(var) written_by = v2.get_functions_writing_to_variable(var) - # if v1.get_state_variable_from_name(var.name) is None: if next((v for v in v1.state_variables_ordered if v.name == var.name), None) is None: new_variables.append(var) elif any( - func in read_by or func in written_by + func in written_by for func in new_modified_functions + tainted_functions ): tainted_variables.append(var) From 823337e45db37cc6de39c452b2898ba0b1748948 Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 17 Apr 2023 14:07:34 -0500 Subject: [PATCH 028/338] Update test --- tests/unit/utils/test_upgradeability_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index 88adcf00f..7a2931d52 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -34,7 +34,6 @@ def test_upgrades_compare() -> None: assert len(missing_vars) == len(tainted_contracts) == 0 assert new_vars == [v2.get_state_variable_from_name("stateC")] assert tainted_vars == [ - v2.get_state_variable_from_name("stateB"), v2.get_state_variable_from_name("bug"), ] assert new_funcs == [v2.get_function_from_signature("i()")] From 6ccc8cfee763448aa15c4ba10aaf093420479553 Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 17 Apr 2023 14:07:42 -0500 Subject: [PATCH 029/338] Black --- slither/utils/upgradeability.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 516855130..5be745bd6 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -182,10 +182,7 @@ def compare( written_by = v2.get_functions_writing_to_variable(var) if next((v for v in v1.state_variables_ordered if v.name == var.name), None) is None: new_variables.append(var) - elif any( - func in written_by - for func in new_modified_functions + tainted_functions - ): + elif any(func in written_by for func in new_modified_functions + tainted_functions): tainted_variables.append(var) # Find all external contracts and functions called by new/modified/tainted functions From ef2eadc1c412222f815fee2326b51b17062b3019 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 19 Apr 2023 15:24:42 -0500 Subject: [PATCH 030/338] Update test_upgrades_compare to test cross-contract taint --- .../upgradeability_util/src/ContractV2.sol | 5 + .../upgradeability_util/src/ERC20.sol | 376 ++++++++++++++++++ tests/unit/utils/test_upgradeability_util.py | 20 +- 3 files changed, 399 insertions(+), 2 deletions(-) create mode 100644 tests/unit/utils/test_data/upgradeability_util/src/ERC20.sol diff --git a/tests/unit/utils/test_data/upgradeability_util/src/ContractV2.sol b/tests/unit/utils/test_data/upgradeability_util/src/ContractV2.sol index 9b102f3e9..9c508caf3 100644 --- a/tests/unit/utils/test_data/upgradeability_util/src/ContractV2.sol +++ b/tests/unit/utils/test_data/upgradeability_util/src/ContractV2.sol @@ -1,6 +1,7 @@ pragma solidity ^0.8.2; import "./ProxyStorage.sol"; +import "./ERC20.sol"; contract ContractV2 is ProxyStorage { uint private stateA = 0; @@ -38,4 +39,8 @@ contract ContractV2 is ProxyStorage { function checkB() internal returns (bool) { return stateB == 32; } + + function erc20Transfer(address erc20, address to, uint256 amount) public returns (bool) { + return ERC20(erc20).transfer(to, amount); + } } diff --git a/tests/unit/utils/test_data/upgradeability_util/src/ERC20.sol b/tests/unit/utils/test_data/upgradeability_util/src/ERC20.sol new file mode 100644 index 000000000..6c7801581 --- /dev/null +++ b/tests/unit/utils/test_data/upgradeability_util/src/ERC20.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20 { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address to, uint256 amount) public virtual returns (bool) { + address owner = msg.sender; + _transfer(owner, to, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual returns (bool) { + address owner = msg.sender; + _approve(owner, spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + * - the caller must have allowance for ``from``'s tokens of at least + * `amount`. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual returns (bool) { + address spender = msg.sender; + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + address owner = msg.sender; + _approve(owner, spender, allowance(owner, spender) + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + address owner = msg.sender; + uint256 currentAllowance = allowance(owner, spender); + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer( + address from, + address to, + uint256 amount + ) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(from, to, amount); + + uint256 fromBalance = _balances[from]; + require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[from] = fromBalance - amount; + // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by + // decrementing then incrementing. + _balances[to] += amount; + } + _afterTokenTransfer(from, to, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + unchecked { + // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. + _balances[account] += amount; + } + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + // Overflow not possible: amount <= accountBalance <= totalSupply. + _totalSupply -= amount; + } + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance amount in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Might emit an {Approval} event. + */ + function _spendAllowance( + address owner, + address spender, + uint256 amount + ) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} +} diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index 7a2931d52..e367a3eed 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -31,16 +31,32 @@ def test_upgrades_compare() -> None: tainted_funcs, tainted_contracts, ) = compare(v1, v2) - assert len(missing_vars) == len(tainted_contracts) == 0 + assert len(missing_vars) == 0 assert new_vars == [v2.get_state_variable_from_name("stateC")] assert tainted_vars == [ v2.get_state_variable_from_name("bug"), ] - assert new_funcs == [v2.get_function_from_signature("i()")] + assert new_funcs == [ + v2.get_function_from_signature("i()"), + v2.get_function_from_signature("erc20Transfer(address,address,uint256)"), + ] assert modified_funcs == [v2.get_function_from_signature("checkB()")] assert tainted_funcs == [ v2.get_function_from_signature("h()"), ] + erc20 = sl.get_contract_from_name("ERC20")[0] + assert len(tainted_contracts) == 1 + assert tainted_contracts[0].contract == erc20 + assert set(tainted_contracts[0].tainted_functions) == { + erc20.get_function_from_signature("transfer(address,uint256)"), + erc20.get_function_from_signature("_transfer(address,address,uint256)"), + erc20.get_function_from_signature("_burn(address,uint256)"), + erc20.get_function_from_signature("balanceOf(address)"), + erc20.get_function_from_signature("_mint(address,uint256)"), + } + assert tainted_contracts[0].tainted_variables == [ + erc20.get_state_variable_from_name("_balances") + ] def test_upgrades_implementation_var() -> None: From b26f8da1248e7f57119e76f5dc89014cd46272e8 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 24 Apr 2023 21:23:08 +0200 Subject: [PATCH 031/338] Improve try-catch parsing --- slither/solc_parsing/declarations/function.py | 76 +++++++++++++++++-- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 7438a7bb0..ab5d289a8 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -660,6 +660,55 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node_condition, node_endDoWhile) return node_endDoWhile + # pylint: disable=no-self-use + def _construct_try_expression(self, externalCall: Dict, parameters_list: Dict) -> Dict: + # if the parameters are more than 1 we make the leftHandSide of the Assignment node + # a TupleExpression otherwise an Identifier + + ret: Dict = {"nodeType": "Assignment", "operator": "=", "src": parameters_list["src"]} + + parameters = parameters_list.get("parameters", None) + + # if the name is "" it means the return variable is not used + if len(parameters) == 1: + if parameters[0]["name"] != "": + ret["typeDescriptions"] = { + "typeString": parameters[0]["typeName"]["typeDescriptions"]["typeString"] + } + leftHandSide = { + "name": parameters[0]["name"], + "nodeType": "Identifier", + "src": parameters[0]["src"], + "typeDescriptions": parameters[0]["typeDescriptions"], + } + else: + # we don't need an Assignment so we return only the external call + return externalCall + else: + ret["typeDescriptions"] = {"typeString": "tuple()"} + leftHandSide = { + "components": [], + "nodeType": "TupleExpression", + "src": parameters_list["src"], + } + + for p in parameters: + if p["name"] == "": + continue + + ident = { + "name": p["name"], + "nodeType": "Identifier", + "src": p["src"], + "typeDescriptions": p["typeDescriptions"], + } + leftHandSide["components"].append(ident) + + ret["leftHandSide"] = leftHandSide + ret["rightHandSide"] = externalCall + + return ret + def _parse_try_catch(self, statement: Dict, node: NodeSolc) -> NodeSolc: externalCall = statement.get("externalCall", None) @@ -669,15 +718,27 @@ class FunctionSolc(CallerContextExpression): node.underlying_node.scope.is_checked, False, node.underlying_node.scope ) new_node = self._new_node(NodeType.TRY, statement["src"], catch_scope) - new_node.add_unparsed_expression(externalCall) + clauses = statement.get("clauses", []) + # the first clause is the try scope + returned_variables = clauses[0].get("parameters", None) + constructed_try_expression = self._construct_try_expression( + externalCall, returned_variables + ) + new_node.add_unparsed_expression(constructed_try_expression) link_underlying_nodes(node, new_node) node = new_node - for clause in statement.get("clauses", []): - self._parse_catch(clause, node) + for index, clause in enumerate(clauses): + # clauses after the first one are related to catch cases + # we set the parameters (e.g. data in this case. catch(string memory data) ...) + # to be initialized so they are not reported by the uninitialized-local-variables detector + if index >= 1: + self._parse_catch(clause, node, True) + else: + self._parse_catch(clause, node, False) return node - def _parse_catch(self, statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_catch(self, statement: Dict, node: NodeSolc, var_initialized: bool) -> NodeSolc: block = statement.get("block", None) if block is None: @@ -695,7 +756,7 @@ class FunctionSolc(CallerContextExpression): if params: for param in params.get("parameters", []): assert param[self.get_key()] == "VariableDeclaration" - self._add_param(param) + self._add_param(param, var_initialized) return self._parse_statement(block, try_node, try_scope) @@ -1161,7 +1222,7 @@ class FunctionSolc(CallerContextExpression): visited.add(son) self._fix_catch(son, end_node, visited) - def _add_param(self, param: Dict) -> LocalVariableSolc: + def _add_param(self, param: Dict, initialized: bool = False) -> LocalVariableSolc: local_var = LocalVariable() local_var.set_function(self._function) @@ -1171,6 +1232,9 @@ class FunctionSolc(CallerContextExpression): local_var_parser.analyze(self) + if initialized: + local_var.initialized = True + # see https://solidity.readthedocs.io/en/v0.4.24/types.html?highlight=storage%20location#data-location if local_var.location == "default": local_var.set_location("memory") From d7b0d612c64eefc4bce33cdc4b09c6c740837a94 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 27 Apr 2023 10:53:20 +0200 Subject: [PATCH 032/338] Improve handling of multiple return variables --- slither/solc_parsing/declarations/function.py | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index ab5d289a8..7ac67a02d 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -672,6 +672,7 @@ class FunctionSolc(CallerContextExpression): # if the name is "" it means the return variable is not used if len(parameters) == 1: if parameters[0]["name"] != "": + self._add_param(parameters[0]) ret["typeDescriptions"] = { "typeString": parameters[0]["typeName"]["typeDescriptions"]["typeString"] } @@ -692,10 +693,17 @@ class FunctionSolc(CallerContextExpression): "src": parameters_list["src"], } - for p in parameters: + for i, p in enumerate(parameters): if p["name"] == "": continue + new_statement = { + "nodeType": "VariableDefinitionStatement", + "src": p["src"], + "declarations": [p], + } + self._add_param_init_tuple(new_statement, i) + ident = { "name": p["name"], "nodeType": "Identifier", @@ -735,10 +743,11 @@ class FunctionSolc(CallerContextExpression): if index >= 1: self._parse_catch(clause, node, True) else: + # the parameters for the try scope were already added in _construct_try_expression self._parse_catch(clause, node, False) return node - def _parse_catch(self, statement: Dict, node: NodeSolc, var_initialized: bool) -> NodeSolc: + def _parse_catch(self, statement: Dict, node: NodeSolc, add_param: bool) -> NodeSolc: block = statement.get("block", None) if block is None: @@ -748,15 +757,16 @@ class FunctionSolc(CallerContextExpression): try_node = self._new_node(NodeType.CATCH, statement["src"], try_scope) link_underlying_nodes(node, try_node) - if self.is_compact_ast: - params = statement.get("parameters", None) - else: - params = statement[self.get_children("children")] + if add_param: + if self.is_compact_ast: + params = statement.get("parameters", None) + else: + params = statement[self.get_children("children")] - if params: - for param in params.get("parameters", []): - assert param[self.get_key()] == "VariableDeclaration" - self._add_param(param, var_initialized) + if params: + for param in params.get("parameters", []): + assert param[self.get_key()] == "VariableDeclaration" + self._add_param(param, True) return self._parse_statement(block, try_node, try_scope) @@ -1242,6 +1252,17 @@ class FunctionSolc(CallerContextExpression): self._add_local_variable(local_var_parser) return local_var_parser + def _add_param_init_tuple(self, statement: Dict, index: int) -> LocalVariableInitFromTupleSolc: + + local_var = LocalVariableInitFromTuple() + local_var.set_function(self._function) + local_var.set_offset(statement["src"], self._function.compilation_unit) + + local_var_parser = LocalVariableInitFromTupleSolc(local_var, statement, index) + + self._add_local_variable(local_var_parser) + return local_var_parser + def _parse_params(self, params: Dict): assert params[self.get_key()] == "ParameterList" From 50876cf368bca53cada09234ee1096b2991af3d7 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 27 Apr 2023 11:13:01 +0200 Subject: [PATCH 033/338] Handle when there aren't return variables --- slither/solc_parsing/declarations/function.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 7ac67a02d..57d7784e5 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -665,6 +665,11 @@ class FunctionSolc(CallerContextExpression): # if the parameters are more than 1 we make the leftHandSide of the Assignment node # a TupleExpression otherwise an Identifier + # case when there isn't returns(...) + # e.g. external call that doesn't have any return variable + if not parameters_list: + return externalCall + ret: Dict = {"nodeType": "Assignment", "operator": "=", "src": parameters_list["src"]} parameters = parameters_list.get("parameters", None) From 6eb296cdf71ebd48ccab7e24ca99ba89a3b2c171 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 27 Apr 2023 11:23:03 +0200 Subject: [PATCH 034/338] Test catch variables not detected as uninitialized --- ...11_uninitialized_local_variable_sol__0.txt | 2 +- ..._6_uninitialized_local_variable_sol__0.txt | 2 +- .../0.6.11/uninitialized_local_variable.sol | 14 +++++++++++++- ...ninitialized_local_variable.sol-0.6.11.zip | Bin 1824 -> 2712 bytes .../0.7.6/uninitialized_local_variable.sol | 14 +++++++++++++- ...uninitialized_local_variable.sol-0.7.6.zip | Bin 1762 -> 2649 bytes 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_6_11_uninitialized_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_6_11_uninitialized_local_variable_sol__0.txt index 8e5dc65e8..7e5fa9559 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_6_11_uninitialized_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_6_11_uninitialized_local_variable_sol__0.txt @@ -1,2 +1,2 @@ -Uninitialized.func().uint_not_init (tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol#4) is a local variable never initialized +Uninitialized.func().uint_not_init (tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol#8) is a local variable never initialized diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_7_6_uninitialized_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_7_6_uninitialized_local_variable_sol__0.txt index 495859ec1..7bf1564d7 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_7_6_uninitialized_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UninitializedLocalVars_0_7_6_uninitialized_local_variable_sol__0.txt @@ -1,2 +1,2 @@ -Uninitialized.func().uint_not_init (tests/e2e/detectors/test_data/uninitialized-local/0.7.6/uninitialized_local_variable.sol#4) is a local variable never initialized +Uninitialized.func().uint_not_init (tests/e2e/detectors/test_data/uninitialized-local/0.7.6/uninitialized_local_variable.sol#8) is a local variable never initialized diff --git a/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol b/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol index d28eef957..00a4fbc86 100644 --- a/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol +++ b/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol @@ -1,9 +1,21 @@ +interface I { + function a() external; +} + contract Uninitialized{ function func() external returns(uint){ uint uint_not_init; uint uint_init = 1; return uint_not_init + uint_init; - } + } + + function func_try_catch(I i) external returns(uint) { + try i.a() { + return 1; + } catch (bytes memory data) { + data; + } + } } diff --git a/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol-0.6.11.zip b/tests/e2e/detectors/test_data/uninitialized-local/0.6.11/uninitialized_local_variable.sol-0.6.11.zip index ca7ea0eb308fe7b52d4395dd5171d8bdbf5d44f2..d5b1203065287433605f4fdd799d6e32862f7048 100644 GIT binary patch delta 2557 zcmV@KL7#%4gfV;n^xf(0*uZH003G%kr-ru^+P_6+Z$mK{=)<4#k(GbXB?s{~H=a zs3iZSL1y6a%c)g=c8>~Gzo559b-?F@wye`NK)+y_mW4~=J%l}F&*_)3Aiw|>(5`1O z>!tfUafTu?!!Sn&5*^ygdzy;8H7BLD=W~5~y=n%^pC9f{{R3Z~-k2`0P=BWZarpw# z!zcOOX?_oKPLE`8q-&F=(Jlr8F_nz>CnbC5Gm$7Q_roxMvgz4;#M+XVKe_~?6~*)G z26CcKqL-st$F@hZVKEU8XrU)6Ihxs4zJ|Em2x!1)dSG=3twk5gJai^t9(CeW_8Nt`A$c4AX z!L9X_Ei*B|sO$6_X_rU+nB?ES!a)PZsLAabL*!3?g6Xf4bHyJa?PCv%`vycUDY(-! z(1EBBrk2I@e{v8*{XplTytWpbb+nv)nnL`K@Z17&f>E5R7N2YoDRSeU809V#IR@R_ zic$9uusQfhSOrMN;HFQU%y9@8S^ZHaHu{)hz|;nC&5gnj(QP<)`7X4lnR`ju=`Q4u3K1Wif)?Ka-kMexshf9 zo|cCbj)BxSi}FzHAzbngE*`UQ*x6MFfRh&zUvT1wVpT6}w0J?!pnuv%brbs$4QSx@ z^~sgRB^)CGQS0wj7E<6jL3U9%_&#*$&3}t+=ew3U|Mx&JierJAqw<{7u-apqYiOE( z-zlLtp15QYtvku0Ww6;%&BS!R0g0cX1&(N0+>EW&lgFcjut4xd!L<*l7Qi8fZTD}7 zO4LFUsg=p}vrrLMC`<1sqnZqfKyTH3f_(E}b=Vuk`JAzHWeT6j4A`#x=WsKmf8Lti zE+~@@U?iNQ3|SkM-){^WDb8D$!-`^m+rB2>D%)v~@S=TU@iQ+XT4ML38l;YRYyB}N z)pnN5!ZiU!^+0SdDQCN1J%lG~E@pm7Dj-+2zo874m_9oRJ37@NXB_0~TeQckdaoJH zc%*PI`?>eI2s7IEM*okcu6-1!NPzs=szbpU*%p~M{#_`{1>mHcZ>{N|4YK8bHOQ1r z1*RD(^jtM#+E8cM(giRmH#fmWaA3|fTx=-mvz(p6Hj41(m z`Fi7Z7^f_UwyCVvVrH7Ox@Iw|k%L@9JP36;H@7QAO3o&PSPh9yF{Ri-#hFfUY)dH1 zY{}VdqCLpLl)@)|sWai~nP&TcwrPui#wai}z7PTw;YKt(Eg_k*asE`b&IwI*(N($G zev;cB&FF*F=_F*{g5+Xe2J_;*!0sMGuH=#TZgri!ozdimHsM?<7rHZ`5^Fa2?xnnmj&&?6NQh^fI!`rUiowF`O)^t@ z9yYZrq-T-hXf?Mw)OykA-2M#FH2H8GTY@Dh;EYI#q}{N|(0TW!bu8SFuCUWl<&hZS zmydxk6jM}(^#CP>B1x%#Q@RzR&(W#9i{!N*(|8Bq{^ba1v0hF#^1IZhn%d=V=Jod; z=ysp64{GpWdTGPuNSO!xoKMsvxsE^xm6;pV#-Q!BrmDqoT9epazvXIW9a^rSE6Atly@@SD{>-5@~R6pqnYrya(B1@MoMev(wPxvh3k_Y8&U zq&@x9n#SVrNyCdxof+B2U#Y0&KMNQqjz+oscN+ui{G=dpwtUt8Z*b48By3_d$xkIZIr>QuZDK#F#CvlL{n4{_9kk074aWKdfm%;!{sGY4hBpz&4`t#nn>@OEh6H6 zieA|hM+vh57e_zswlLxG^i!HjJT08L=x-oV*y(#|g^ClBWH}{Zh{^w%gS7NI3?|{` zgpW_Y T2><|EJd?r(SOy>p00000-=q6_ delta 1662 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 I2><{907VzOmjD0& delta 1607 zcmV-N2Dtgz6ygmVP)h>@KL7#%4gfoicUE;nYX2Ap002T9001|}t(aS6;oO)2cgKrt@CvFD zq-twonro_@{&p*CwbB5MY;H;&9AR62-ZWz<@VE4AZ4Qa(U0<$njRn~ymyLt`Xc7Yr zPW;C;9N^_wQV658`?crE5J&a2g{MGF(MSyx_#E^>kW!?o1Q6FJyPm z1ZMR&cXfcTHweG@NUjJ2%n)`xOWk|IzI5u{Tw9D~q22nnKNm9|r>K8&egVk>2h;JI zT2npyo2Ro6mNX&c2+u*bcw2HdQ8*Gnc8rTxPW_eD+U=R%<-2-V?P_(GL(*ZiU5b@4 zEKfrm01iBZ1k}ckgyH)E))5Fjf3^i1Xb> zGXd7wA=Mf~r>fchP|&Nie_Oxw*6f}Z!PwG|R=QQLE9AW1YGWd(g*pr}!&))ti{$^2 zNVy{4J)sTsn%``g+bO$mlb2QibhQLJtY4Pokoor5^_zMQg(H8kM|M}m+^hc_!pxT> zs2R62g)o|hlJ72*sYp?jCpZm`eapu-o+YR7X4;BvQZ6p%JkB7@OIccF!2Q(dAu5jt z#(XDCsqAmuvcbt!8)m%UF)W3R*TQ~eGp#%PInmo?Emw^;q z6t1IH@OQHQ(bK!r8iv=hwVOn`xlWE_V+Z4M)UHEaVdhxRMJCQnMwNsx*9 zw1`WgZ6bfGoBoJpVOBe85ymLKcYYlhzW@UjyR1^-xx%myN*BQ}k~ce3^S9!+B+$yq zH>RUV+MM5VxrBk46l0*)$85C|8u*?FkvO-wBM%vD92uxyuj288k1ofGQ9s#)AYzW! z!T5h-y;74pRnmBp5MN}CX9t2L9j+2Av36@{m4{DkT28j|e}U@R=ERYL{F=ShmxM=> z?ERla+q06O0Po|^-jXFfX(1+A3cgq+8%s8h`E$w`uu}L2(8=at?JGhJ96P{geOTI2 z1P16WkR6sq>smlds2Tz8(lY=1Pr7;IBzu2fe}w24sKLD#@QQq{AVt}o{}H=KZt+9 z+?xVqzK?Ny3vtzTOafoqzCXGI+t**{GDVvmO$07sT-@l;Qv=AdEk@oNbFHhkTrepe z`NCLkxeJrafMpvdBW?lvE50B}1-l^%Nm&p`Ep%&DVa|q(*RM_|u##Crc}ZQv6@)9c zFoVs2zDZa{F^U!c-CK~-P)h* Date: Tue, 2 May 2023 15:51:04 -0700 Subject: [PATCH 035/338] feat: loc printer --- slither/printers/all_printers.py | 1 + slither/printers/summary/human_summary.py | 79 ++++++-------- slither/printers/summary/loc.py | 127 ++++++++++++++++++++++ slither/utils/myprettytable.py | 39 +++++++ 4 files changed, 201 insertions(+), 45 deletions(-) create mode 100644 slither/printers/summary/loc.py diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 6dc8dddbd..3dd64da3e 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -1,6 +1,7 @@ # pylint: disable=unused-import,relative-beyond-top-level from .summary.function import FunctionSummary from .summary.contract import ContractSummary +from .summary.loc import Loc from .inheritance.inheritance import PrinterInheritance from .inheritance.inheritance_graph import PrinterInheritanceGraph from .call.call_graph import PrinterCallGraph diff --git a/slither/printers/summary/human_summary.py b/slither/printers/summary/human_summary.py index 9eacb97c6..157b8228a 100644 --- a/slither/printers/summary/human_summary.py +++ b/slither/printers/summary/human_summary.py @@ -2,12 +2,12 @@ Module printing summary of the contract """ import logging -from pathlib import Path from typing import Tuple, List, Dict from slither.core.declarations import SolidityFunction, Function from slither.core.variables.state_variable import StateVariable from slither.printers.abstract_printer import AbstractPrinter +from slither.printers.summary.loc import compute_loc_metrics from slither.slithir.operations import ( LowLevelCall, HighLevelCall, @@ -21,7 +21,6 @@ from slither.utils.colors import green, red, yellow from slither.utils.myprettytable import MyPrettyTable from slither.utils.standard_libraries import is_standard_library from slither.core.cfg.node import NodeType -from slither.utils.tests_pattern import is_test_file class PrinterHumanSummary(AbstractPrinter): @@ -32,7 +31,6 @@ class PrinterHumanSummary(AbstractPrinter): @staticmethod def _get_summary_erc20(contract): - functions_name = [f.name for f in contract.functions] state_variables = [v.name for v in contract.state_variables] @@ -165,27 +163,6 @@ class PrinterHumanSummary(AbstractPrinter): def _number_functions(contract): return len(contract.functions) - def _lines_number(self): - if not self.slither.source_code: - return None - total_dep_lines = 0 - total_lines = 0 - total_tests_lines = 0 - - for filename, source_code in self.slither.source_code.items(): - lines = len(source_code.splitlines()) - is_dep = False - if self.slither.crytic_compile: - is_dep = self.slither.crytic_compile.is_dependency(filename) - if is_dep: - total_dep_lines += lines - else: - if is_test_file(Path(filename)): - total_tests_lines += lines - else: - total_lines += lines - return total_lines, total_dep_lines, total_tests_lines - def _get_number_of_assembly_lines(self): total_asm_lines = 0 for contract in self.contracts: @@ -226,7 +203,6 @@ class PrinterHumanSummary(AbstractPrinter): return list(set(ercs)) def _get_features(self, contract): # pylint: disable=too-many-branches - has_payable = False can_send_eth = False can_selfdestruct = False @@ -291,6 +267,36 @@ class PrinterHumanSummary(AbstractPrinter): "Proxy": contract.is_upgradeable_proxy, } + def _get_contracts(self, txt): + ( + number_contracts, + number_contracts_deps, + number_contracts_tests, + ) = self._number_contracts() + txt += f"Total number of contracts in source files: {number_contracts}\n" + if number_contracts_deps > 0: + txt += f"Number of contracts in dependencies: {number_contracts_deps}\n" + if number_contracts_tests > 0: + txt += f"Number of contracts in tests : {number_contracts_tests}\n" + return txt + + def _get_number_lines(self, txt, results): + lines_dict = compute_loc_metrics(self.slither) + txt += "Source lines of code (SLOC) in source files: " + txt += f"{lines_dict['src']['sloc']}\n" + if lines_dict["dep"]["sloc"] > 0: + txt += "Source lines of code (SLOC) in dependencies: " + txt += f"{lines_dict['dep']['sloc']}\n" + if lines_dict["test"]["sloc"] > 0: + txt += "Source lines of code (SLOC) in tests : " + txt += f"{lines_dict['test']['sloc']}\n" + results["number_lines"] = lines_dict["src"]["sloc"] + results["number_lines__dependencies"] = lines_dict["dep"]["sloc"] + total_asm_lines = self._get_number_of_assembly_lines() + txt += f"Number of assembly lines: {total_asm_lines}\n" + results["number_lines_assembly"] = total_asm_lines + return txt, results + def output(self, _filename): # pylint: disable=too-many-locals,too-many-statements """ _filename is not used @@ -311,24 +317,8 @@ class PrinterHumanSummary(AbstractPrinter): "number_findings": {}, "detectors": [], } - - lines_number = self._lines_number() - if lines_number: - total_lines, total_dep_lines, total_tests_lines = lines_number - txt += f"Number of lines: {total_lines} (+ {total_dep_lines} in dependencies, + {total_tests_lines} in tests)\n" - results["number_lines"] = total_lines - results["number_lines__dependencies"] = total_dep_lines - total_asm_lines = self._get_number_of_assembly_lines() - txt += f"Number of assembly lines: {total_asm_lines}\n" - results["number_lines_assembly"] = total_asm_lines - - ( - number_contracts, - number_contracts_deps, - number_contracts_tests, - ) = self._number_contracts() - txt += f"Number of contracts: {number_contracts} (+ {number_contracts_deps} in dependencies, + {number_contracts_tests} tests) \n\n" - + txt = self._get_contracts(txt) + txt, results = self._get_number_lines(txt, results) ( txt_detectors, detectors_results, @@ -352,7 +342,7 @@ class PrinterHumanSummary(AbstractPrinter): libs = self._standard_libraries() if libs: txt += f'\nUse: {", ".join(libs)}\n' - results["standard_libraries"] = [str(l) for l in libs] + results["standard_libraries"] = [str(lib) for lib in libs] ercs = self._ercs() if ercs: @@ -363,7 +353,6 @@ class PrinterHumanSummary(AbstractPrinter): ["Name", "# functions", "ERCS", "ERC20 info", "Complex code", "Features"] ) for contract in self.slither.contracts_derived: - if contract.is_from_dependency() or contract.is_test: continue diff --git a/slither/printers/summary/loc.py b/slither/printers/summary/loc.py new file mode 100644 index 000000000..4ed9aa6ab --- /dev/null +++ b/slither/printers/summary/loc.py @@ -0,0 +1,127 @@ +""" + Lines of Code (LOC) printer + + Definitions: + cloc: comment lines of code containing only comments + sloc: source lines of code with no whitespace or comments + loc: all lines of code including whitespace and comments + src: source files (excluding tests and dependencies) + dep: dependency files + test: test files +""" +from pathlib import Path +from slither.printers.abstract_printer import AbstractPrinter +from slither.utils.myprettytable import transpose, make_pretty_table +from slither.utils.tests_pattern import is_test_file + + +def count_lines(contract_lines: list) -> tuple: + """Function to count and classify the lines of code in a contract. + Args: + contract_lines: list(str) representing the lines of a contract. + Returns: + tuple(int, int, int) representing (cloc, sloc, loc) + """ + multiline_comment = False + cloc = 0 + sloc = 0 + loc = 0 + + for line in contract_lines: + loc += 1 + stripped_line = line.strip() + if not multiline_comment: + if stripped_line.startswith("//"): + cloc += 1 + elif "/*" in stripped_line: + # Account for case where /* is followed by */ on the same line. + # If it is, then multiline_comment does not need to be set to True + start_idx = stripped_line.find("/*") + end_idx = stripped_line.find("*/", start_idx + 2) + if end_idx == -1: + multiline_comment = True + cloc += 1 + elif stripped_line: + sloc += 1 + else: + cloc += 1 + if "*/" in stripped_line: + multiline_comment = False + + return cloc, sloc, loc + + +def _update_lines_dict(file_type: str, lines: list, lines_dict: dict) -> dict: + """An internal function used to update (mutate in place) the lines_dict. + Args: + file_type: str indicating "src" (source files), "dep" (dependency files), or "test" tests. + lines: list(str) representing the lines of a contract. + lines_dict: dict to be updated with this shape: + { + "src" : {"loc": 30, "sloc": 20, "cloc": 5}, # code in source files + "dep" : {"loc": 50, "sloc": 30, "cloc": 10}, # code in dependencies + "test": {"loc": 80, "sloc": 60, "cloc": 10}, # code in tests + } + Returns: + an updated lines_dict + """ + cloc, sloc, loc = count_lines(lines) + lines_dict[file_type]["loc"] += loc + lines_dict[file_type]["cloc"] += cloc + lines_dict[file_type]["sloc"] += sloc + return lines_dict + + +def compute_loc_metrics(slither) -> dict: + """Used to compute the lines of code metrics for a Slither object. + Args: + slither: A Slither object + Returns: + A new dict with the following shape: + { + "src" : {"loc": 30, "sloc": 20, "cloc": 5}, # code in source files + "dep" : {"loc": 50, "sloc": 30, "cloc": 10}, # code in dependencies + "test": {"loc": 80, "sloc": 60, "cloc": 10}, # code in tests + } + """ + + lines_dict = { + "src": {"loc": 0, "sloc": 0, "cloc": 0}, + "dep": {"loc": 0, "sloc": 0, "cloc": 0}, + "test": {"loc": 0, "sloc": 0, "cloc": 0}, + } + + if not slither.source_code: + return lines_dict + + for filename, source_code in slither.source_code.items(): + current_lines = source_code.splitlines() + is_dep = False + if slither.crytic_compile: + is_dep = slither.crytic_compile.is_dependency(filename) + file_type = "dep" if is_dep else "test" if is_test_file(Path(filename)) else "src" + lines_dict = _update_lines_dict(file_type, current_lines, lines_dict) + return lines_dict + + +class Loc(AbstractPrinter): + ARGUMENT = "loc" + HELP = """Count the total number lines of code (LOC), source lines of code (SLOC), \ + and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), \ + and test files (TEST).""" + + WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#loc" + + def output(self, _filename): + # compute loc metrics + lines_dict = compute_loc_metrics(self.slither) + + # prepare the table + headers = [""] + list(lines_dict.keys()) + report_dict = transpose(lines_dict) + table = make_pretty_table(headers, report_dict) + txt = "Lines of Code \n" + str(table) + self.info(txt) + res = self.generate_output(txt) + res.add_pretty_table(table, "Code Lines") + return res diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index af10a6ff2..efdb96504 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -22,3 +22,42 @@ class MyPrettyTable: def __str__(self) -> str: return str(self.to_pretty_table()) + + +# **Dict to MyPrettyTable utility functions** + + +# Converts a dict to a MyPrettyTable. Dict keys are the row headers. +# @param headers str[] of column names +# @param body dict of row headers with a dict of the values +# @param totals bool optional add Totals row +def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: + table = MyPrettyTable(headers) + for row in body: + table_row = [row] + [body[row][key] for key in headers[1:]] + table.add_row(table_row) + if totals: + table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) + return table + + +# takes a dict of dicts and returns a dict of dicts with the keys transposed +# example: +# in: +# { +# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, +# "test": {"loc": 0, "sloc": 0, "cloc": 0}, +# "src": {"loc": 0, "sloc": 0, "cloc": 0}, +# } +# out: +# { +# 'loc': {'dep': 0, 'test': 0, 'src': 0}, +# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, +# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, +# } +def transpose(table): + any_key = list(table.keys())[0] + return { + inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} + for inner_key in table[any_key] + } From 201b4dfcfe1b645f34d65f5a87e7d5a095411431 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Tue, 2 May 2023 10:33:47 -0700 Subject: [PATCH 036/338] feat: halstead printer --- slither/printers/all_printers.py | 1 + slither/printers/summary/halstead.py | 166 +++++++++++++++++++++++++++ slither/utils/myprettytable.py | 39 +++++++ 3 files changed, 206 insertions(+) create mode 100644 slither/printers/summary/halstead.py diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 6dc8dddbd..120279403 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -8,6 +8,7 @@ from .functions.authorization import PrinterWrittenVariablesAndAuthorization from .summary.slithir import PrinterSlithIR from .summary.slithir_ssa import PrinterSlithIRSSA from .summary.human_summary import PrinterHumanSummary +from .summary.halstead import Halstead from .functions.cfg import CFG from .summary.function_ids import FunctionIds from .summary.variable_order import VariableOrder diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py new file mode 100644 index 000000000..b50575ab6 --- /dev/null +++ b/slither/printers/summary/halstead.py @@ -0,0 +1,166 @@ +""" + Halstead complexity metrics + https://en.wikipedia.org/wiki/Halstead_complexity_measures + + 12 metrics based on the number of unique operators and operands: + + Core metrics: + n1 = the number of distinct operators + n2 = the number of distinct operands + N1 = the total number of operators + N2 = the total number of operands + + Extended metrics: + n = n1 + n2 # Program vocabulary + N = N1 + N2 # Program length + S = n1 * log2(n1) + n2 * log2(n2) # Estimated program length + V = N * log2(n) # Volume + D = (n1 / 2) * (N2 / n2) # Difficulty + E = D * V # Effort + T = E / 18 seconds # Time required to program + B = (E^(2/3)) / 3000 # Number of delivered bugs + + +""" +import math +from collections import OrderedDict +from slither.printers.abstract_printer import AbstractPrinter +from slither.slithir.variables.temporary import TemporaryVariable +from slither.utils.myprettytable import make_pretty_table + + +def compute_halstead(contracts: list) -> tuple: + """Used to compute the Halstead complexity metrics for a list of contracts. + Args: + contracts: list of contracts. + Returns: + Halstead metrics as a tuple of two OrderedDicts (core_metrics, extended_metrics) + which each contain one key per contract. The value of each key is a dict of metrics. + + In addition to one key per contract, there is a key for "ALL CONTRACTS" that contains + the metrics for ALL CONTRACTS combined. (Not the sums of the individual contracts!) + + core_metrics: + {"contract1 name": { + "n1_unique_operators": n1, + "n2_unique_operands": n1, + "N1_total_operators": N1, + "N2_total_operands": N2, + }} + + extended_metrics: + {"contract1 name": { + "n_vocabulary": n1 + n2, + "N_prog_length": N1 + N2, + "S_est_length": S, + "V_volume": V, + "D_difficulty": D, + "E_effort": E, + "T_time": T, + "B_bugs": B, + }} + + """ + core = OrderedDict() + extended = OrderedDict() + all_operators = [] + all_operands = [] + for contract in contracts: + operators = [] + operands = [] + for func in contract.functions: + for node in func.nodes: + for operation in node.irs: + # use operation.expression.type to get the unique operator type + operator_type = operation.expression.type + operators.append(operator_type) + all_operators.append(operator_type) + + # use operation.used to get the operands of the operation ignoring the temporary variables + new_operands = [ + op for op in operation.used if not isinstance(op, TemporaryVariable) + ] + operands.extend(new_operands) + all_operands.extend(new_operands) + (core[contract.name], extended[contract.name]) = _calculate_metrics(operators, operands) + core["ALL CONTRACTS"] = OrderedDict() + extended["ALL CONTRACTS"] = OrderedDict() + (core["ALL CONTRACTS"], extended["ALL CONTRACTS"]) = _calculate_metrics( + all_operators, all_operands + ) + return (core, extended) + + +# pylint: disable=too-many-locals +def _calculate_metrics(operators, operands): + """Used to compute the Halstead complexity metrics for a list of operators and operands. + Args: + operators: list of operators. + operands: list of operands. + Returns: + Halstead metrics as a tuple of two OrderedDicts (core_metrics, extended_metrics) + which each contain one key per contract. The value of each key is a dict of metrics. + NOTE: The metric values are ints and floats that have been converted to formatted strings + """ + n1 = len(set(operators)) + n2 = len(set(operands)) + N1 = len(operators) + N2 = len(operands) + n = n1 + n2 + N = N1 + N2 + S = 0 if (n1 == 0 or n2 == 0) else n1 * math.log2(n1) + n2 * math.log2(n2) + V = N * math.log2(n) if n > 0 else 0 + D = (n1 / 2) * (N2 / n2) if n2 > 0 else 0 + E = D * V + T = E / 18 + B = (E ** (2 / 3)) / 3000 + core_metrics = { + "n1_unique_operators": n1, + "n2_unique_operands": n2, + "N1_total_operators": N1, + "N2_total_operands": N2, + } + extended_metrics = { + "n_vocabulary": str(n1 + n2), + "N_prog_length": str(N1 + N2), + "S_est_length": f"{S:.0f}", + "V_volume": f"{V:.0f}", + "D_difficulty": f"{D:.0f}", + "E_effort": f"{E:.0f}", + "T_time": f"{T:.0f}", + "B_bugs": f"{B:.3f}", + } + return (core_metrics, extended_metrics) + + +class Halstead(AbstractPrinter): + ARGUMENT = "halstead" + HELP = "Computes the Halstead complexity metrics for each contract" + + WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#halstead" + + def output(self, _filename): + if len(self.contracts) == 0: + return self.generate_output("No contract found") + + core, extended = compute_halstead(self.contracts) + + # Core metrics: operations and operands + txt = "\n\nHalstead complexity core metrics:\n" + keys = list(core[self.contracts[0].name].keys()) + table1 = make_pretty_table(["Contract", *keys], core, False) + txt += str(table1) + "\n" + + # Extended metrics: volume, difficulty, effort, time, bugs + # TODO: should we break this into 2 tables? currently 119 chars wide + txt += "\nHalstead complexity extended metrics:\n" + keys = list(extended[self.contracts[0].name].keys()) + table2 = make_pretty_table(["Contract", *keys], extended, False) + txt += str(table2) + "\n" + + res = self.generate_output(txt) + res.add_pretty_table(table1, "Halstead core metrics") + res.add_pretty_table(table2, "Halstead extended metrics") + self.info(txt) + + return res diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index af10a6ff2..efdb96504 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -22,3 +22,42 @@ class MyPrettyTable: def __str__(self) -> str: return str(self.to_pretty_table()) + + +# **Dict to MyPrettyTable utility functions** + + +# Converts a dict to a MyPrettyTable. Dict keys are the row headers. +# @param headers str[] of column names +# @param body dict of row headers with a dict of the values +# @param totals bool optional add Totals row +def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: + table = MyPrettyTable(headers) + for row in body: + table_row = [row] + [body[row][key] for key in headers[1:]] + table.add_row(table_row) + if totals: + table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) + return table + + +# takes a dict of dicts and returns a dict of dicts with the keys transposed +# example: +# in: +# { +# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, +# "test": {"loc": 0, "sloc": 0, "cloc": 0}, +# "src": {"loc": 0, "sloc": 0, "cloc": 0}, +# } +# out: +# { +# 'loc': {'dep': 0, 'test': 0, 'src': 0}, +# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, +# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, +# } +def transpose(table): + any_key = list(table.keys())[0] + return { + inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} + for inner_key in table[any_key] + } From f48189951b95f752540043aa3c427f2a12f6aaaa Mon Sep 17 00:00:00 2001 From: bart1e Date: Sun, 26 Feb 2023 17:39:01 +0100 Subject: [PATCH 037/338] Detector for array length caching added --- slither/detectors/all_detectors.py | 1 + .../operations/cache_array_length.py | 215 ++++++++++++++++++ .../0.8.17/CacheArrayLength.sol | 127 +++++++++++ ...rayLength.sol.0.8.17.CacheArrayLength.json | 74 ++++++ tests/e2e/detectors/test_detectors.py | 5 + 5 files changed, 422 insertions(+) create mode 100644 slither/detectors/operations/cache_array_length.py create mode 100644 tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol create mode 100644 tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index 9722b8793..6a1ec6739 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -89,3 +89,4 @@ from .functions.protected_variable import ProtectedVariables from .functions.permit_domain_signature_collision import DomainSeparatorCollision from .functions.codex import Codex from .functions.cyclomatic_complexity import CyclomaticComplexity +from .operations.cache_array_length import CacheArrayLength diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py new file mode 100644 index 000000000..8c1112d2d --- /dev/null +++ b/slither/detectors/operations/cache_array_length.py @@ -0,0 +1,215 @@ +from typing import List, Set + +from slither.core.cfg.node import Node, NodeType +from slither.core.declarations import Function +from slither.core.expressions import BinaryOperation, Identifier, MemberAccess, UnaryOperation +from slither.core.solidity_types import ArrayType +from slither.core.source_mapping.source_mapping import SourceMapping +from slither.core.variables import StateVariable +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.slithir.operations import Length, Delete + + +class CacheArrayLength(AbstractDetector): + """ + Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it. + """ + + ARGUMENT = "cache-array-length" + HELP = ( + "Detects `for` loops that use `length` member of some storage array in their loop condition and don't " + "modify it. " + ) + IMPACT = DetectorClassification.OPTIMIZATION + CONFIDENCE = DetectorClassification.HIGH + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length" + + WIKI_TITLE = "Cache array length" + WIKI_DESCRIPTION = ( + "Detects `for` loops that use `length` member of some storage array in their loop condition " + "and don't modify it. " + ) + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract C +{ + uint[] array; + + function f() public + { + for (uint i = 0; i < array.length; i++) + { + // code that does not modify length of `array` + } + } +} +``` +Since the `for` loop in `f` doesn't modify `array.length`, it is more gas efficient to cache it in some local variable and use that variable instead, like in the following example: + +```solidity +contract C +{ + uint[] array; + + function f() public + { + uint array_length = array.length; + for (uint i = 0; i < array_length; i++) + { + // code that does not modify length of `array` + } + } +} +``` + """ + WIKI_RECOMMENDATION = ( + "Cache the lengths of storage arrays if they are used and not modified in `for` loops." + ) + + @staticmethod + def _is_identifier_member_access_comparison(exp: BinaryOperation) -> bool: + """ + Checks whether a BinaryOperation `exp` is an operation on Identifier and MemberAccess. + """ + return ( + isinstance(exp.expression_left, Identifier) + and isinstance(exp.expression_right, MemberAccess) + ) or ( + isinstance(exp.expression_left, MemberAccess) + and isinstance(exp.expression_right, Identifier) + ) + + @staticmethod + def _extract_array_from_length_member_access(exp: MemberAccess) -> [StateVariable | None]: + """ + Given a member access `exp`, it returns state array which `length` member is accessed through `exp`. + If array is not a state array or its `length` member is not referenced, it returns `None`. + """ + if exp.member_name != "length": + return None + if not isinstance(exp.expression, Identifier): + return None + if not isinstance(exp.expression.value, StateVariable): + return None + if not isinstance(exp.expression.value.type, ArrayType): + return None + return exp.expression.value + + @staticmethod + def _is_loop_referencing_array_length( + node: Node, visited: Set[Node], array: StateVariable, depth: int + ) -> True: + """ + For a given loop, checks if it references `array.length` at some point. + Will also return True if `array.length` is referenced but not changed. + This may potentially generate false negatives in the detector, but it was done this way because: + - situations when array `length` is referenced but not modified in loop are rare + - checking if `array.length` is indeed modified would require much more work + """ + visited.add(node) + if node.type == NodeType.STARTLOOP: + depth += 1 + if node.type == NodeType.ENDLOOP: + depth -= 1 + if depth == 0: + return False + + # Array length may change in the following situations: + # - when `push` is called + # - when `pop` is called + # - when `delete` is called on the entire array + if node.type == NodeType.EXPRESSION: + for op in node.irs: + if isinstance(op, Length) and op.value == array: + # op accesses array.length, not necessarily modifying it + return True + if isinstance(op, Delete): + # take into account only delete entire array, since delete array[i] doesn't change `array.length` + if ( + isinstance(op.expression, UnaryOperation) + and isinstance(op.expression.expression, Identifier) + and op.expression.expression.value == array + ): + return True + + for son in node.sons: + if son not in visited: + if CacheArrayLength._is_loop_referencing_array_length(son, visited, array, depth): + return True + return False + + @staticmethod + def _handle_loops(nodes: List[Node], non_optimal_array_len_usages: List[SourceMapping]) -> None: + """ + For each loop, checks if it has a comparison with `length` array member and, if it has, checks whether that + array size could potentially change in that loop. + If it cannot, the loop condition is added to `non_optimal_array_len_usages`. + There may be some false negatives here - see docs for `_is_loop_referencing_array_length` for more information. + """ + for node in nodes: + if node.type == NodeType.STARTLOOP: + if_node = node.sons[0] + if if_node.type != NodeType.IFLOOP: + continue + if not isinstance(if_node.expression, BinaryOperation): + continue + exp: BinaryOperation = if_node.expression + if not CacheArrayLength._is_identifier_member_access_comparison(exp): + continue + array: StateVariable + if isinstance(exp.expression_right, MemberAccess): + array = CacheArrayLength._extract_array_from_length_member_access( + exp.expression_right + ) + else: # isinstance(exp.expression_left, MemberAccess) == True + array = CacheArrayLength._extract_array_from_length_member_access( + exp.expression_left + ) + if array is None: + continue + + visited: Set[Node] = set() + if not CacheArrayLength._is_loop_referencing_array_length( + if_node, visited, array, 1 + ): + non_optimal_array_len_usages.append(if_node.expression) + + @staticmethod + def _get_non_optimal_array_len_usages_for_function(f: Function) -> List[SourceMapping]: + """ + Finds non-optimal usages of array length in loop conditions in a given function. + """ + non_optimal_array_len_usages: List[SourceMapping] = [] + CacheArrayLength._handle_loops(f.nodes, non_optimal_array_len_usages) + + return non_optimal_array_len_usages + + @staticmethod + def _get_non_optimal_array_len_usages(functions: List[Function]) -> List[SourceMapping]: + """ + Finds non-optimal usages of array length in loop conditions in given functions. + """ + non_optimal_array_len_usages: List[SourceMapping] = [] + + for f in functions: + non_optimal_array_len_usages += ( + CacheArrayLength._get_non_optimal_array_len_usages_for_function(f) + ) + + return non_optimal_array_len_usages + + def _detect(self): + results = [] + + non_optimal_array_len_usages = CacheArrayLength._get_non_optimal_array_len_usages( + self.compilation_unit.functions + ) + for usage in non_optimal_array_len_usages: + info = [ + f"Loop condition at {usage.source_mapping} should use cached array length instead of referencing " + f"`length` member of the storage array.\n " + ] + res = self.generate_result(info) + results.append(res) + return results diff --git a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol new file mode 100644 index 000000000..79858d182 --- /dev/null +++ b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol @@ -0,0 +1,127 @@ +pragma solidity 0.8.17; + +contract CacheArrayLength +{ + struct S + { + uint s; + } + + S[] array; + S[] array2; + + function f() public + { + // array accessed but length doesn't change + for (uint i = 0; i < array.length; i++) // warning should appear + { + array[i] = S(0); + } + + // array.length doesn't change, but array.length not used in loop condition + for (uint i = array.length; i >= 0; i--) + { + + } + + // array.length changes in the inner loop + for (uint i = 0; i < array.length; i++) + { + for (uint j = i; j < 2 * i; j++) + array.push(S(j)); + } + + // array.length changes + for (uint i = 0; i < array.length; i++) + { + array.pop(); + } + + // array.length changes + for (uint i = 0; i < array.length; i++) + { + delete array; + } + + // array.length doesn't change despite using delete + for (uint i = 0; i < array.length; i++) // warning should appear + { + delete array[i]; + } + + // array.length changes; push used in more complex expression + for (uint i = 0; i < array.length; i++) + { + array.push() = S(i); + } + + // array.length doesn't change + for (uint i = 0; i < array.length; i++) // warning should appear + { + array2.pop(); + array2.push(); + array2.push(S(i)); + delete array2; + delete array[0]; + } + + // array.length changes; array2.length doesn't change + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) // warning should appear + { + array.pop(); + } + } + } + + // array.length doesn't change; array2.length changes + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) // warning should appear + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) + { + array2.pop(); + } + } + } + + // none of array.length and array2.length changes + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) // warning should appear + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) // warning should appear + { + + } + } + } + + S[] memory array3; + + // array3 not modified, but it's not a storage array + for (uint i = 0; i < array3.length; i++) + { + + } + } +} \ No newline at end of file diff --git a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json new file mode 100644 index 000000000..b2050508f --- /dev/null +++ b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json @@ -0,0 +1,74 @@ +[ + [ + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "66f0059f2e2608b9e532ab9f6a473aa9128f1e9f02fe16fcb960b4ae4970b2cb", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "8463e2cd88985588ad2426476df033957fb4f8969117b7649f1165244b86d2e0", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "961db8345eea46c3814eb2c6f6fc6d1506a2feaa85630349266cff940f33a7ab", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "aea0a11159dec6d660f39a09aa44b56ad0effb7ced7183552b21b69f0f62e0c7", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "d296a0fd4cbe7b9a2db11b3d08b2db08a53414326a91eeda1f78853c4d4c5714", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "db2bfdc710cfa1ea5339e1f14b1a5b80735c50c37522f983a220b579df34c5d0", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [], + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n", + "first_markdown_element": "", + "id": "f5085e5d1ddd69d59f60443b7e89ea5f7301ba6a0a42786624b783389474aaf7", + "check": "cache-array-length", + "impact": "Optimization", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py index e6b87d530..5a9180256 100644 --- a/tests/e2e/detectors/test_detectors.py +++ b/tests/e2e/detectors/test_detectors.py @@ -1639,6 +1639,11 @@ ALL_TEST_OBJECTS = [ "LowCyclomaticComplexity.sol", "0.8.16", ), + Test( + all_detectors.CacheArrayLength, + "CacheArrayLength.sol", + "0.8.17", + ), ] GENERIC_PATH = "/GENERIC_PATH" From 71fef2c437ca97bc7e303f6eadc615252ef78726 Mon Sep 17 00:00:00 2001 From: bart1e Date: Sun, 26 Feb 2023 18:11:34 +0100 Subject: [PATCH 038/338] 'unsupported operand type' error fix --- .../operations/cache_array_length.py | 2 +- ...rayLength.sol.0.8.17.CacheArrayLength.json | 42 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py index 8c1112d2d..1f8111bdb 100644 --- a/slither/detectors/operations/cache_array_length.py +++ b/slither/detectors/operations/cache_array_length.py @@ -81,7 +81,7 @@ contract C ) @staticmethod - def _extract_array_from_length_member_access(exp: MemberAccess) -> [StateVariable | None]: + def _extract_array_from_length_member_access(exp: MemberAccess) -> StateVariable: """ Given a member access `exp`, it returns state array which `length` member is accessed through `exp`. If array is not a state array or its `length` member is not referenced, it returns `None`. diff --git a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json index b2050508f..3323ff479 100644 --- a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json +++ b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json @@ -2,70 +2,70 @@ [ { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "66f0059f2e2608b9e532ab9f6a473aa9128f1e9f02fe16fcb960b4ae4970b2cb", + "id": "2ff6144814e406cadadd58712f5a7a8ef6ee169da06660d590e7bee37759fc98", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "8463e2cd88985588ad2426476df033957fb4f8969117b7649f1165244b86d2e0", + "id": "48a6388cf2193fdd780ea86cb3e588dfd3276182e209f3f2807d9927a5ba25bc", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "961db8345eea46c3814eb2c6f6fc6d1506a2feaa85630349266cff940f33a7ab", + "id": "562b7ae618977ea1d0a232d8af5edd81ce404b6844e864d0c4ab162a88142c71", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "aea0a11159dec6d660f39a09aa44b56ad0effb7ced7183552b21b69f0f62e0c7", + "id": "8f1aa2da0763f65179e90a2b96d7feb68c99aab60f227a5da8dad2f12069f047", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "d296a0fd4cbe7b9a2db11b3d08b2db08a53414326a91eeda1f78853c4d4c5714", + "id": "9c988bc3f6748fadb8527c9eea53e3d06f5f4e7b2a0c7c70993c4af758bbba47", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "db2bfdc710cfa1ea5339e1f14b1a5b80735c50c37522f983a220b579df34c5d0", + "id": "a1c39b4ae47535f3354d0bf26ea67d3b524efb94a3bdb2f503bda245471ee451", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" }, { "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n", + "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n ", + "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n ", "first_markdown_element": "", - "id": "f5085e5d1ddd69d59f60443b7e89ea5f7301ba6a0a42786624b783389474aaf7", + "id": "c57b54ebb07e5114ccb8c124fa3971b9385d5252264f2bf2acbe131b3a986aa8", "check": "cache-array-length", "impact": "Optimization", "confidence": "High" From d1804f3d01edb309f9632ac0ba67e0ca7e8fdce3 Mon Sep 17 00:00:00 2001 From: bart1e Date: Wed, 3 May 2023 19:20:05 +0200 Subject: [PATCH 039/338] Tests updated --- ...yLength_0_8_17_CacheArrayLength_sol__0.txt | 14 ++ .../0.8.17/CacheArrayLength.sol | 127 ++++++++++++++++++ .../0.8.17/CacheArrayLength.sol-0.8.17.zip | Bin 0 -> 7589 bytes 3 files changed, 141 insertions(+) create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol create mode 100644 tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip diff --git a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt new file mode 100644 index 000000000..a0ba35740 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt @@ -0,0 +1,14 @@ +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array. + diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol new file mode 100644 index 000000000..79858d182 --- /dev/null +++ b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol @@ -0,0 +1,127 @@ +pragma solidity 0.8.17; + +contract CacheArrayLength +{ + struct S + { + uint s; + } + + S[] array; + S[] array2; + + function f() public + { + // array accessed but length doesn't change + for (uint i = 0; i < array.length; i++) // warning should appear + { + array[i] = S(0); + } + + // array.length doesn't change, but array.length not used in loop condition + for (uint i = array.length; i >= 0; i--) + { + + } + + // array.length changes in the inner loop + for (uint i = 0; i < array.length; i++) + { + for (uint j = i; j < 2 * i; j++) + array.push(S(j)); + } + + // array.length changes + for (uint i = 0; i < array.length; i++) + { + array.pop(); + } + + // array.length changes + for (uint i = 0; i < array.length; i++) + { + delete array; + } + + // array.length doesn't change despite using delete + for (uint i = 0; i < array.length; i++) // warning should appear + { + delete array[i]; + } + + // array.length changes; push used in more complex expression + for (uint i = 0; i < array.length; i++) + { + array.push() = S(i); + } + + // array.length doesn't change + for (uint i = 0; i < array.length; i++) // warning should appear + { + array2.pop(); + array2.push(); + array2.push(S(i)); + delete array2; + delete array[0]; + } + + // array.length changes; array2.length doesn't change + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) // warning should appear + { + array.pop(); + } + } + } + + // array.length doesn't change; array2.length changes + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) // warning should appear + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) + { + array2.pop(); + } + } + } + + // none of array.length and array2.length changes + for (uint i = 0; i < 7; i++) + { + for (uint j = i; j < array.length; j++) // warning should appear + { + for (uint k = 0; k < j; k++) + { + + } + + for (uint k = 0; k < array2.length; k++) // warning should appear + { + + } + } + } + + S[] memory array3; + + // array3 not modified, but it's not a storage array + for (uint i = 0; i < array3.length; i++) + { + + } + } +} \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip new file mode 100644 index 0000000000000000000000000000000000000000..ab3d813718b45d438f91556934cc243e900beb57 GIT binary patch literal 7589 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 literal 0 HcmV?d00001 From 9cc616e4cc539a6479673d62565625d446532b0e Mon Sep 17 00:00:00 2001 From: bart1e Date: Wed, 3 May 2023 19:21:58 +0200 Subject: [PATCH 040/338] Old tests removed --- .../0.8.17/CacheArrayLength.sol | 127 ------------------ ...rayLength.sol.0.8.17.CacheArrayLength.json | 74 ---------- 2 files changed, 201 deletions(-) delete mode 100644 tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol delete mode 100644 tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json diff --git a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol deleted file mode 100644 index 79858d182..000000000 --- a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol +++ /dev/null @@ -1,127 +0,0 @@ -pragma solidity 0.8.17; - -contract CacheArrayLength -{ - struct S - { - uint s; - } - - S[] array; - S[] array2; - - function f() public - { - // array accessed but length doesn't change - for (uint i = 0; i < array.length; i++) // warning should appear - { - array[i] = S(0); - } - - // array.length doesn't change, but array.length not used in loop condition - for (uint i = array.length; i >= 0; i--) - { - - } - - // array.length changes in the inner loop - for (uint i = 0; i < array.length; i++) - { - for (uint j = i; j < 2 * i; j++) - array.push(S(j)); - } - - // array.length changes - for (uint i = 0; i < array.length; i++) - { - array.pop(); - } - - // array.length changes - for (uint i = 0; i < array.length; i++) - { - delete array; - } - - // array.length doesn't change despite using delete - for (uint i = 0; i < array.length; i++) // warning should appear - { - delete array[i]; - } - - // array.length changes; push used in more complex expression - for (uint i = 0; i < array.length; i++) - { - array.push() = S(i); - } - - // array.length doesn't change - for (uint i = 0; i < array.length; i++) // warning should appear - { - array2.pop(); - array2.push(); - array2.push(S(i)); - delete array2; - delete array[0]; - } - - // array.length changes; array2.length doesn't change - for (uint i = 0; i < 7; i++) - { - for (uint j = i; j < array.length; j++) - { - for (uint k = 0; k < j; k++) - { - - } - - for (uint k = 0; k < array2.length; k++) // warning should appear - { - array.pop(); - } - } - } - - // array.length doesn't change; array2.length changes - for (uint i = 0; i < 7; i++) - { - for (uint j = i; j < array.length; j++) // warning should appear - { - for (uint k = 0; k < j; k++) - { - - } - - for (uint k = 0; k < array2.length; k++) - { - array2.pop(); - } - } - } - - // none of array.length and array2.length changes - for (uint i = 0; i < 7; i++) - { - for (uint j = i; j < array.length; j++) // warning should appear - { - for (uint k = 0; k < j; k++) - { - - } - - for (uint k = 0; k < array2.length; k++) // warning should appear - { - - } - } - } - - S[] memory array3; - - // array3 not modified, but it's not a storage array - for (uint i = 0; i < array3.length; i++) - { - - } - } -} \ No newline at end of file diff --git a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json b/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json deleted file mode 100644 index 3323ff479..000000000 --- a/tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol.0.8.17.CacheArrayLength.json +++ /dev/null @@ -1,74 +0,0 @@ -[ - [ - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "2ff6144814e406cadadd58712f5a7a8ef6ee169da06660d590e7bee37759fc98", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "48a6388cf2193fdd780ea86cb3e588dfd3276182e209f3f2807d9927a5ba25bc", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "562b7ae618977ea1d0a232d8af5edd81ce404b6844e864d0c4ab162a88142c71", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "8f1aa2da0763f65179e90a2b96d7feb68c99aab60f227a5da8dad2f12069f047", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "9c988bc3f6748fadb8527c9eea53e3d06f5f4e7b2a0c7c70993c4af758bbba47", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "a1c39b4ae47535f3354d0bf26ea67d3b524efb94a3bdb2f503bda245471ee451", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [], - "description": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n ", - "markdown": "Loop condition at tests/detectors/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array.\n ", - "first_markdown_element": "", - "id": "c57b54ebb07e5114ccb8c124fa3971b9385d5252264f2bf2acbe131b3a986aa8", - "check": "cache-array-length", - "impact": "Optimization", - "confidence": "High" - } - ] -] \ No newline at end of file From 7eb270adeffffe08a3eb496ff62a298e7b5ccf8d Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 4 May 2023 12:53:54 -0700 Subject: [PATCH 041/338] feat: halstead printer --- slither/printers/summary/halstead.py | 103 ++++++++++++++++----------- slither/utils/upgradeability.py | 57 +++++++++++++++ 2 files changed, 120 insertions(+), 40 deletions(-) diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index b50575ab6..12e422fb0 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -10,11 +10,13 @@ N1 = the total number of operators N2 = the total number of operands - Extended metrics: + Extended metrics1: n = n1 + n2 # Program vocabulary N = N1 + N2 # Program length S = n1 * log2(n1) + n2 * log2(n2) # Estimated program length V = N * log2(n) # Volume + + Extended metrics2: D = (n1 / 2) * (N2 / n2) # Difficulty E = D * V # Effort T = E / 18 seconds # Time required to program @@ -27,6 +29,7 @@ from collections import OrderedDict from slither.printers.abstract_printer import AbstractPrinter from slither.slithir.variables.temporary import TemporaryVariable from slither.utils.myprettytable import make_pretty_table +from slither.utils.upgradeability import encode_ir_for_halstead def compute_halstead(contracts: list) -> tuple: @@ -42,18 +45,21 @@ def compute_halstead(contracts: list) -> tuple: core_metrics: {"contract1 name": { - "n1_unique_operators": n1, - "n2_unique_operands": n1, "N1_total_operators": N1, + "n1_unique_operators": n1, "N2_total_operands": N2, + "n2_unique_operands": n1, }} - extended_metrics: + extended_metrics1: {"contract1 name": { "n_vocabulary": n1 + n2, "N_prog_length": N1 + N2, "S_est_length": S, "V_volume": V, + }} + extended_metrics2: + {"contract1 name": { "D_difficulty": D, "E_effort": E, "T_time": T, @@ -62,7 +68,8 @@ def compute_halstead(contracts: list) -> tuple: """ core = OrderedDict() - extended = OrderedDict() + extended1 = OrderedDict() + extended2 = OrderedDict() all_operators = [] all_operands = [] for contract in contracts: @@ -72,9 +79,9 @@ def compute_halstead(contracts: list) -> tuple: for node in func.nodes: for operation in node.irs: # use operation.expression.type to get the unique operator type - operator_type = operation.expression.type - operators.append(operator_type) - all_operators.append(operator_type) + encoded_operator = encode_ir_for_halstead(operation) + operators.append(encoded_operator) + all_operators.append(encoded_operator) # use operation.used to get the operands of the operation ignoring the temporary variables new_operands = [ @@ -82,13 +89,21 @@ def compute_halstead(contracts: list) -> tuple: ] operands.extend(new_operands) all_operands.extend(new_operands) - (core[contract.name], extended[contract.name]) = _calculate_metrics(operators, operands) - core["ALL CONTRACTS"] = OrderedDict() - extended["ALL CONTRACTS"] = OrderedDict() - (core["ALL CONTRACTS"], extended["ALL CONTRACTS"]) = _calculate_metrics( - all_operators, all_operands - ) - return (core, extended) + ( + core[contract.name], + extended1[contract.name], + extended2[contract.name], + ) = _calculate_metrics(operators, operands) + if len(contracts) > 1: + core["ALL CONTRACTS"] = OrderedDict() + extended1["ALL CONTRACTS"] = OrderedDict() + extended2["ALL CONTRACTS"] = OrderedDict() + ( + core["ALL CONTRACTS"], + extended1["ALL CONTRACTS"], + extended2["ALL CONTRACTS"], + ) = _calculate_metrics(all_operators, all_operands) + return (core, extended1, extended2) # pylint: disable=too-many-locals @@ -115,22 +130,24 @@ def _calculate_metrics(operators, operands): T = E / 18 B = (E ** (2 / 3)) / 3000 core_metrics = { - "n1_unique_operators": n1, - "n2_unique_operands": n2, - "N1_total_operators": N1, - "N2_total_operands": N2, + "Total Operators": N1, + "Unique Operators": n1, + "Total Operands": N2, + "Unique Operands": n2, } - extended_metrics = { - "n_vocabulary": str(n1 + n2), - "N_prog_length": str(N1 + N2), - "S_est_length": f"{S:.0f}", - "V_volume": f"{V:.0f}", - "D_difficulty": f"{D:.0f}", - "E_effort": f"{E:.0f}", - "T_time": f"{T:.0f}", - "B_bugs": f"{B:.3f}", + extended_metrics1 = { + "Vocabulary": str(n1 + n2), + "Program Length": str(N1 + N2), + "Estimated Length": f"{S:.0f}", + "Volume": f"{V:.0f}", } - return (core_metrics, extended_metrics) + extended_metrics2 = { + "Difficulty": f"{D:.0f}", + "Effort": f"{E:.0f}", + "Time": f"{T:.0f}", + "Estimated Bugs": f"{B:.3f}", + } + return (core_metrics, extended_metrics1, extended_metrics2) class Halstead(AbstractPrinter): @@ -143,24 +160,30 @@ class Halstead(AbstractPrinter): if len(self.contracts) == 0: return self.generate_output("No contract found") - core, extended = compute_halstead(self.contracts) + core, extended1, extended2 = compute_halstead(self.contracts) # Core metrics: operations and operands txt = "\n\nHalstead complexity core metrics:\n" keys = list(core[self.contracts[0].name].keys()) - table1 = make_pretty_table(["Contract", *keys], core, False) - txt += str(table1) + "\n" + table_core = make_pretty_table(["Contract", *keys], core, False) + txt += str(table_core) + "\n" + + # Extended metrics1: vocabulary, program length, estimated length, volume + txt += "\nHalstead complexity extended metrics1:\n" + keys = list(extended1[self.contracts[0].name].keys()) + table_extended1 = make_pretty_table(["Contract", *keys], extended1, False) + txt += str(table_extended1) + "\n" - # Extended metrics: volume, difficulty, effort, time, bugs - # TODO: should we break this into 2 tables? currently 119 chars wide - txt += "\nHalstead complexity extended metrics:\n" - keys = list(extended[self.contracts[0].name].keys()) - table2 = make_pretty_table(["Contract", *keys], extended, False) - txt += str(table2) + "\n" + # Extended metrics2: difficulty, effort, time, bugs + txt += "\nHalstead complexity extended metrics2:\n" + keys = list(extended2[self.contracts[0].name].keys()) + table_extended2 = make_pretty_table(["Contract", *keys], extended2, False) + txt += str(table_extended2) + "\n" res = self.generate_output(txt) - res.add_pretty_table(table1, "Halstead core metrics") - res.add_pretty_table(table2, "Halstead extended metrics") + res.add_pretty_table(table_core, "Halstead core metrics") + res.add_pretty_table(table_extended1, "Halstead extended metrics1") + res.add_pretty_table(table_extended2, "Halstead extended metrics2") self.info(txt) return res diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 7b4e8493a..910ba6f08 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -325,6 +325,63 @@ def encode_ir_for_compare(ir: Operation) -> str: return "" +# pylint: disable=too-many-branches +def encode_ir_for_halstead(ir: Operation) -> str: + # operations + if isinstance(ir, Assignment): + return "assignment" + if isinstance(ir, Index): + return "index" + if isinstance(ir, Member): + return "member" # .format(ntype(ir._type)) + if isinstance(ir, Length): + return "length" + if isinstance(ir, Binary): + return f"binary({str(ir.type)})" + if isinstance(ir, Unary): + return f"unary({str(ir.type)})" + if isinstance(ir, Condition): + return f"condition({encode_var_for_compare(ir.value)})" + if isinstance(ir, NewStructure): + return "new_structure" + if isinstance(ir, NewContract): + return "new_contract" + if isinstance(ir, NewArray): + return f"new_array({ntype(ir.array_type)})" + if isinstance(ir, NewElementaryType): + return f"new_elementary({ntype(ir.type)})" + if isinstance(ir, Delete): + return "delete" + if isinstance(ir, SolidityCall): + return f"solidity_call({ir.function.full_name})" + if isinstance(ir, InternalCall): + return f"internal_call({ntype(ir.type_call)})" + if isinstance(ir, EventCall): # is this useful? + return "event" + if isinstance(ir, LibraryCall): + return "library_call" + if isinstance(ir, InternalDynamicCall): + return "internal_dynamic_call" + if isinstance(ir, HighLevelCall): # TODO: improve + return "high_level_call" + if isinstance(ir, LowLevelCall): # TODO: improve + return "low_level_call" + if isinstance(ir, TypeConversion): + return f"type_conversion({ntype(ir.type)})" + if isinstance(ir, Return): # this can be improved using values + return "return" # .format(ntype(ir.type)) + if isinstance(ir, Transfer): + return "transfer" + if isinstance(ir, Send): + return "send" + if isinstance(ir, Unpack): # TODO: improve + return "unpack" + if isinstance(ir, InitArray): # TODO: improve + return "init_array" + # default + raise NotImplementedError(f"encode_ir_for_halstead: {ir}") + + # pylint: disable=too-many-branches def encode_var_for_compare(var: Variable) -> str: From 34a343e36c5005ac4f7cc2dfc0a5f4d66ff96121 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 5 May 2023 13:42:04 -0700 Subject: [PATCH 042/338] feat: ck printer --- slither/printers/all_printers.py | 1 + slither/printers/summary/ck.py | 266 +++++++++++++++++++++++++++++++ slither/utils/myprettytable.py | 80 +++++++++- 3 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 slither/printers/summary/ck.py diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 6dc8dddbd..4e66351f8 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -8,6 +8,7 @@ from .functions.authorization import PrinterWrittenVariablesAndAuthorization from .summary.slithir import PrinterSlithIR from .summary.slithir_ssa import PrinterSlithIRSSA from .summary.human_summary import PrinterHumanSummary +from .summary.ck import CKMetrics from .functions.cfg import CFG from .summary.function_ids import FunctionIds from .summary.variable_order import VariableOrder diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py new file mode 100644 index 000000000..d896015b2 --- /dev/null +++ b/slither/printers/summary/ck.py @@ -0,0 +1,266 @@ +""" + + # TODO: Add in other CK metrics (NOC, DIT) + # TODO: Don't display all the general function metrics, but add those to complexity-dashboard + CK Metrics are a suite of six software metrics proposed by Chidamber and Kemerer in 1994. + These metrics are used to measure the complexity of a class. + https://en.wikipedia.org/wiki/Programming_complexity + + - Response For a Class (RFC) is a metric that measures the number of unique method calls within a class. + - Number of Children (NOC) is a metric that measures the number of children a class has. + - Depth of Inheritance Tree (DIT) is a metric that measures the number of parent classes a class has. + + Not implemented: + - Lack of Cohesion of Methods (LCOM) is a metric that measures the lack of cohesion in methods. + - Weighted Methods per Class (WMC) is a metric that measures the complexity of a class. + - Coupling Between Object Classes (CBO) is a metric that measures the number of classes a class is coupled to. + +""" +from typing import Tuple +from slither.printers.abstract_printer import AbstractPrinter +from slither.utils.myprettytable import make_pretty_table +from slither.slithir.operations.high_level_call import HighLevelCall +from slither.utils.colors import bold + + +def compute_dit(contract, depth=0): + """ + Recursively compute the depth of inheritance tree (DIT) of a contract + Args: + contract: Contract - the contract to compute the DIT for + depth: int - the depth of the contract in the inheritance tree + Returns: + the depth of the contract in the inheritance tree + """ + if not contract.inheritance: + return depth + max_dit = depth + for inherited_contract in contract.inheritance: + dit = compute_dit(inherited_contract, depth + 1) + max_dit = max(max_dit, dit) + return max_dit + + +# pylint: disable=too-many-locals +def compute_metrics(contracts): + """ + Compute CK metrics of a contract + Args: + contracts(list): list of contracts + Returns: + a tuple of (metrics1, metrics2, metrics3, metrics4, metrics5) + # Visbility + metrics1["contract name"] = { + "State variables":int, + "Constants":int, + "Immutables":int, + } + metrics2["contract name"] = { + "Public": int, + "External":int, + "Internal":int, + "Private":int, + } + # Mutability + metrics3["contract name"] = { + "Mutating":int, + "View":int, + "Pure":int, + } + # External facing, mutating: total / no auth / no modifiers + metrics4["contract name"] = { + "External mutating":int, + "No auth or onlyOwner":int, + "No modifiers":int, + } + metrics5["contract name"] = { + "Ext calls":int, + "Response For a Class":int, + "NOC":int, + "DIT":int, + } + + RFC is counted as follows: + +1 for each public or external fn + +1 for each public getter + +1 for each UNIQUE external call + + """ + metrics1 = {} + metrics2 = {} + metrics3 = {} + metrics4 = {} + metrics5 = {} + dependents = { + inherited.name: { + contract.name for contract in contracts if inherited.name in contract.inheritance + } + for inherited in contracts + } + + for c in contracts: + (state_variables, constants, immutables, public_getters) = count_variables(c) + rfc = public_getters # add 1 for each public getter + metrics1[c.name] = { + "State variables": state_variables, + "Constants": constants, + "Immutables": immutables, + } + metrics2[c.name] = { + "Public": 0, + "External": 0, + "Internal": 0, + "Private": 0, + } + metrics3[c.name] = { + "Mutating": 0, + "View": 0, + "Pure": 0, + } + metrics4[c.name] = { + "External mutating": 0, + "No auth or onlyOwner": 0, + "No modifiers": 0, + } + metrics5[c.name] = { + "Ext calls": 0, + "RFC": 0, + "NOC": len(dependents[c.name]), + "DIT": compute_dit(c), + } + for func in c.functions: + if func.name == "constructor": + continue + pure = func.pure + view = not pure and func.view + mutating = not pure and not view + external = func.visibility == "external" + public = func.visibility == "public" + internal = func.visibility == "internal" + private = func.visibility == "private" + external_public_mutating = external or public and mutating + external_no_auth = external_public_mutating and no_auth(func) + external_no_modifiers = external_public_mutating and len(func.modifiers) == 0 + if external or public: + rfc += 1 + + high_level_calls = [ + ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ] + + # convert irs to string with target function and contract name + external_calls = [] + for h in high_level_calls: + if hasattr(h.destination, "name"): + external_calls.append(f"{h.function_name}{h.destination.name}") + else: + external_calls.append(f"{h.function_name}{h.destination.type.type.name}") + + rfc += len(set(external_calls)) + + metrics2[c.name]["Public"] += 1 if public else 0 + metrics2[c.name]["External"] += 1 if external else 0 + metrics2[c.name]["Internal"] += 1 if internal else 0 + metrics2[c.name]["Private"] += 1 if private else 0 + + metrics3[c.name]["Mutating"] += 1 if mutating else 0 + metrics3[c.name]["View"] += 1 if view else 0 + metrics3[c.name]["Pure"] += 1 if pure else 0 + + metrics4[c.name]["External mutating"] += 1 if external_public_mutating else 0 + metrics4[c.name]["No auth or onlyOwner"] += 1 if external_no_auth else 0 + metrics4[c.name]["No modifiers"] += 1 if external_no_modifiers else 0 + + metrics5[c.name]["Ext calls"] += len(external_calls) + metrics5[c.name]["RFC"] = rfc + + return metrics1, metrics2, metrics3, metrics4, metrics5 + + +def count_variables(contract) -> Tuple[int, int, int, int]: + """Count the number of variables in a contract + Args: + contract(core.declarations.contract.Contract): contract to count variables + Returns: + Tuple of (state_variable_count, constant_count, immutable_count, public_getter) + """ + state_variable_count = 0 + constant_count = 0 + immutable_count = 0 + public_getter = 0 + for var in contract.variables: + if var.is_constant: + constant_count += 1 + elif var.is_immutable: + immutable_count += 1 + else: + state_variable_count += 1 + if var.visibility == "Public": + public_getter += 1 + return (state_variable_count, constant_count, immutable_count, public_getter) + + +def no_auth(func) -> bool: + """ + Check if a function has no auth or only_owner modifiers + Args: + func(core.declarations.function.Function): function to check + Returns: + bool + """ + for modifier in func.modifiers: + if "auth" in modifier.name or "only_owner" in modifier.name: + return False + return True + + +class CKMetrics(AbstractPrinter): + ARGUMENT = "ck" + HELP = "Computes the CK complexity metrics for each contract" + + WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#ck" + + def output(self, _filename): + if len(self.contracts) == 0: + return self.generate_output("No contract found") + metrics1, metrics2, metrics3, metrics4, metrics5 = compute_metrics(self.contracts) + txt = bold("\nCK complexity metrics\n") + # metrics2: variable counts + txt += bold("\nVariables\n") + keys = list(metrics1[self.contracts[0].name].keys()) + table0 = make_pretty_table(["Contract", *keys], metrics1, True) + txt += str(table0) + "\n" + + # metrics3: function visibility + txt += bold("\nFunction visibility\n") + keys = list(metrics2[self.contracts[0].name].keys()) + table1 = make_pretty_table(["Contract", *keys], metrics2, True) + txt += str(table1) + "\n" + + # metrics4: function mutability counts + txt += bold("\nFunction mutatability\n") + keys = list(metrics3[self.contracts[0].name].keys()) + table2 = make_pretty_table(["Contract", *keys], metrics3, True) + txt += str(table2) + "\n" + + # metrics5: external facing mutating functions + txt += bold("\nExternal/Public functions with modifiers\n") + keys = list(metrics4[self.contracts[0].name].keys()) + table3 = make_pretty_table(["Contract", *keys], metrics4, True) + txt += str(table3) + "\n" + + # metrics5: ext calls and rfc + txt += bold("\nExt calls and RFC\n") + keys = list(metrics5[self.contracts[0].name].keys()) + table4 = make_pretty_table(["Contract", *keys], metrics5, False) + txt += str(table4) + "\n" + + res = self.generate_output(txt) + res.add_pretty_table(table0, "CK complexity core metrics 1/5") + res.add_pretty_table(table1, "CK complexity core metrics 2/5") + res.add_pretty_table(table2, "CK complexity core metrics 3/5") + res.add_pretty_table(table3, "CK complexity core metrics 4/5") + res.add_pretty_table(table4, "CK complexity core metrics 5/5") + self.info(txt) + + return res diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index af10a6ff2..379d6699d 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -4,9 +4,17 @@ from prettytable import PrettyTable class MyPrettyTable: - def __init__(self, field_names: List[str]): + def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: True by default? self._field_names = field_names self._rows: List = [] + self._options: Dict = {} + if pretty_align: + self._options["set_alignment"] = [] + self._options["set_alignment"] += [(field_names[0], "l")] + for field_name in field_names[1:]: + self._options["set_alignment"] += [(field_name, "r")] + else: + self._options["set_alignment"] = [] def add_row(self, row: List[Union[str, List[str]]]) -> None: self._rows.append(row) @@ -15,6 +23,9 @@ class MyPrettyTable: table = PrettyTable(self._field_names) for row in self._rows: table.add_row(row) + if len(self._options["set_alignment"]): + for column_header, value in self._options["set_alignment"]: + table.align[column_header] = value return table def to_json(self) -> Dict: @@ -22,3 +33,70 @@ class MyPrettyTable: def __str__(self) -> str: return str(self.to_pretty_table()) + + +# **Dict to MyPrettyTable utility functions** + + +def make_pretty_table( + headers: list, body: dict, totals: bool = False, total_header="TOTAL" +) -> MyPrettyTable: + """ + Converts a dict to a MyPrettyTable. Dict keys are the row headers. + Args: + headers: str[] of column names + body: dict of row headers with a dict of the values + totals: bool optional add Totals row + total_header: str optional if totals is set to True this will override the default "TOTAL" header + Returns: + MyPrettyTable + """ + table = MyPrettyTable(headers) + for row in body: + table_row = [row] + [body[row][key] for key in headers[1:]] + table.add_row(table_row) + if totals: + table.add_row( + [total_header] + [sum([body[row][key] for row in body]) for key in headers[1:]] + ) + return table + + +def make_pretty_table_simple( + data: dict, first_column_header, second_column_header="" +) -> MyPrettyTable: + """ + Converts a dict to a MyPrettyTable. Dict keys are the row headers. + Args: + data: dict of row headers with a dict of the values + column_header: str of column name for 1st column + Returns: + MyPrettyTable + """ + + table = MyPrettyTable([first_column_header, second_column_header]) + for k, v in data.items(): + table.add_row([k] + [v]) + return table + + +# takes a dict of dicts and returns a dict of dicts with the keys transposed +# example: +# in: +# { +# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, +# "test": {"loc": 0, "sloc": 0, "cloc": 0}, +# "src": {"loc": 0, "sloc": 0, "cloc": 0}, +# } +# out: +# { +# 'loc': {'dep': 0, 'test': 0, 'src': 0}, +# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, +# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, +# } +def transpose(table): + any_key = list(table.keys())[0] + return { + inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} + for inner_key in table[any_key] + } From 16b57263f47b1628d8bf4a4ca08ae9d674be9375 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Tue, 2 May 2023 09:54:51 -0700 Subject: [PATCH 043/338] feat: martin printer --- slither/printers/all_printers.py | 1 + slither/printers/summary/martin.py | 114 +++++++++++++++++++++++++++++ slither/utils/myprettytable.py | 39 ++++++++++ 3 files changed, 154 insertions(+) create mode 100644 slither/printers/summary/martin.py diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 6dc8dddbd..c836b98d2 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -20,3 +20,4 @@ from .summary.evm import PrinterEVM from .summary.when_not_paused import PrinterWhenNotPaused from .summary.declaration import Declaration from .functions.dominator import Dominator +from .summary.martin import Martin diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py new file mode 100644 index 000000000..1bb59c4ff --- /dev/null +++ b/slither/printers/summary/martin.py @@ -0,0 +1,114 @@ +""" + Robert "Uncle Bob" Martin - Agile software metrics + https://en.wikipedia.org/wiki/Software_package_metrics + + Efferent Coupling (Ce): Number of contracts that the contract depends on + Afferent Coupling (Ca): Number of contracts that depend on a contract + Instability (I): Ratio of efferent coupling to total coupling (Ce / (Ce + Ca)) + Abstractness (A): Number of abstract contracts / total number of contracts + Distance from the Main Sequence (D): abs(A + I - 1) + +""" +from slither.printers.abstract_printer import AbstractPrinter +from slither.slithir.operations.high_level_call import HighLevelCall +from slither.utils.myprettytable import make_pretty_table + + +def count_abstracts(contracts): + """ + Count the number of abstract contracts + Args: + contracts(list): list of contracts + Returns: + a tuple of (abstract_contract_count, total_contract_count) + """ + abstract_contract_count = 0 + for c in contracts: + if not c.is_fully_implemented: + abstract_contract_count += 1 + return (abstract_contract_count, len(contracts)) + + +def compute_coupling(contracts: list, abstractness: float) -> dict: + """ + Used to compute the coupling between contracts external calls made to internal contracts + Args: + contracts: list of contracts + Returns: + dict of contract names with dicts of the coupling metrics: + { + "contract_name1": { + "Dependents": 0, + "Dependencies": 3 + "Instability": 1.0, + "Abstractness": 0.0, + "Distance from main sequence": 1.0, + }, + "contract_name2": { + "Dependents": 1, + "Dependencies": 0 + "Instability": 0.0, + "Abstractness": 1.0, + "Distance from main sequence": 0.0, + } + """ + dependencies = {} + for contract in contracts: + for func in contract.functions: + high_level_calls = [ + ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ] + # convert irs to string with target function and contract name + external_calls = [h.destination.type.type.name for h in high_level_calls] + dependencies[contract.name] = set(external_calls) + dependents = {} + for contract, deps in dependencies.items(): + for dep in deps: + if dep not in dependents: + dependents[dep] = set() + dependents[dep].add(contract) + + coupling_dict = {} + for contract in contracts: + ce = len(dependencies.get(contract.name, [])) + ca = len(dependents.get(contract.name, [])) + i = 0.0 + d = 0.0 + if ce + ca > 0: + i = float(ce / (ce + ca)) + d = float(abs(i - abstractness)) + coupling_dict[contract.name] = { + "Dependents": ca, + "Dependencies": ce, + "Instability": f"{i:.2f}", + "Distance from main sequence": f"{d:.2f}", + } + return coupling_dict + + +class Martin(AbstractPrinter): + ARGUMENT = "martin" + HELP = "Martin agile software metrics (Ca, Ce, I, A, D)" + + WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#martin" + + def output(self, _filename): + (abstract_contract_count, total_contract_count) = count_abstracts(self.contracts) + abstractness = float(abstract_contract_count / total_contract_count) + coupling_dict = compute_coupling(self.contracts, abstractness) + + table = make_pretty_table( + ["Contract", *list(coupling_dict[self.contracts[0].name].keys())], coupling_dict + ) + txt = "Martin agile software metrics\n" + txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" + txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" + txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" + txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" + txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" + txt += "\n" + txt += f"Abstractness (overall): {round(abstractness, 2)}\n" + str(table) + self.info(txt) + res = self.generate_output(txt) + res.add_pretty_table(table, "Code Lines") + return res diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index af10a6ff2..efdb96504 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -22,3 +22,42 @@ class MyPrettyTable: def __str__(self) -> str: return str(self.to_pretty_table()) + + +# **Dict to MyPrettyTable utility functions** + + +# Converts a dict to a MyPrettyTable. Dict keys are the row headers. +# @param headers str[] of column names +# @param body dict of row headers with a dict of the values +# @param totals bool optional add Totals row +def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: + table = MyPrettyTable(headers) + for row in body: + table_row = [row] + [body[row][key] for key in headers[1:]] + table.add_row(table_row) + if totals: + table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) + return table + + +# takes a dict of dicts and returns a dict of dicts with the keys transposed +# example: +# in: +# { +# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, +# "test": {"loc": 0, "sloc": 0, "cloc": 0}, +# "src": {"loc": 0, "sloc": 0, "cloc": 0}, +# } +# out: +# { +# 'loc': {'dep': 0, 'test': 0, 'src': 0}, +# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, +# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, +# } +def transpose(table): + any_key = list(table.keys())[0] + return { + inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} + for inner_key in table[any_key] + } From 2da5ee4caa89d57af91ec6c3c391151fde9aee96 Mon Sep 17 00:00:00 2001 From: Simone Date: Wed, 10 May 2023 16:34:05 +0200 Subject: [PATCH 044/338] Fix multiple try catch with same return var name --- slither/solc_parsing/declarations/function.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 57d7784e5..ed1fbcd7f 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -685,6 +685,7 @@ class FunctionSolc(CallerContextExpression): "name": parameters[0]["name"], "nodeType": "Identifier", "src": parameters[0]["src"], + "referencedDeclaration": parameters[0]["id"], "typeDescriptions": parameters[0]["typeDescriptions"], } else: @@ -713,6 +714,7 @@ class FunctionSolc(CallerContextExpression): "name": p["name"], "nodeType": "Identifier", "src": p["src"], + "referencedDeclaration": p["id"], "typeDescriptions": p["typeDescriptions"], } leftHandSide["components"].append(ident) From 2cdc5448acd2f2d4bcc3f78b5c71ef6695eb2472 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 10 May 2023 11:09:22 -0500 Subject: [PATCH 045/338] Make cross-contract taint optional in `compare` --- slither/utils/upgradeability.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 5be745bd6..f90dc1376 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -90,7 +90,7 @@ class TaintedExternalContract: # pylint: disable=too-many-locals def compare( - v1: Contract, v2: Contract + v1: Contract, v2: Contract, include_external: bool = False ) -> Tuple[ List[Variable], List[Variable], @@ -185,10 +185,12 @@ def compare( elif any(func in written_by for func in new_modified_functions + tainted_functions): tainted_variables.append(var) - # Find all external contracts and functions called by new/modified/tainted functions - tainted_contracts = tainted_external_contracts( - new_functions + modified_functions + tainted_functions - ) + tainted_contracts = [] + if include_external: + # Find all external contracts and functions called by new/modified/tainted functions + tainted_contracts = tainted_external_contracts( + new_functions + modified_functions + tainted_functions + ) return ( missing_vars_in_v2, From 10641851e738d7f3f27b0a851612c0b24a7efb9c Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 10 May 2023 11:53:06 -0500 Subject: [PATCH 046/338] Update test --- tests/unit/utils/test_upgradeability_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/utils/test_upgradeability_util.py b/tests/unit/utils/test_upgradeability_util.py index e367a3eed..86ae0d675 100644 --- a/tests/unit/utils/test_upgradeability_util.py +++ b/tests/unit/utils/test_upgradeability_util.py @@ -30,7 +30,7 @@ def test_upgrades_compare() -> None: modified_funcs, tainted_funcs, tainted_contracts, - ) = compare(v1, v2) + ) = compare(v1, v2, include_external=True) assert len(missing_vars) == 0 assert new_vars == [v2.get_state_variable_from_name("stateC")] assert tainted_vars == [ From af7279a6bf5bba57d8a48cdbc78d79551adf6f18 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 10 May 2023 11:54:09 -0500 Subject: [PATCH 047/338] Update docstring --- slither/utils/upgradeability.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index f90dc1376..37c5301e2 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -107,6 +107,7 @@ def compare( Args: v1: Original version of (upgradeable) contract v2: Updated version of (upgradeable) contract + include_external: Optional flag to enable cross-contract external taint analysis Returns: missing-vars-in-v2: list[Variable], From 8408788e8e3ce74c9d34d7bf94bc200067b33f27 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 11 May 2023 10:59:09 -0700 Subject: [PATCH 048/338] chore: add to scripts/ci_test_printers.sh --- scripts/ci_test_printers.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index 61994b337..d13932b81 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash -### Test printer +### Test printer cd tests/e2e/solc_parsing/test_data/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,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,human-summary,inheritance,inheritance-graph,loc,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 From d682232b46df040fb799df56f3b51e5804d3af9d Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 11 May 2023 11:01:12 -0700 Subject: [PATCH 049/338] chore: add to scripts/ci_test_printers.sh --- scripts/ci_test_printers.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index 61994b337..7ed2b6202 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash -### Test printer +### Test printer cd tests/e2e/solc_parsing/test_data/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,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,halstead,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 From 0b7257209dd09b1d877ec40870dd55eaf8ab10d1 Mon Sep 17 00:00:00 2001 From: bart1e Date: Mon, 15 May 2023 21:01:04 +0200 Subject: [PATCH 050/338] External calls handled + output printing changed --- .../operations/cache_array_length.py | 16 +++++-- ...yLength_0_8_17_CacheArrayLength_sol__0.txt | 18 ++++--- .../0.8.17/CacheArrayLength.sol | 44 ++++++++++++++++++ .../0.8.17/CacheArrayLength.sol-0.8.17.zip | Bin 7589 -> 8898 bytes 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py index 1f8111bdb..da73d3fd5 100644 --- a/slither/detectors/operations/cache_array_length.py +++ b/slither/detectors/operations/cache_array_length.py @@ -7,7 +7,7 @@ from slither.core.solidity_types import ArrayType from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables import StateVariable from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification -from slither.slithir.operations import Length, Delete +from slither.slithir.operations import Length, Delete, HighLevelCall class CacheArrayLength(AbstractDetector): @@ -119,8 +119,10 @@ contract C # - when `push` is called # - when `pop` is called # - when `delete` is called on the entire array + # - when external function call is made (instructions from internal function calls are already in + # `node.all_slithir_operations()`, so we don't need to handle internal calls separately) if node.type == NodeType.EXPRESSION: - for op in node.irs: + for op in node.all_slithir_operations(): if isinstance(op, Length) and op.value == array: # op accesses array.length, not necessarily modifying it return True @@ -132,6 +134,8 @@ contract C and op.expression.expression.value == array ): return True + if isinstance(op, HighLevelCall) and not op.function.view and not op.function.pure: + return True for son in node.sons: if son not in visited: @@ -173,7 +177,7 @@ contract C if not CacheArrayLength._is_loop_referencing_array_length( if_node, visited, array, 1 ): - non_optimal_array_len_usages.append(if_node.expression) + non_optimal_array_len_usages.append(if_node) @staticmethod def _get_non_optimal_array_len_usages_for_function(f: Function) -> List[SourceMapping]: @@ -207,8 +211,10 @@ contract C ) for usage in non_optimal_array_len_usages: info = [ - f"Loop condition at {usage.source_mapping} should use cached array length instead of referencing " - f"`length` member of the storage array.\n " + "Loop condition at ", + usage, + " should use cached array length instead of referencing `length` member " + "of the storage array.\n ", ] res = self.generate_result(info) results.append(res) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt index a0ba35740..63d4b883c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt @@ -1,14 +1,18 @@ -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#47 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at i < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#36) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#78 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at i_scope_22 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#166) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#16 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at j_scope_11 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#108) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#88 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at i_scope_6 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#79) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#105 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at i_scope_21 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#160) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#112 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at k_scope_9 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#98) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#59 should use cached array length instead of referencing `length` member of the storage array. +Loop condition at k_scope_17 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#132) should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at j_scope_15 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#125) should use cached array length instead of referencing `length` member of the storage array. + +Loop condition at i_scope_4 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#67) should use cached array length instead of referencing `length` member of the storage array. diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol index 79858d182..704d6bed9 100644 --- a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol +++ b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol @@ -10,6 +10,26 @@ contract CacheArrayLength S[] array; S[] array2; + function h() external + { + + } + + function g() internal + { + this.h(); + } + + function h_view() external view + { + + } + + function g_view() internal view + { + this.h_view(); + } + function f() public { // array accessed but length doesn't change @@ -123,5 +143,29 @@ contract CacheArrayLength { } + + // array not modified, but it may potentially change in an internal function call + for (uint i = 0; i < array.length; i++) + { + g(); + } + + // array not modified, but it may potentially change in an external function call + for (uint i = 0; i < array.length; i++) + { + this.h(); + } + + // array not modified and it cannot be changed in a function call since g_view is a view function + for (uint i = 0; i < array.length; i++) // warning should appear + { + g_view(); + } + + // array not modified and it cannot be changed in a function call since h_view is a view function + for (uint i = 0; i < array.length; i++) // warning should appear + { + this.h_view(); + } } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip index ab3d813718b45d438f91556934cc243e900beb57..dafdfc43167f9eb622fed98bdc69e91d02f89dfa 100644 GIT binary patch delta 8644 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 delta 7346 zcmV;j98KfGMWs6%P)h>@KL7#%4giChqgIY!eB$#Q002XU0RSkIfg&rBM%I4~x|0Xb zonxsj?@8N(;;rrxSnXW%0tyU6{_#j_sxY3G^IcK{_+=h`^KN#!Cfgo&s6PX9EuwI# zgAu&K6n+ufOLfDmHieMl?DgODWIf;~fe^4oiI#9Bn3F7!ls0r6^vxAu`oeQ^^hv!h zyIj;_JWP@ydYJOwkgsidE8c&tdJ6#n%6S=Kvh=YhKFp#hOs?0nUmE1mY)i+N(WFrD z)kiPc7-bz`%`>a00_>jX_?j zeB;19j(CTj@Z)0>gsQxGb?e2DFX;#h{yf~QcTkv6|=ev~P023qPD*bFe zGkGWV1oEoV6Uh}WlVEnM`HJ-|I zP!OSk65uoj<^?UbUsyI2k(+%r7up?Iz}Ub#B63rgV2w0HzU+Uv#W6!hR7_+(tm3h* zU{<A zcQ5BIa6q_aPi%iRkp1k-4C>y@uxf-+ptwqYo-)OvlNE?Q_r(4+?{m8R)Ur`6_GMRO z0bZuRp>IJoLq5r?w_DLxGtzM@((5)(3L@QGiT+A}$LA&0O9EBXakung;M~kpQ_&}3 ze)K>o-6t30vk77={cfax!+KHF#J~TwGn`IMgOm5JMcjXT1{{^^>1_A%#r%)UBO~y9 zhsvPj93C+$dP@b@8Sep801V&KSy&)>e&SW-fk_DQ?1%(ZxJ;&iz)jMoO%%&Nr0Ot7 z`)G`pdApZBDp27>tmhqi7vC**r4+uKG(&6t=UQtmuHYj34h?wY$C^u`hJgHLsL~5x zK9@z!XNaq5c*&}NP;Nv+$gAxuh@|V8TBbmS74DB%eBb3?R1@A?1WTN5<}2i+&n)%Y z;6v7@tX2Rivi>V{hlUq+msaTCB3OJDH4_7ulHPxbDMl%gj?laG|E?6#o3KCQbc7zr zdn8*^>{s%?=HLl-n?$B5&lq1Q;JP1}1+~m1@;(TGH~mjX#0(@|moHK#lPs|u+P|9w zSjlGA;aVi|`q-JCi3{}asUI;26e@Pqap2xZJ~JQ{ZI&K{=U?Uv;3x(2bL*O@#Tj|S z(?WkEK~=x_0jtyD?xI~!h%oH!bN2$${B|IYsE)YG&Gyzpse!s1_SY#RMit%XRX%yb zxK^|XdgFJ1=_J(Yi3wcFq0GBq22;PE}>q(FmW@K?eyxFR}8cDXT&1YTJqHz5e(hzx;%!q$@ z63+NrP8yP}e%eQGvlN$1whWo#fD?zWLDJrah|2E~hOpofN)3}#n3CLm>V^!Ls`E`U zjS4{Qoemotjnbb1H0?&~P8!=t6Th>dO;NB&O{Zi;O*q(9Ui~l@DKYQLW5dmMhsc=H zFQ&TQgTD7D+&TY-@I1u~K9>yQWu1T3JY6sV$U-Kd&}esY;Ns>ALqP*W2)ODWZuE!t zJolcbQW;gun}gyA)WOg*k#2ek=AMkp8F_<6(Sdd1pcKF+X_aVDkmZ%y`GkPvu~lp8 zH-c@|7JGq|>|Ad0sO)e|ttZhbek5B;u7#0qxt}JsKoG%s=K{H#lOb;b$OwNz8JZav z8RQPk+$etBy9mW7&U;6Rn1a>dA`?aB*Qj4!bR5DL8zbyqn4B>lNUl`~WD`?vH#??w zd7q0QEtV++>EpRX^POg4aPS~2p1dDtQD>HYPCoU+Jf=~ zoV*=PO*~ou*t>0c0i7cHLUMl?3>!WUNLz*N=o@bZw2JR$4rLF`h7)#cr>l6W5ckBF z-y|mqnM$ife1*`ccFU~4>p!F6a&DKG_%8;oRH`^J{XPlTh;Pcc2SyBcwJS1~aVW_O ztv@+=02AvPYZ7Pw57RPl4|IlrhqDnNIO`8nca!&1FXnm= z1iyu(Bc^s79v_LQa{}#}+RjN=16`$IYlP+=HBpP!<+zXy1CV3DR-3-B!r0n!qc|>} zp&6V`O4@^m8)V}M zpKE@PK^#asdXY1VVjLj&^t6eIa(Z{Q#qI>jMJ2y%GoP^FNqV$)v)Ht2R}F}G7qOvF zic@YIzG5SRPWwe)8y{}Q+oIZ5N-SkWXM4H47F6c#&I*a+#XMQal#UT!9#_+E08XdF zSAR^VdPebq7yN(ph3SLgxR-mGg4TFuiI0`d8A!-&)OxB2TCb}{@JTK}>W1!_N?*Pi z%W#j^Tqf`k0{NKDq%phOv+l1VK&k1N%K+hbr_o}^&Vp~6YTUr)-D2Ig$Q+Z&|NSr8 zZlE&vS{U84V-B($bKWOcFKml%893qz;&0;8WNXy5h}?hAa#tZOGS~R!h{CS8cE&N% z^CNE}x-d^d&k6wSaHok=gu6>Dm?*bW4;CKz1tGs);16p@8qZ@M2vC(l9Y>oCQY-|R z+~M;^z6sjGAoM(PppB3QqhP`4BhUj@QX`Q)@3Y;FmU*RyJ|4}exwAkFaB|RSZigK; zdFe-j1i^p0-;cclMnh&abfNxz10go}w?BZWr7yd#Bd@rx6~87oAX487pvN(@bNoPC z@Zm&e#I!>B66OO<%?J#W_d+uPWQ3|{7o3?*3WX@-*aY@((ZIk6xbLvm6SEX@g+=^`YUdZsY-UP$DL_JXX}N~DS-bY zuM&T=)Ewzfavvhk?byTj!zb*9O8#^_TUc38_w{LPavnIQ7JN~+*Z(E~kRCXbf%Jd6 zr!8I}jPu)AR*-GA!V7MW*iKPXoDWp+{eqh~c8mTJzC-9)Up>xQ8DTEBS4Ri{ysTgL z0mbdFhOP*7rXp|I8fq(dee+{se}0T;mfnBMI5L21PBL-=X)*NaSW!jonwFShQW>cF z!k$G7&@Ju_W~X+9P53*P93$G}&45W=@}GC2<6rCYdpe~LGx>F?44)g-K(o0+zRobz zy4ps;*A4Q(D3OT99O$BKoJW|%cSdzX+34tUq#6vRX|nH-@%9C*?;>N`pGMRHP^N#T z#x)mi`URTGkiwmhL=r3pvz%$e^NKz0<|}l;V)mHrJC?B6iN)R zRiiJR{8m>KR)km5f4E;$YOvzU?Z^u&F&qcE1H5${?yVw#A&_o4;HGD=OwmA3Tb*MN zwm~i+@@;pDD77&c$1@t8iiX1hhOU1nk2BDaMev+m=*FzEPvqQ2k5db?x1)Bhgb9qC zn0Ix9{0hL(6IQ<7ayVaAkB=8RJ(C;Vw)8h?7ucRUrUq-%(#()yJ6nIuB!ZwYy%KVR z<=Osu<9;gEn~Vb27kyS$uP zSeGAJE2}7h;!oNFlBgp@0>c!f=Yc_;eh97{1XF|jyh>f+Bif;SDanv4X~j{~k2qZ+ zUjSGjDQ$SmdTz|LkO-43a?^h=3VYV^HAAz`(Nfsp*cvie758oq;zgDzBWZ#SZoo#1 zct4YkzfW@9ikL<&Qiw7>uOzf0*2|$hFiwe5`5tYU6EW9z`@>Ytah(UN@+G=}3rJ7Z z$4EfuWU-+M+W0td$HP---suW4*hfr!*X4B6ke*Ei*Q8@!Dy1+B3P$y%z z`9FS?%7+J?^~0P$KKy^@tZ+NSYQVisjW1?izGooeeHO9`pkMz&!BR(seES!{ARd{V zw`)yOol;K%yxXcG7PK8?gZi23RKu|PmJa<^^klBhN&E%nsMSu+^^^)n-_Q_REhK*^Dn?%>xMTy)bkSYHqm^%b z#Q~D8>ex80ylJJnCfX9F^ zP7MMw5kB8C7Gwpl|x%P{vpgb9vn zxe%T(IrqE^?#F`$(n8SZ!p&S-X=D?#UmV$fw0mpa8f9IFsUbr{wvcBhOx>=5VD$!s zt4ZA@Gp?S)&`F2{5^;&pbfcK72Ak^12?Hr@M) zpE;*RJ>l&WGG=)xgMKElS3yRwn(HRReKU~5NrT# zvHpJTz=Y(*y6dA87q- zYQpz(!iQr|BZCs~0w)Y1%AqRAi=#eev#%g@71Zk6m489A`(SPn0n(b@A&u*cYhl~H zr&$(t*3iPfd$D8&J*CpELia>mV5!SMM5H*{1#voeOiA|K zcX0tLb3AvcENe-Sn~Us31(hwE!rW!*gEmWF$)#l~Xjo1*|5A zu#j6h-&I43VTUTc(dc~#>DYoTMIa&sx?gZot-x7+45Z7yjzW@3na`J&&W5|C* zyS|^RtKgbC>8dk`R|CpWQegzGwAXFkp>OQK_Bc=xc?Zxj*l0o!KZ>F!inQh-r8!<(HbwQ?P7CLTdx>ORhF;wd8?}74#nylJTKo*^ zfVXOnxpnNk1mNt^<*m;MhUhH-nBp3@hZTSn35OZ48QBBI(nB2L#7X;Ed6=ttSK1bF zPWqf{x(4~oAv|2yRn_^T_XLrqoSCZ&*h9$wFHMEFplltDHDG26doYD|BGpReY-yjA z8S|;IzEj?GgQYhZkiRaZiVuG#1l!Vu%inM7AKzc`R_;P>@!6Lh)&;3_SOILMU+Yv_ z1l8!5FP)$B{nETcS%CG`gTS;fczHAX*d}g(+bOi*N+rZ=|1fp=nrWmUHBBl@3m;!q z^a2jRRQM_0c%xT$n^IxGY7M?0X%y(hy`;LG1tifyy%P>L+ z55FDDq28HJjg`&m{SiAV!rXT{I8$7p5=G(B%^Z7`;vTL!A94!-I ztv$hXfQ!1Fxo5Ax3{+{c+p?Kh0mjQ z6bowkVS22)N=>^$WK?f7HN)Z(VmzHMmReR~MrahcTf=Q1SoiZH0PS%}xmOw|xe;n( zr*_6zg95sDo=E_3tWk?&?w&>!Y&iosMvjnI-!5E&$)DDl>~_PXuHF6@Fw5LG|Na1T&ojy3{V~}tm>TjUzXt$7vs@6VC857Y)A03^TI@dR3wy-;F?S~_r+EN=8w3pz;nN*OE&_o5~kFCUTbZF#(^It@SvURX# zzqKQku~VJUr_VSCAd~q;ah|o8*-ch52iMz!uOzcMzi6*jJvq&RHw51+tNQ_ExOPZA zkb{KRc@^Lj$grA~*3W%7lMF1Yv!G~Vy9a9{QOJLlTlP6&36On?^mig>?{a!_^=Z;3 zG7y;PHpM~GGE=n>X}*}xpiL^?uGfFa4mH3QbSlEN%cgS&!VYA;p_Z$IhuGxji9m2e zzI2ae5#}Z()ls0!O#qyl=DWcO=5pZ?J5qfxr4J@|FtB{IGYyon$B)e0ZLgqgG*X#= zkMw^&icccyW9HAT9~q22*YhS_QTOKS|IO>2Ar9yVt7HofHuL?*pY>~pLGjuri-vQ? zfWKIe-jmKeip>t)KaHA5EHwL9Ard>+M+tt_F0;H&Xpi_Qj_3H_x)_ttGoUxpi361C z6tP5H^QV)cz5DI#EZzHJ^(*~qf61Zg-rawvZ`MF0gCur#24Z2>%oW>`U?-Y-u}d&E zg1;>5spdjb96`hz{qnt#_SYHv*E)X8jCVex++6!Jv4aMYXzr9_`_6%(#c#DwW6b-H zN}#DE=6DG=T4BMo^TX&#g&}btgzbp5m8AF0Up<|4dU1*fg0=ft?R(*&nL@LrklKHw zQ133DobicMr^9l(ZZBt}oSe4$_01H#blgSAwJM?(%I0ddt=xT>iXsOXJ<(dGgR!gm zp3j^WW5Ky{1V|bpP;#4hv_el`IUc)$iIOA5huajmclXuE(MS_-=dt(=-R|JdP2TL z-a`cgB)aSndhGrUQMDM0bRb#1L+a$ZLR8J8Kl=vaWm#SZ`q9<`ti;6mEt?`In}brD z0lAQp&Psp#R1tdCF@CT}o>XJLf$!4wODF%FShgZX94TUX8b?&u#HZwlNz+uE$#b8rckkA{G#$ zZst&xPt6oRYrkLCA&BB9#2B4#xUI0TAv%LNJ<9@&+~SpCgoZ(6GJbzJ%CVSLC7@zK z0~4wfYsR(zJBpJ;c}Wm@gGh@1-35-9_c3tNvh3Kn6n^ZQ9KW-HufdtJMtifA2~6S9yLmJWJ(B*L5Q zU`cxm2CEjhhWFI!h2(z$coGN2p(Z$fT|hRe^HSAoz*%FL&_vRblWdaRqQEKze4?11 z>=5n~@&iH%N=kH13g_1*bbdJ*_;(z?e*PrRN_O{q`c>LE+CC4Xuh9pm=f?B?O~@ZK zLjVocl}iqsk-qpkV)C3#gc9!reO zP)h* Date: Mon, 15 May 2023 22:14:22 +0200 Subject: [PATCH 051/338] Fix yul function calls --- slither/solc_parsing/yul/parse_yul.py | 28 ++++++++++++++++-- tests/e2e/solc_parsing/test_ast_parsing.py | 4 +++ .../test_data/assembly-functions.sol | 11 +++++++ .../assembly-functions.sol-0.6.9-compact.zip | Bin 0 -> 1537 bytes .../assembly-functions.sol-0.6.9-legacy.zip | Bin 0 -> 1403 bytes .../assembly-functions.sol-0.7.6-compact.zip | Bin 0 -> 1510 bytes .../assembly-functions.sol-0.7.6-legacy.zip | Bin 0 -> 1378 bytes .../assembly-functions.sol-0.8.16-compact.zip | Bin 0 -> 1528 bytes .../assembly-functions.sol-0.6.9-compact.json | 9 ++++++ .../assembly-functions.sol-0.6.9-legacy.json | 5 ++++ .../assembly-functions.sol-0.7.6-compact.json | 9 ++++++ .../assembly-functions.sol-0.7.6-legacy.json | 5 ++++ ...assembly-functions.sol-0.8.16-compact.json | 9 ++++++ 13 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/assembly-functions.sol create mode 100644 tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-legacy.zip create mode 100644 tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip create mode 100644 tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json create mode 100644 tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json create mode 100644 tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 35d5cdd9d..978859a53 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -181,7 +181,7 @@ class YulScope(metaclass=abc.ABCMeta): def add_yul_local_function(self, func: "YulFunction") -> None: self._yul_local_functions.append(func) - def get_yul_local_function_from_name(self, func_name: str) -> Optional["YulLocalVariable"]: + def get_yul_local_function_from_name(self, func_name: str) -> Optional["YulFunction"]: return next( (v for v in self._yul_local_functions if v.underlying.name == func_name), None, @@ -252,6 +252,10 @@ class YulFunction(YulScope): def function(self) -> Function: return self._function + @property + def root(self) -> YulScope: + return self._root + def convert_body(self) -> None: node = self.new_node(NodeType.ENTRYPOINT, self._ast["src"]) link_underlying_nodes(self._entrypoint, node) @@ -271,6 +275,9 @@ class YulFunction(YulScope): def parse_body(self) -> None: for node in self._nodes: node.analyze_expressions() + for f in self._yul_local_functions: + if f != self: + f.parse_body() def new_node(self, node_type: NodeType, src: str) -> YulNode: if self._function: @@ -325,7 +332,10 @@ class YulBlock(YulScope): return yul_node def convert(self, ast: Dict) -> YulNode: - return convert_yul(self, self._entrypoint, ast, self.node_scope) + yul_node = convert_yul(self, self._entrypoint, ast, self.node_scope) + for f in self._yul_local_functions: + f.parse_body() + return yul_node def analyze_expressions(self) -> None: for node in self._nodes: @@ -390,7 +400,6 @@ def convert_yul_function_definition( root.add_yul_local_function(yul_function) yul_function.convert_body() - yul_function.parse_body() return parent @@ -809,6 +818,19 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[ if func: return Identifier(func.underlying) + # check yul-block scoped function + if isinstance(root, YulFunction): + yul_block = root.root + + # Iterate until we get to the YulBlock scope + while not isinstance(yul_block, YulBlock): + if isinstance(yul_block, YulFunction): + yul_block = yul_block.root + + func = yul_block.get_yul_local_function_from_name(name) + if func: + return Identifier(func.underlying) + magic_suffix = _parse_yul_magic_suffixes(name, root) if magic_suffix: return magic_suffix diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index a561343de..ebdd04d9a 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -453,6 +453,10 @@ ALL_TESTS = [ Test("complex_imports/import_aliases_issue_1319/test.sol", ["0.5.12"]), Test("yul-state-constant-access.sol", ["0.8.16"]), Test("negate-unary-element.sol", ["0.8.16"]), + Test( + "assembly-functions.sol", + ["0.6.9", "0.7.6", "0.8.16"], + ), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/assembly-functions.sol b/tests/e2e/solc_parsing/test_data/assembly-functions.sol new file mode 100644 index 000000000..c7b1c17d3 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/assembly-functions.sol @@ -0,0 +1,11 @@ +contract A { + function foo() public { + assembly { + function f() { function z() { function x() { g() } x() } z() } + function g() { + f() + } + g() + } + } +} diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..10b6ee248058585c51cf6277ed5477a09f86838b GIT binary patch literal 1537 zcma*nX*|;n00;2@Vn#Wl#*;Z09Ue!hJnsA4M2faOq{SLFTedMW%q^<9a+H!)dI}-o zVeX@Oh{D>e!^e?pJ?{G`kDm9>=kxr2FMh9nZ@=yc5m8HE4^g}|^~I9?0s=#Ex>qSAqJ$_I@Bsh@ z0GKBy;|;eBgA4n6t4*cyJBWdrO)3euJrpfe`IH8E{S{k_JD*@!*|G6I7x#HRWUe?V zE|u$f%;x4eJ=-tfQiC55#T$FtgA)j>itJL*prS>rzbR1&?SuQOj}Md-cAX5q_e+}1 zfgT_)9;g~`GmlyjdufNrC(D_{D1C9v<)Q=DQh8rGsnW_8a`JmyHcla|HCmR-2-5-w zr>tk8Ixi&MkcsikKm@^_87JFpfyvYzX?sAOx8~qP*cT{VEp9kCumGL zOB-JKI@<29IK3dY6#tU7JdWU~tUTqk7^%ZuJ3V99kcJuhZXXqpA;F)J)L7AI%ie_d zJAP2*d;2K4m6(b3)o#NBGJH`r*yN7fRXx+tJR$&5Xf0s*LkOy>Y0o*>L6PBkhifo; zk+{kW~X2#hj^29l*Nu3_3_pv#)N&MV#7IZ+FO(M_L38PHC9#6G456bkNo8D>eG zVk0$NYOV66(%e#}*&aomJ8Vrv+DTw5B*poLcOdaePa}$gP1-N*w%SE(znMd;$eTD{_a2K`5!w3p4pg2c89R8`|ZlHOU+EB_{2?HNPBIL7t5-5&lM-;HZR4cHmD(Xk*?^ zd&Jqe7Opgxyl2mr2FXs&K*B9OOjB#BdRXg>3sPgB|8Ogk(G6`cRvb8g)7e9`{!9jU z_3#AcIGkwqwpjFY3fw0(RU;F5V4ysmE8EWa>cp5bP0o;f6{(kyI8#%D=03vIMQMT4 z3Bnjz23WKsbuXN5VZ5;dtM13s)p)O0KgFCtbSZV&Q_9|3fhPDZ57x38X}G6};a@BL z9cn9I(^lajboJsD;#`d zg5eEh!LpJe!XF_*TSrkVP;=*FjJkJJJm=WR;^;x~Fiujsf(Zz^sfiv0@hY_iGmzD2 zXj!YoHF4qwILHU2s((CI%d7456Lu!Iq+s#t^2MTaW64`@q=lZBD>4%HZW=t^$mbV@ zIn|F3@5g9cuB^D1CCP@3ye4CL3S>c#itWDRccSAI;f8np#yXui@Mk$Wr4#f`J z@?mrrvLLJb`ts6vIa6%(D{DNH#QLs)*L%#1+Ueuu*1ID>dn`r%8|7V>{|y85bN)Zk U?g+5h&j)C?sNK!ng&qL@0g`UfH~;_u literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-legacy.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-legacy.zip new file mode 100644 index 0000000000000000000000000000000000000000..b429bc3e35436fff28f2da46365ac4367ed774e7 GIT binary patch literal 1403 zcma)+YdF&j0LK5zZEl&{Fqg@3iQJ+ilFg9YRI9P5+@@jJmJP8KVI@R*oP!>8aa=+S z2SY+9=Dtl1%{Am+ZmlTd)cJm%=e+NS-}8QWzy2_2Az>tN05}M+nN_&qcii?4VE~Yj z0{{a60Q_k*0tp`$V-y%k4u~L9$TVXbCCrx)eU(Cu@b#w#1QVkO#vwEcSzK5I@CJZ* z0I*3;4l>_04}UT^P;V`r*Fh%gv}!Q!orfXdBeWLi(a-jX^f6U`+1WYPrX;Q)#$`=b()9EVfglsj5ua#{~&a*?x!hFA-$MHkU7 zw$hin8Dy7(Df$YpwYJwdq_?19ZLg~(@D`;BYBSY;uyGdATY`4`_K`bEkE1rD)(DYq zFUkeHgp;`lF3pxBLJvLCAhlJbuNZl!-W92-qTBY_O18tv#Ww30rVJ7ujvm>`j2bRq zU|2fdZdI;LD2moWuj7%YPsOTnqmG(`7T_0}l0I^ys;{Ovj;b27?D83KA$9~)6?MA9 zEPi|-7qdJc!yz??i|;}L_59>Ls=!J?5%==Ms%EG@o+C57ZJ+qQ>-sT#Q(}Mqr9oNd zr;H1iv81*as98e8g1*%Lj^k8d1FAKvbWIwZQFGWp(-Y5i@V1(Fnrsl+NVy!OC=pmP zJnpqV5=iQ@C$-(JSUyxHJgtto)ZErH+aSYH95dB8XH63XgDqWeH(JTB>(y&Cxo9Nd znHvKal8Ae(;bcEo?6fa*7n*0s$Iq_VzBJn|0yWSG#P9R#AG{7Mi9-3R?h>K?G?^?A z6=$+mvGllBTzKPaabl|eGXoprXiS23!`GD~7iCzK@3&d+t8WRFYrP(KqATQN#lGV^ zEgI>XJ4pkjGJ~+q8uQMnM)+2Y*YWf&vDm4t#mWa8ug(!tH-n(4{ozcoN>qxaL~Z^; zz&_1wc!B)k0!j)v$-}|= zI$R6zy}9^_Q{FyF)}nB%vuAyr@%IlB$`$;u!^BcdWMmQJ5)VFF6b2OhndWU+S)-#~ zF81kdNlms@ou#CI@pLHL#Dq0D&E73NiFR+(q)r4Y$T(Y<5B1sF3)-=gG5MCEqK~T* z!4~0bI&lNBN`7wph?L-qHpn`=n&4eI4;f#?THg@|^VOz= z@3W83m(^b literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-compact.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..300b4bf39f0421ea4e2f730dcc8d585c358cc42e GIT binary patch literal 1510 zcma*nYdF&j00!{CYfLmG8FHya7`bFIQz$e^NJx{*G?_7zYvkIP!?dR4&N<61EJ7Wd zyG%2kP_%?N8@W{&(Z$jEexB#N?}zu(`}OCH6cM!ogaH|VMXz`7Kx_;diUGh`MF2Po z0Dv!nfDZA)#^?v$!1+f6h2jWMLMYY;9UT@L9^vB~?vDwIL_@C=LUEF!V!#yuNCW`O z^z>`S-;MEQLxas0(uKXapu_D4(z0A22(?iHbKfz64I=xUvajq6@9Bz^dofvH4_T!f zxGd-0x32)d9f`mf;UwBPJ@_T2YuL{fkQEP z+HQn;^E9aF3lZn~BvTz^(pP-J*T8jdLGfGtIRiGXF?^062ogu z3c0VJEKpopB^v(dxGVvKIY{x{-j{6Dg#Nh4WzTDbI`577JB>pEAp-qKOqF`R)-z>e zeraY@59@sbF@WI34C2i$F*8DZF4N#q1i!}%vc(+j@3MeX>@@u~EUj?=-YA9}UjjBRRp+^#{!tnbc$l3=x*3VC zJIeKRgFA)D++5c?$~^c{Zf)cn?Ns{-tAeu%115i!8{c`k3IlJQeW-AOM(uCwB%4gw z~YW;x~R!=e6~ruX-UJM+TZBeGt}iG+d<*Uio8CF*mC z=ll5kz}1z`Z}I-CP1LuA0>*h^NW3fVbkN@2lV^QkfWuA&y2`=@)ow+ z?X8TWqev}xrAdENwLC)(^>ES8L@eLi&EbQ>hF-)cfk>;;0)4h|&u`T>`~9`6Fq0k1 zY)lj#EAtG524G-auY}ibZ2eNo5TdQUS&LhDNG0f6%b#OYtXRMB00BqIM=Aa}!j$}I zP#$j08aVk0G^&zOCemRme25-aIRG^iiYq=he0TTj){D|pyegKmDK9pW;)t+$Y4DqWf9fOyg~5*T7?^zJGtx&hiB zWCl4))Ubf(Xy^DxNfP0?pgdIbA!8anWwmog2a%QL!YmtfzVbkeO{-NKI1X~11qVBj z#BBwH>V{}tSBiMyq@4D{-G}4qxDf-y{5FEN<4-~7{ti52h0wLNC*HPf*C@7IxMtG9?Z{ z*#WX((m8>JjVZI$`fB`hH3|yg|K5u!FDzXbOPouBV_awT4l18+Il-t6i__>4_si%8 z4}S%anxYJDLN)KjMVK761SM literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip new file mode 100644 index 0000000000000000000000000000000000000000..916e32eb2547685b6e0825b6413fdbcb1d3213ec GIT binary patch literal 1378 zcma*nYdF&j00!{CHn%XhXhv>P$ukOB$7MLgkPHzO3z=DLW`trSw20EF$hNY%bR$uO zT*6$Al9=Z(moAtg#nx~p+0prap69&phxgO_^@sKZfgONt00iiLRvnl^|ng%E<%)Xn{HN~FAS+SLT=GKxZ;e=AJ-05o#r(N6$0*EUqQjX zKQs6JR#b?3pu!!FCou?et^I6LRy3>TPL=*=~grxgxkEW1?b%pcV_+poSqmFB^&b93wLAQ1Yw7g zN#%-2{rV}tg)~&JCNKQ#MaFSDy!bL|vKr~+i8HC2I2|;dbN117ib0nqaPa5zp$!2_ za}#zymiBZRCl_MJ`eOHPn^M2)?YvY_dq)swkK;#1+A`~wx6dj{@*@Iz1mRdUp6(tp z>bJtp8Nl6ZE}Di~Y*Hybpw(e=P*mxoGj%R}V|MuQ(EiKacY1XeL8x_420ipR>z^l0l{Ad-dt=rfOJ8odMHEB2&}N+~d1b>i0_pS6P&7cf4jX`$5o{r_b`quUp37Ol$t$)+6&A>P(qJ z!Y}o?tDU^frZRMLQ;V)_j^;CxyAt#zH$8r7dosujJagz?w%OsS{V4xrrUIA8Nt{ zVXY67?o1`ntRbf|GAj47_%Gl;v(r%^x+iPsXp|1n>b>bx%gl{(8)eQ|6R=xF+s(2yZ_hDdJfJe1E z=B8UeJq#DdLfy9m%FUs=59LJrEVxYwEWM(LvDR6^t=KgUyV$x%x?-(w!}#EdtP6jx zg~f0Tu+1bto)ZmmbWp1sEwA7G)e6aG$vyyAT`e8wWDYG%!mOB0+s77^ubG_QXK3~C zf)k^_n;67*IyTkd^0|)}x0oQhXc`FqiYPcvtmX&P)ii#mnV&$<_H8 zxf1X+&jt+FJ#qNPnvo^6Hn7cWdUj*uWHS#phA5}M!i;ntpk%)EVJ@KS9|sY17$r4LRtv0=09aHHDrn4*LB%OG4e} zLpi7s1=p_fCcYrS*C}f(SSe=QT=x{;*29n1c@FY-eKLFVu?7gXmb~Vt5QPoaDM&SW zVSuJRu{O4q9#kn~YPcR*WjiDZse;{JTMc%aSxngdHhh+9HdiP~ zsSZ=2kn;oc5<8wj(hy>;!0>dYJd6nV z)abJXUjBO|gNqURe@Vk=v?rKS^6=>Bau3(u8#zGI1B7D-%47CktMx*ed31C1+A`ts z@{Tl|xWY$LD>3eX2^`LlCWglF?dO6^CGYKSmZ3eRwmE?QTfHs#{!O~nulfH5qCKT$ Qem$hN8o0HhElC039~*>+yZ`_I literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..9a88417ba3a962eddb6396cdbd698545008b2b95 GIT binary patch literal 1528 zcma)+YdF&j0LK49lw6v-2x*pTp<&0ct-@S#FSkrKmxyi6hO|SI$(^LwqN9<{aV^5+ zHkWL2SrJmyArf=xL5hf@^Zh)}dEXDePw$8K%g@^})0Dz-V0txuAXlPIb(VrSZB2rFJNMRQPuU;XAQ!nDe{ewdy15aG0kcfN4!~rY- z&;h_ADd`ey6Gmna2cx}4o@M82nT z>$H3yz+wQkpE@jJmv&cL+UJLZ5OM17G0Z`)5bL@AZ_s_V0lbDTR~wLcGjH%QxhK6wD=2( zkmjeKYDI!A&F3E^v1o2K&dHPz6C>%+Ak>a|&?fU>a&bde5?_m0VS!^CX%xs8{vN zl`-|6G<}xDWY<-`>QmO}tmjmjwrRn=6bae%>jBB7C_ScJ{q6+{J=^u?LsaT zupRb$)7?<|{TL4S=Fw`6Yy1cOxOe5T8bf2JV9%2?t_NzHdY);Nr>UE2<$7e+Ybf3} zi?Qi-v=mP?E_NXT6!{*16zK3orl$M#pANaHuRBG|rnBcHmm?U4*KUXB)eJxn{DxaE z7m|kP&sx{(Qt|G4ntl3j8MZv~82JLz)``fBXa^lu53j~Y&Ho&3CM=9*6!CHmN;b8} zgA<%$bK<-~DKX4Lb%_(4wY2oJ!g8m8v_WUNWxJ&jl_7-0cTk6^!njt!@s}XMWV15W zWwu+V%U3f984z%k`PRBv%JE1n+%u6hHGm|9Jgl$x`3~CGaZ1s4Zus{Zf@C5^ssTbS zQVkQ#<0CnJjonOh0D6}d)L`kC4~p8T;F+rY-8fv9G!ykucK}rsh^Xkmo%~_NqzOXnaFmmM1ueIS1{)1ALbLwwqkzC(d6yyRXRk$E|@hUx8(&< zJxNs~ST?;}Lbu-N>NF{v&XbfEdROXc^969>kL6@Wl#*NecsTq=WWNWijIsHFXkxNklGcRX!IAXQOT(kKC?4LX&~|Innellu+pC5_XHJQA1_i$Am!y zT&s%}zhZ}l#FHJ?rq5N#lt^Q?_wnliXM2%dDAE6R@s5uF4PE3H{=b=>?ZtQhT8Qk_ MbB8HAeg}Ym030d55dZ)H literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json new file mode 100644 index 000000000..ea4faf796 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json @@ -0,0 +1,9 @@ +{ + "A": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json new file mode 100644 index 000000000..09c0a51f7 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-legacy.json @@ -0,0 +1,5 @@ +{ + "A": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json new file mode 100644 index 000000000..ea4faf796 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json @@ -0,0 +1,9 @@ +{ + "A": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json new file mode 100644 index 000000000..09c0a51f7 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-legacy.json @@ -0,0 +1,5 @@ +{ + "A": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json new file mode 100644 index 000000000..ea4faf796 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json @@ -0,0 +1,9 @@ +{ + "A": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + } +} \ No newline at end of file From 413a50a1d2561fbec306c1823079e6b1579b0f54 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 15 May 2023 22:57:40 +0200 Subject: [PATCH 052/338] Fix call to a function in an inner scope --- slither/solc_parsing/yul/parse_yul.py | 7 ++++++- .../test_data/assembly-functions.sol | 1 + .../assembly-functions.sol-0.6.9-compact.zip | Bin 1537 -> 1607 bytes .../assembly-functions.sol-0.6.9-legacy.zip | Bin 1403 -> 1433 bytes .../assembly-functions.sol-0.7.6-compact.zip | Bin 1510 -> 1588 bytes .../assembly-functions.sol-0.7.6-legacy.zip | Bin 1378 -> 1414 bytes .../assembly-functions.sol-0.8.16-compact.zip | Bin 1528 -> 1605 bytes .../assembly-functions.sol-0.6.9-compact.json | 3 +++ .../assembly-functions.sol-0.7.6-compact.json | 3 +++ ...assembly-functions.sol-0.8.16-compact.json | 3 +++ 10 files changed, 16 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 978859a53..8657947ea 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -787,6 +787,7 @@ def _parse_yul_magic_suffixes(name: str, root: YulScope) -> Optional[Expression] return None +# pylint: disable=too-many-branches def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[Expression]: name = ast["name"] @@ -822,8 +823,12 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[ if isinstance(root, YulFunction): yul_block = root.root - # Iterate until we get to the YulBlock scope + # Iterate until we searched in all the scopes until the YulBlock scope while not isinstance(yul_block, YulBlock): + func = yul_block.get_yul_local_function_from_name(name) + if func: + return Identifier(func.underlying) + if isinstance(yul_block, YulFunction): yul_block = yul_block.root diff --git a/tests/e2e/solc_parsing/test_data/assembly-functions.sol b/tests/e2e/solc_parsing/test_data/assembly-functions.sol index c7b1c17d3..224e16bab 100644 --- a/tests/e2e/solc_parsing/test_data/assembly-functions.sol +++ b/tests/e2e/solc_parsing/test_data/assembly-functions.sol @@ -2,6 +2,7 @@ contract A { function foo() public { assembly { function f() { function z() { function x() { g() } x() } z() } + function w() { function a() {} function b() { a() } b() } function g() { f() } diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.6.9-compact.zip index 10b6ee248058585c51cf6277ed5477a09f86838b..8389eb6f593dc3d0adfaf206f8ba933852ff32db 100644 GIT binary patch delta 1135 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 delta 1056 zcmV+*1mF9#4CV_PP)h>@KL7#%4gkoouU5c5_tG#0002rC001hJ@dYihNM!+kS^tQ* zz*RdDUu(x4b(wR3NuRSGk0%!$Ejg(m11qzM3$_crFw#j!?&6c(%A6D$+WUJV4UWi! z4>dGG@ex`m(Kc{LA&57Muq)TvSyVhuZ4P|)EGoSt=@RtR`=vp@IX|0970fiyqBD`t z^EeRtN~RT2rIg9O!H+cFLzo$Vcy&LGTK92|9x%j7DbiIU$V|EUrF=c5aY6azemdYr zs=IBSY#hipSvte7WxU_bb~{}g_=gf);zl^%k&0QpT;@pW3Jyt@XWDSiXx<2`yXarV zVeQKuONpo4h`iim)MblCLbY{XuDmJgS7gY%KcC`S%atlTONR6aP=aoMOm-a_IyW+# zkEBFsSaz=&PKsVG)2`^~EPyS|hfl}m77(haP}y-~^R<-Oob|j<0vdf&Zq>y0>~oLn zIU9uHjwfiaB|JDOHr_&q?Ng_ezqv8}tfwf+{gRtP$!vO7X!KY3j(R%#Qa*?J zmKD5C+gL9A>|!(pnp{*#;T88R zbno>8yBX`S=d%xtszVrKD5+@Qz#GeGcd%>@xe8?fI1npZe$`aVEufOpKEA)UCfcqf z9BF5_y4c{zdSY^9_01Vy8GXh+HIJ;$6Ffr5%s}r7*BptV1HeRo0wl0-sLU=m0ehZJ z(~}I9>Ta1!rF6IG`fKF{;_j7_jhxir5Ss(FQ4{QoK&2fKIfv25n&-ZOr|7A8Cydkf7MjuZ}Mw$>yR}KsF+DUw8YeAZ8b96V2XIMF3D*(8cK&DJ3NpmkYjfVhdh-Em|nIdGo`SD z^TFdOK8=M^y`j!fU704!rL7;#HVRYc5Nk<_21NC9s0D^rpNoZk{CrVJ%}uG)0W zhnl`~C`|tK!5F}Cy!U@1T$DJ5rA-&kY%FM0pU%P|AJY&#QnP`Se7z8KYjQL{<(@Cz z!g8Q)GO{Y@nqJLE+?5=#p(s{<6^q)O!LAp*2qZ4cWDyXGP4zoNHNCq+V133Pl3oDj zqs3^VoS^n>1%T**JZMwrEF&95w>iA6aC;%d24acB5YzYyzNmxTr!VAQE~y(LaFBa# z!DPJpZ*cJ69T`@0WwIK8kn)uL@b{~Ol*~Bed8`DECkg)Y2V77~0Rle*KL7#%4gkoo auU5c5_tG#0002rCli&qT26zPk0002MruXpx diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.7.6-legacy.zip index 916e32eb2547685b6e0825b6413fdbcb1d3213ec..c1285733d81f638c7c279f1709d3547f7ab2bc15 100644 GIT binary patch delta 775 zcmV+i1Ni*n3Wf_CP)h>@KL7#%4ghhsuT}?yUb@f(006lX001hJ9|bM3NE`xxoGV&c zNQzLkntiT4sxbO%@AgGWA@uTHtLyc;eoT)tJ)TLce&ui)usM!pqTpf*JtlO)j~H@y zN=92@*wtNL@3|3cD+V@Q7t3KrHYw{k!6_^C;uQ1Sxf551bj-U$&BqH>vP`_;xJx z;+a;|<#3GRc_p!2TfDy-fTOH|Fla8(O!%YGk{4R;Up(!FKW`elABo0V?<`5QRco?7 z^R9{s@npNX-NC0s^XjIs@sdBEHJgo+6{Ko19edb{b|uTfy2?1)rG6iO0x5B2%?Mu< zRp(lAe3oarftqhAD@U)Y3Cj)+Q*mApkoG)A;YFV|$Y|>2Kkh4n>Q;Q^6{A5R)$V>r z$_K706I5?_FCi==Wv}mXVjB5{Skib|Q~h~}2t!FMiB9&g3YmFb{U)Jh_OmqOqp^v0 zyx)1j^j2?f?->q@eLYWqQ*)4XGjmc71iTxf65&&Sz=MSlSU~P=dpyAFf_k!i@LPeq z5`8Kd>aW=2WzhINnlzZ^=lubVxACU92BF37&WBK+gAe}Z-@RGJS&GmHs;+0H1Nw84kbPhd}b zwOD>7nhh9k_rlHyT(%Jh$7dgjL59gdIw6ZK0WSpW_8dt*-Y||Pv+31lZN~*ZkZ(_Q z8QjQ9BW$7weo+ajxuaZyLIp9lvaJqr1B8)yVmwS-`nj9XgU!4=MXo&?GS4-FY(@>wNWjnD*XD{&)YAIc=9th{(AOiEt3x3q--O`>DyF z1F-l1vLkgjxS#D$|H5yK!ca>A0zU&k00ICG0CBdjRtJP$y3hmw0J##A4h2pI7zF?T F005F0ZcYFI delta 732 zcmV<20weu~3*rhGP)h>@KL7#%4gkoouT~Jaj(MyE008?Du^3DOe;WNZ#L;y9+no{r z;Mv1aW*EbrqrFGq34ZQ|hl@Kz8obvIecXq<*>}Ql-mzoxV!o(&mg04rHV#{Yf~+T^ z=d>;Th7-p#KZti|4m@FHUv3Y=i%6uRE1Ts+$Qk+xxlhpK7i@^r6rlib1!q4}z`pOj z{71lMbv5nJJ+=Aoe+D;FhMY!6Pz3U=%uxZRwD~CB&+zeTNWnmhfHtl;E%I;}NeTcD zykQ=w2=pj2*}6AooTiwa_rs>yrXAxNd%h+GruWMHB{5fpddc@*x2yL**#A_&v73B^4c(^Z6}PfO-L?E#?v3age`OlK$~d! zrcwX0FaIUN8u341aop0{YQbw=qyNx6lB7^e0Rle*KL7#%4gkoouT~Jaj(MyE008?D OlQIQP2J{2~0000P>ts{_ diff --git a/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip b/tests/e2e/solc_parsing/test_data/compile/assembly-functions.sol-0.8.16-compact.zip index 9a88417ba3a962eddb6396cdbd698545008b2b95..a2b78d7b0698f3f623f5a2a37a95314adaa14197 100644 GIT binary patch delta 1124 zcmV-q1e^Q#3&ji=P)h>@KL7#%4ghhsuU3)0TTYJ!006@ou^6fWe<-GIdm<|qgPLus z)qD0-))LC{XRyf6q?%Mw;DE6v;AqFDBD`g$GJmK~n2I)dBUew?9u4ZEj7{G%%dMvC zo|A`23WLAw0RdeA6Z&w+9r1m-`FX5inpPjU`fOkXCGOWJJrLO}|2c-9CbgMBz%yQr zHonDr0KAwxvjbT)e|oHxZ4EKT@r@7f5ERW0532P3>YF##3f|8HlVGq2%zjYp7yxv? z(xU@Y1+` zly7+DlOysBqqlr%RC3e(rD}2#qZ_ayE7DyGqxW#w+f#}cB=`|jIk})i(;$25F1K)0 z6&Yr?8emN&$Gz6bZ}I5CxZkU)d@m3r=ygM7N(C5{VEeLA@W~M25=Z;kO;rO0gdI44 zDx#^~+5B0ef76BDay4+tZ_f_q!l2apS7Z(3OMEp!bKe|s|J!!ng!0phm3N?DgR+NptX zjCIi9Rm)Xk`a`D$jC3ZK50W}RJUZ2r{mKSlO*v#Z> zVu^%LDM#LfQ^(vmbK<}IQnVbS^RxGnN~N>o$aE#r61-zVd|@p|0~LJhD5RfG|DpIG z0)$ajSC{oT?Rs~ue)@0cbUW$utT#_QOX22J9*ty1!4~dhA*WcOT?I(RcFmqTHQ;kVx;2 zesF5Lb874TrHjk2AzlnAk6h~i;t=6I$GVvFFeKrYv0H9`-4yUg4Xn)9J9>n{n| zM603pkkEAnI|_e6@+Z`FB<*Y9N~Rp!JGo1uYYCKsv1IzmK_QWc05d)!Ap-p{0T8Rx zj9SRrF9sS+*$Y@oWrhjh`rJ5TiSvd*H)qcXe}X!0m%jW0Z8FzRZ`i00rNoIw;Q#rI qNZ3$I0Rle*KL7#%4ghhsuU3)0TTYJ!006@olcWVs2G<1u00012$s;ZR delta 1046 zcmV+x1nK+54EPHeP)h>@KL7#%4gkoouT~F7x9CCz001Nwu^6fWf7~3)j4zo7Y3O#k)O_+bY(3~EzSS~ zvgtt6<`p}AwuHNM2(`Wg5$!0)NnYrtpr+^&Z}t!Qd15St zG=PL^QW)dC`|auLf6uLA+9sy71^!c%?A-Z4jRRL(gl*z-pJB>EY1K{tY<#?xYk-}7 zx4(uevK@NIpwVI4tbQHU+(9$MiH?6|Avst>yAyjHIUtu;kGLHbk~@7!%uYlFhc%^9 zZUA!=%VR$hB;k)AR)76Xmy6TI0XycC>j?67gfV)Oa+|c$e=Qq0Vfn1;Z`FXg!1=a| zVpa*gT+xs*zNS~$?=vAIb&qwz5+odQvSN4a{nov0?c0u{#+NXu{2}0Ig-?E#fm#xZ zeV8J)hvB#QjEzj{tWRW&)KC!eO7Ykj)j9|F62mzZ;2@tY&l1k#y%%&*>B=L>ULR&Y zWMnFs*+!)ce@-ZVH&};n(+eeZ3u^R3%Vz9qZw?@>|%De z&AZB&JOC|~nP$2~V4Mn<~7~i|rtBB}#q$bioqh&g+!(lS|MVNHe_2=ExPs}tY z6oiAJPB%?z&oJ3F&Tw99(ELvWvZY!YT|n_z7s!p{f5(AIwC-cC!e|(J`E8*UDZney zZp$4S#wp}R!O$nc9-(wRz?+QRM6)wl0TZr!SpGk@J;geCdv1XHCuzSX9PwtimL~P? zHk00^cZ>M6ZENkh4tBy_2ZdvQ&@-6l`aI$CNd#btd2#=f^?)Z7N@$tb5dK*w88UPl zZA84!fAK)Tg2=@-tLB>s6Y5&7BiumfR5Ww9MI-L}W8N{>%oczvGrSy2Sz%yMnZ6V1 z^dam~#s^a9Z5H#?1T7&|F;2_b!;r1Rj=ou#+a)n=TstMkMuR;;7nN2wDS};G2r@r= zKLo7nDK8(FQ}LsIV#cArJ~Im*H#Sc3OlyW$ecmTM{*CqPS?)6@0N=6nddvzdezenaX;F+@69ex|kNET%|-j1rxjK^YPBF0*Q zY1_2F4hq7L+Gj_Do15}V)yMX+Tw9{)caki2|FS514lQ6$doNq5bAUjpp}sjZx~_rZ zh15DXAjp}6^GaPOgKqL1x^Nv1poj50L}&Uh5!Hn diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json index ea4faf796..a48faa23d 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json @@ -4,6 +4,9 @@ "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n", + "foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json index ea4faf796..a48faa23d 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json @@ -4,6 +4,9 @@ "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n", + "foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json index ea4faf796..a48faa23d 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json @@ -4,6 +4,9 @@ "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo.asm_0.w.a()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n}\n", + "foo.asm_0.w.b()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.g()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file From b932371e4c4b57237a4c40c0d255f5b9e8dfb170 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 24 May 2023 12:55:10 -0500 Subject: [PATCH 053/338] Avoid IndexError in `is_function_modified` --- slither/utils/upgradeability.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 7b4e8493a..9fb55ce81 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -220,6 +220,8 @@ def is_function_modified(f1: Function, f2: Function) -> bool: visited.extend([node_f1, node_f2]) queue_f1.extend(son for son in node_f1.sons if son not in visited) queue_f2.extend(son for son in node_f2.sons if son not in visited) + if len(node_f1.irs) != len(node_f2.irs): + return True for i, ir in enumerate(node_f1.irs): if encode_ir_for_compare(ir) != encode_ir_for_compare(node_f2.irs[i]): return True From 58391ae487406a1ed1870028a5e50d0bf80af3b1 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 24 May 2023 12:57:12 -0500 Subject: [PATCH 054/338] Improve encoding for comparison --- slither/utils/upgradeability.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 9fb55ce81..8d18dd67c 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -275,13 +275,13 @@ def encode_ir_for_compare(ir: Operation) -> str: if isinstance(ir, Assignment): return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" if isinstance(ir, Index): - return f"index({ntype(ir.index_type)})" + return f"index({ntype(ir.variable_right.type)})" if isinstance(ir, Member): return "member" # .format(ntype(ir._type)) if isinstance(ir, Length): return "length" if isinstance(ir, Binary): - return f"binary({str(ir.variable_left)}{str(ir.type)}{str(ir.variable_right)})" + return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})" if isinstance(ir, Unary): return f"unary({str(ir.type)})" if isinstance(ir, Condition): @@ -332,7 +332,7 @@ def encode_var_for_compare(var: Variable) -> str: # variables if isinstance(var, Constant): - return f"constant({ntype(var.type)})" + return f"constant({ntype(var.type)},{var.value})" if isinstance(var, SolidityVariableComposed): return f"solidity_variable_composed({var.name})" if isinstance(var, SolidityVariable): @@ -342,9 +342,16 @@ def encode_var_for_compare(var: Variable) -> str: if isinstance(var, ReferenceVariable): return f"reference({ntype(var.type)})" if isinstance(var, LocalVariable): - return f"local_solc_variable({var.location})" + return f"local_solc_variable({ntype(var.type)},{var.location})" if isinstance(var, StateVariable): - return f"state_solc_variable({ntype(var.type)})" + if not (var.is_constant or var.is_immutable): + try: + slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) + except KeyError: + slot = var.name + else: + slot = var.name + return f"state_solc_variable({ntype(var.type)},{slot})" if isinstance(var, LocalVariableInitFromTuple): return "local_variable_init_tuple" if isinstance(var, TupleVariable): From e85572824d593540e9dc6c8b40b1898538b003e6 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 25 May 2023 12:07:31 +0200 Subject: [PATCH 055/338] - Move LoC features into utils.loc as they are now used by two printers - Remove the usage of dict and create LoC/LoCInfo dataclass to reduce complexity - Add to_pretty_table in LoC to reduce complexity - Use proper type (remove PEP 585 for python 3.8 support) --- slither/printers/all_printers.py | 2 +- slither/printers/summary/human_summary.py | 26 +++--- slither/printers/summary/loc.py | 106 ++-------------------- slither/utils/loc.py | 105 +++++++++++++++++++++ slither/utils/myprettytable.py | 39 -------- 5 files changed, 125 insertions(+), 153 deletions(-) create mode 100644 slither/utils/loc.py diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 3dd64da3e..5555fe708 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -1,7 +1,7 @@ # pylint: disable=unused-import,relative-beyond-top-level from .summary.function import FunctionSummary from .summary.contract import ContractSummary -from .summary.loc import Loc +from .summary.loc import LocPrinter from .inheritance.inheritance import PrinterInheritance from .inheritance.inheritance_graph import PrinterInheritanceGraph from .call.call_graph import PrinterCallGraph diff --git a/slither/printers/summary/human_summary.py b/slither/printers/summary/human_summary.py index 157b8228a..314335ebf 100644 --- a/slither/printers/summary/human_summary.py +++ b/slither/printers/summary/human_summary.py @@ -163,7 +163,7 @@ class PrinterHumanSummary(AbstractPrinter): def _number_functions(contract): return len(contract.functions) - def _get_number_of_assembly_lines(self): + def _get_number_of_assembly_lines(self) -> int: total_asm_lines = 0 for contract in self.contracts: for function in contract.functions_declared: @@ -179,9 +179,7 @@ class PrinterHumanSummary(AbstractPrinter): return "Compilation non standard\n" return f"Compiled with {str(self.slither.crytic_compile.type)}\n" - def _number_contracts(self): - if self.slither.crytic_compile is None: - return len(self.slither.contracts), 0, 0 + def _number_contracts(self) -> Tuple[int, int, int]: contracts = self.slither.contracts deps = [c for c in contracts if c.is_from_dependency()] tests = [c for c in contracts if c.is_test] @@ -267,7 +265,7 @@ class PrinterHumanSummary(AbstractPrinter): "Proxy": contract.is_upgradeable_proxy, } - def _get_contracts(self, txt): + def _get_contracts(self, txt: str) -> str: ( number_contracts, number_contracts_deps, @@ -280,18 +278,18 @@ class PrinterHumanSummary(AbstractPrinter): txt += f"Number of contracts in tests : {number_contracts_tests}\n" return txt - def _get_number_lines(self, txt, results): - lines_dict = compute_loc_metrics(self.slither) + def _get_number_lines(self, txt: str, results: Dict) -> Tuple[str, Dict]: + loc = compute_loc_metrics(self.slither) txt += "Source lines of code (SLOC) in source files: " - txt += f"{lines_dict['src']['sloc']}\n" - if lines_dict["dep"]["sloc"] > 0: + txt += f"{loc.src.sloc}\n" + if loc.dep.sloc > 0: txt += "Source lines of code (SLOC) in dependencies: " - txt += f"{lines_dict['dep']['sloc']}\n" - if lines_dict["test"]["sloc"] > 0: + txt += f"{loc.dep.sloc}\n" + if loc.test.sloc > 0: txt += "Source lines of code (SLOC) in tests : " - txt += f"{lines_dict['test']['sloc']}\n" - results["number_lines"] = lines_dict["src"]["sloc"] - results["number_lines__dependencies"] = lines_dict["dep"]["sloc"] + txt += f"{loc.test.sloc}\n" + results["number_lines"] = loc.src.sloc + results["number_lines__dependencies"] = loc.dep.sloc total_asm_lines = self._get_number_of_assembly_lines() txt += f"Number of assembly lines: {total_asm_lines}\n" results["number_lines_assembly"] = total_asm_lines diff --git a/slither/printers/summary/loc.py b/slither/printers/summary/loc.py index 4ed9aa6ab..35bb20fc4 100644 --- a/slither/printers/summary/loc.py +++ b/slither/printers/summary/loc.py @@ -9,102 +9,13 @@ dep: dependency files test: test files """ -from pathlib import Path -from slither.printers.abstract_printer import AbstractPrinter -from slither.utils.myprettytable import transpose, make_pretty_table -from slither.utils.tests_pattern import is_test_file - - -def count_lines(contract_lines: list) -> tuple: - """Function to count and classify the lines of code in a contract. - Args: - contract_lines: list(str) representing the lines of a contract. - Returns: - tuple(int, int, int) representing (cloc, sloc, loc) - """ - multiline_comment = False - cloc = 0 - sloc = 0 - loc = 0 - - for line in contract_lines: - loc += 1 - stripped_line = line.strip() - if not multiline_comment: - if stripped_line.startswith("//"): - cloc += 1 - elif "/*" in stripped_line: - # Account for case where /* is followed by */ on the same line. - # If it is, then multiline_comment does not need to be set to True - start_idx = stripped_line.find("/*") - end_idx = stripped_line.find("*/", start_idx + 2) - if end_idx == -1: - multiline_comment = True - cloc += 1 - elif stripped_line: - sloc += 1 - else: - cloc += 1 - if "*/" in stripped_line: - multiline_comment = False - - return cloc, sloc, loc - -def _update_lines_dict(file_type: str, lines: list, lines_dict: dict) -> dict: - """An internal function used to update (mutate in place) the lines_dict. - Args: - file_type: str indicating "src" (source files), "dep" (dependency files), or "test" tests. - lines: list(str) representing the lines of a contract. - lines_dict: dict to be updated with this shape: - { - "src" : {"loc": 30, "sloc": 20, "cloc": 5}, # code in source files - "dep" : {"loc": 50, "sloc": 30, "cloc": 10}, # code in dependencies - "test": {"loc": 80, "sloc": 60, "cloc": 10}, # code in tests - } - Returns: - an updated lines_dict - """ - cloc, sloc, loc = count_lines(lines) - lines_dict[file_type]["loc"] += loc - lines_dict[file_type]["cloc"] += cloc - lines_dict[file_type]["sloc"] += sloc - return lines_dict - - -def compute_loc_metrics(slither) -> dict: - """Used to compute the lines of code metrics for a Slither object. - Args: - slither: A Slither object - Returns: - A new dict with the following shape: - { - "src" : {"loc": 30, "sloc": 20, "cloc": 5}, # code in source files - "dep" : {"loc": 50, "sloc": 30, "cloc": 10}, # code in dependencies - "test": {"loc": 80, "sloc": 60, "cloc": 10}, # code in tests - } - """ - - lines_dict = { - "src": {"loc": 0, "sloc": 0, "cloc": 0}, - "dep": {"loc": 0, "sloc": 0, "cloc": 0}, - "test": {"loc": 0, "sloc": 0, "cloc": 0}, - } - - if not slither.source_code: - return lines_dict - - for filename, source_code in slither.source_code.items(): - current_lines = source_code.splitlines() - is_dep = False - if slither.crytic_compile: - is_dep = slither.crytic_compile.is_dependency(filename) - file_type = "dep" if is_dep else "test" if is_test_file(Path(filename)) else "src" - lines_dict = _update_lines_dict(file_type, current_lines, lines_dict) - return lines_dict +from slither.printers.abstract_printer import AbstractPrinter +from slither.utils.loc import compute_loc_metrics +from slither.utils.output import Output -class Loc(AbstractPrinter): +class LocPrinter(AbstractPrinter): ARGUMENT = "loc" HELP = """Count the total number lines of code (LOC), source lines of code (SLOC), \ and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), \ @@ -112,14 +23,11 @@ class Loc(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#loc" - def output(self, _filename): + def output(self, _filename: str) -> Output: # compute loc metrics - lines_dict = compute_loc_metrics(self.slither) + loc = compute_loc_metrics(self.slither) - # prepare the table - headers = [""] + list(lines_dict.keys()) - report_dict = transpose(lines_dict) - table = make_pretty_table(headers, report_dict) + table = loc.to_pretty_table() txt = "Lines of Code \n" + str(table) self.info(txt) res = self.generate_output(txt) diff --git a/slither/utils/loc.py b/slither/utils/loc.py new file mode 100644 index 000000000..0e51dfa46 --- /dev/null +++ b/slither/utils/loc.py @@ -0,0 +1,105 @@ +from dataclasses import dataclass +from pathlib import Path +from typing import List, Tuple + +from slither import Slither +from slither.utils.myprettytable import MyPrettyTable +from slither.utils.tests_pattern import is_test_file + + +@dataclass +class LoCInfo: + loc: int = 0 + sloc: int = 0 + cloc: int = 0 + + def total(self) -> int: + return self.loc + self.sloc + self.cloc + + +@dataclass +class LoC: + src: LoCInfo = LoCInfo() + dep: LoCInfo = LoCInfo() + test: LoCInfo = LoCInfo() + + def to_pretty_table(self) -> MyPrettyTable: + table = MyPrettyTable(["", "src", "dep", "test"]) + + table.add_row(["loc", str(self.src.loc), str(self.dep.loc), str(self.test.loc)]) + table.add_row(["sloc", str(self.src.sloc), str(self.dep.sloc), str(self.test.sloc)]) + table.add_row(["cloc", str(self.src.cloc), str(self.dep.cloc), str(self.test.cloc)]) + table.add_row( + ["Total", str(self.src.total()), str(self.dep.total()), str(self.test.total())] + ) + return table + + +def count_lines(contract_lines: List[str]) -> Tuple[int, int, int]: + """Function to count and classify the lines of code in a contract. + Args: + contract_lines: list(str) representing the lines of a contract. + Returns: + tuple(int, int, int) representing (cloc, sloc, loc) + """ + multiline_comment = False + cloc = 0 + sloc = 0 + loc = 0 + + for line in contract_lines: + loc += 1 + stripped_line = line.strip() + if not multiline_comment: + if stripped_line.startswith("//"): + cloc += 1 + elif "/*" in stripped_line: + # Account for case where /* is followed by */ on the same line. + # If it is, then multiline_comment does not need to be set to True + start_idx = stripped_line.find("/*") + end_idx = stripped_line.find("*/", start_idx + 2) + if end_idx == -1: + multiline_comment = True + cloc += 1 + elif stripped_line: + sloc += 1 + else: + cloc += 1 + if "*/" in stripped_line: + multiline_comment = False + + return cloc, sloc, loc + + +def _update_lines(loc_info: LoCInfo, lines: list) -> None: + """An internal function used to update (mutate in place) the loc_info. + + Args: + loc_info: LoCInfo to be updated + lines: list(str) representing the lines of a contract. + """ + cloc, sloc, loc = count_lines(lines) + loc_info.loc += loc + loc_info.cloc += cloc + loc_info.sloc += sloc + + +def compute_loc_metrics(slither: Slither) -> LoC: + """Used to compute the lines of code metrics for a Slither object. + + Args: + slither: A Slither object + Returns: + A LoC object + """ + + loc = LoC() + + for filename, source_code in slither.source_code.items(): + current_lines = source_code.splitlines() + is_dep = False + if slither.crytic_compile: + is_dep = slither.crytic_compile.is_dependency(filename) + loc_type = loc.dep if is_dep else loc.test if is_test_file(Path(filename)) else loc.src + _update_lines(loc_type, current_lines) + return loc diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index 57e130884..2f2be7e72 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -22,42 +22,3 @@ class MyPrettyTable: def __str__(self) -> str: return str(self.to_pretty_table()) - - -# **Dict to MyPrettyTable utility functions** - - -# Converts a dict to a MyPrettyTable. Dict keys are the row headers. -# @param headers str[] of column names -# @param body dict of row headers with a dict of the values -# @param totals bool optional add Totals row -def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: - table = MyPrettyTable(headers) - for row in body: - table_row = [row] + [body[row][key] for key in headers[1:]] - table.add_row(table_row) - if totals: - table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) - return table - - -# takes a dict of dicts and returns a dict of dicts with the keys transposed -# example: -# in: -# { -# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, -# "test": {"loc": 0, "sloc": 0, "cloc": 0}, -# "src": {"loc": 0, "sloc": 0, "cloc": 0}, -# } -# out: -# { -# 'loc': {'dep': 0, 'test': 0, 'src': 0}, -# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, -# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, -# } -def transpose(table): - any_key = list(table.keys())[0] - return { - inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} - for inner_key in table[any_key] - } From 00461aad9a6c9205cbf826aa83f6c258609ade91 Mon Sep 17 00:00:00 2001 From: William E Bodell III Date: Fri, 2 Jun 2023 08:39:42 -0500 Subject: [PATCH 056/338] slither-read-storage native POA support (#1843) * Native support for POA networks in read_storage * Set `srs.rpc` before `srs.block` * Type hint * New RpcInfo class w/ RpcInfo.web3 and RpcInfo.block In SlitherReadStorage, self.rpc_info: Optional[RpcInfo] replaces self.rpc, self._block, self._web3 * Black * Update test_read_storage.py * Add import in __init__.py * Avoid instantiating SRS twice * Add comment about `get_block` for POA networks * Pylint * Black * Allow other valid block string arguments ["latest", "earliest", "pending", "safe", "finalized"] * `args.block` can be in ["latest", "earliest", "pending", "safe", "finalized"] * Use BlockTag enum class for valid `str` arguments * Tweak `RpcInfo.__init__()` signature * get rid of `or "latest"` * Import BlockTag * Use `web3.types.BlockIdentifier` * Revert BlockTag enum * Pylint and black * Replace missing newline * Update slither/tools/read_storage/__main__.py Better, cleaner python Co-authored-by: alpharush <0xalpharush@protonmail.com> * Drop try/except around args.block parsing allow ValueError if user provides invalid block arg * Remove unused import --------- Co-authored-by: alpharush <0xalpharush@protonmail.com> --- slither/tools/read_storage/__init__.py | 2 +- slither/tools/read_storage/__main__.py | 29 +++++----- slither/tools/read_storage/read_storage.py | 57 +++++++++++++------ tests/tools/read-storage/test_read_storage.py | 6 +- 4 files changed, 57 insertions(+), 37 deletions(-) diff --git a/slither/tools/read_storage/__init__.py b/slither/tools/read_storage/__init__.py index dbc1e5bc0..df9b8280d 100644 --- a/slither/tools/read_storage/__init__.py +++ b/slither/tools/read_storage/__init__.py @@ -1 +1 @@ -from .read_storage import SlitherReadStorage +from .read_storage import SlitherReadStorage, RpcInfo diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index 1a8901321..f6635ab4b 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -7,7 +7,7 @@ import argparse from crytic_compile import cryticparser from slither import Slither -from slither.tools.read_storage.read_storage import SlitherReadStorage +from slither.tools.read_storage.read_storage import SlitherReadStorage, RpcInfo def parse_args() -> argparse.Namespace: @@ -126,22 +126,19 @@ def main() -> None: else: contracts = slither.contracts - srs = SlitherReadStorage(contracts, args.max_depth) - - try: - srs.block = int(args.block) - except ValueError: - srs.block = str(args.block or "latest") - + rpc_info = None if args.rpc_url: - # Remove target prefix e.g. rinkeby:0x0 -> 0x0. - address = target[target.find(":") + 1 :] - # Default to implementation address unless a storage address is given. - if not args.storage_address: - args.storage_address = address - srs.storage_address = args.storage_address - - srs.rpc = args.rpc_url + valid = ["latest", "earliest", "pending", "safe", "finalized"] + block = args.block if args.block in valid else int(args.block) + rpc_info = RpcInfo(args.rpc_url, block) + + srs = SlitherReadStorage(contracts, args.max_depth, rpc_info) + # Remove target prefix e.g. rinkeby:0x0 -> 0x0. + address = target[target.find(":") + 1 :] + # Default to implementation address unless a storage address is given. + if not args.storage_address: + args.storage_address = address + srs.storage_address = args.storage_address if args.variable_name: # Use a lambda func to only return variables that have same name as target. diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index 2947081da..72331f66a 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -6,8 +6,11 @@ import dataclasses from eth_abi import decode, encode from eth_typing.evm import ChecksumAddress -from eth_utils import keccak +from eth_utils import keccak, to_checksum_address from web3 import Web3 +from web3.types import BlockIdentifier +from web3.exceptions import ExtraDataLengthError +from web3.middleware import geth_poa_middleware from slither.core.declarations import Contract, Structure from slither.core.solidity_types import ArrayType, ElementaryType, MappingType, UserDefinedType @@ -42,18 +45,43 @@ class SlitherReadStorageException(Exception): pass +class RpcInfo: + def __init__(self, rpc_url: str, block: BlockIdentifier = "latest") -> None: + assert isinstance(block, int) or block in [ + "latest", + "earliest", + "pending", + "safe", + "finalized", + ] + self.rpc: str = rpc_url + self._web3: Web3 = Web3(Web3.HTTPProvider(self.rpc)) + """If the RPC is for a POA network, the first call to get_block fails, so we inject geth_poa_middleware""" + try: + self._block: int = self.web3.eth.get_block(block)["number"] + except ExtraDataLengthError: + self._web3.middleware_onion.inject(geth_poa_middleware, layer=0) + self._block: int = self.web3.eth.get_block(block)["number"] + + @property + def web3(self) -> Web3: + return self._web3 + + @property + def block(self) -> int: + return self._block + + # pylint: disable=too-many-instance-attributes class SlitherReadStorage: - def __init__(self, contracts: List[Contract], max_depth: int) -> None: + def __init__(self, contracts: List[Contract], max_depth: int, rpc_info: RpcInfo = None) -> None: self._checksum_address: Optional[ChecksumAddress] = None self._contracts: List[Contract] = contracts self._log: str = "" self._max_depth: int = max_depth self._slot_info: Dict[str, SlotInfo] = {} self._target_variables: List[Tuple[Contract, StateVariable]] = [] - self._web3: Optional[Web3] = None - self.block: Union[str, int] = "latest" - self.rpc: Optional[str] = None + self.rpc_info: Optional[RpcInfo] = rpc_info self.storage_address: Optional[str] = None self.table: Optional[MyPrettyTable] = None @@ -73,18 +101,12 @@ class SlitherReadStorage: def log(self, log: str) -> None: self._log = log - @property - def web3(self) -> Web3: - if not self._web3: - self._web3 = Web3(Web3.HTTPProvider(self.rpc)) - return self._web3 - @property def checksum_address(self) -> ChecksumAddress: if not self.storage_address: raise ValueError if not self._checksum_address: - self._checksum_address = self.web3.to_checksum_address(self.storage_address) + self._checksum_address = to_checksum_address(self.storage_address) return self._checksum_address @property @@ -223,11 +245,12 @@ class SlitherReadStorage: """Fetches the slot value of `SlotInfo` object :param slot_info: """ + assert self.rpc_info is not None hex_bytes = get_storage_data( - self.web3, + self.rpc_info.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big"), - self.block, + self.rpc_info.block, ) slot_info.value = self.convert_value_to_type( hex_bytes, slot_info.size, slot_info.offset, slot_info.type_string @@ -600,15 +623,15 @@ class SlitherReadStorage: (int): The length of the array. """ val = 0 - if self.rpc: + if self.rpc_info: # The length of dynamic arrays is stored at the starting slot. # Convert from hexadecimal to decimal. val = int( get_storage_data( - self.web3, + self.rpc_info.web3, self.checksum_address, int.to_bytes(slot, 32, byteorder="big"), - self.block, + self.rpc_info.block, ).hex(), 16, ) diff --git a/tests/tools/read-storage/test_read_storage.py b/tests/tools/read-storage/test_read_storage.py index 6d2ab007d..ea04a91fe 100644 --- a/tests/tools/read-storage/test_read_storage.py +++ b/tests/tools/read-storage/test_read_storage.py @@ -12,7 +12,7 @@ from web3 import Web3 from web3.contract import Contract from slither import Slither -from slither.tools.read_storage import SlitherReadStorage +from slither.tools.read_storage import SlitherReadStorage, RpcInfo TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" @@ -105,8 +105,8 @@ def test_read_storage(web3, ganache, solc_binary_path) -> None: sl = Slither(Path(TEST_DATA_DIR, "storage_layout-0.8.10.sol").as_posix(), solc=solc_path) contracts = sl.contracts - srs = SlitherReadStorage(contracts, 100) - srs.rpc = ganache.provider + rpc_info: RpcInfo = RpcInfo(ganache.provider) + srs = SlitherReadStorage(contracts, 100, rpc_info) srs.storage_address = address srs.get_all_storage_variables() srs.get_storage_layout() From a82683139d46fca135299bc7c751aa48ea2c58b0 Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Fri, 2 Jun 2023 16:12:24 -0400 Subject: [PATCH 057/338] initial optimization --- slither/detectors/variables/similar_variables.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 465e1ce01..5db955241 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -47,9 +47,7 @@ class SimilarVarsDetection(AbstractDetector): Returns: bool: true if names are similar """ - if len(seq1) != len(seq2): - return False - val = difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() + val = difflib.SequenceMatcher(a=seq1, b=seq2).ratio() ret = val > 0.90 return ret @@ -69,11 +67,15 @@ class SimilarVarsDetection(AbstractDetector): ret = [] for v1 in all_var: + _len_v1 = len(v1.name) for v2 in all_var: - if v1.name.lower() != v2.name.lower(): - if SimilarVarsDetection.similar(v1.name, v2.name): - if (v2, v1) not in ret: - ret.append((v1, v2)) + if _len_v1 != len(v2.name): + continue + _v1_name_lower = v1.name.lower() + _v2_name_lower = v2.name.lower() + if _v1_name_lower != _v2_name_lower: + if SimilarVarsDetection.similar(_v1_name_lower, _v2_name_lower): + ret.append((v1, v2)) return set(ret) From 1b4c0b913727ff6306db9e6f7bb9a4cf0ff900c3 Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Fri, 2 Jun 2023 18:07:45 -0400 Subject: [PATCH 058/338] reduced num iterations in inner loop --- slither/detectors/variables/similar_variables.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 5db955241..8bd5b93d7 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -63,12 +63,14 @@ class SimilarVarsDetection(AbstractDetector): contract_var = contract.variables - all_var = set(all_var + contract_var) + all_var = list(set(all_var + contract_var)) ret = [] - for v1 in all_var: + for i in range(len(all_var)): + v1 = all_var[i] _len_v1 = len(v1.name) - for v2 in all_var: + for j in range(i,len(all_var)): + v2 = all_var[j] if _len_v1 != len(v2.name): continue _v1_name_lower = v1.name.lower() From 15e8ce9e330df30090a5ce82c1fbef0491ee6f1d Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Sat, 3 Jun 2023 07:15:57 -0400 Subject: [PATCH 059/338] remove changes to how similar() works --- .../detectors/variables/similar_variables.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 8bd5b93d7..7cb10cbd5 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -47,7 +47,9 @@ class SimilarVarsDetection(AbstractDetector): Returns: bool: true if names are similar """ - val = difflib.SequenceMatcher(a=seq1, b=seq2).ratio() + if len(seq1) != len(seq2): + return False + val = difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() ret = val > 0.90 return ret @@ -68,16 +70,13 @@ class SimilarVarsDetection(AbstractDetector): ret = [] for i in range(len(all_var)): v1 = all_var[i] - _len_v1 = len(v1.name) - for j in range(i,len(all_var)): + _v1_name_lower = v1.name.lower() + for j in range(i,len(all_var)): v2 = all_var[j] - if _len_v1 != len(v2.name): - continue - _v1_name_lower = v1.name.lower() - _v2_name_lower = v2.name.lower() - if _v1_name_lower != _v2_name_lower: - if SimilarVarsDetection.similar(_v1_name_lower, _v2_name_lower): - ret.append((v1, v2)) + if _v1_name_lower != v2.name.lower(): + if SimilarVarsDetection.similar(v1.name, v2.name): + if (v2, v1) not in ret: + ret.append((v1, v2)) return set(ret) From 173698d8e0b598ad2a79e5eab20db48bf601d898 Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Sat, 3 Jun 2023 11:55:54 -0400 Subject: [PATCH 060/338] linting --- slither/detectors/variables/similar_variables.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 7cb10cbd5..9f8eaaa2d 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -68,10 +68,11 @@ class SimilarVarsDetection(AbstractDetector): all_var = list(set(all_var + contract_var)) ret = [] + # pylint: disable=consider-using-enumerate for i in range(len(all_var)): v1 = all_var[i] _v1_name_lower = v1.name.lower() - for j in range(i,len(all_var)): + for j in range(i, len(all_var)): v2 = all_var[j] if _v1_name_lower != v2.name.lower(): if SimilarVarsDetection.similar(v1.name, v2.name): From 5f9abc2e89e8d49eb20a1d4b882ec98721b5381f Mon Sep 17 00:00:00 2001 From: A23187 <41769181+A-23187@users.noreply.github.com> Date: Sun, 4 Jun 2023 02:14:59 +0800 Subject: [PATCH 061/338] fix evm printer for solc > 0.6.0 (#1567) --- slither/analyses/evm/convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/analyses/evm/convert.py b/slither/analyses/evm/convert.py index bff308cbc..5e8c4a128 100644 --- a/slither/analyses/evm/convert.py +++ b/slither/analyses/evm/convert.py @@ -186,7 +186,7 @@ def generate_source_to_evm_ins_mapping(evm_instructions, srcmap_runtime, slither if mapping_item[i] == "": mapping_item[i] = int(prev_mapping[i]) - offset, _length, file_id, _ = mapping_item + offset, _length, file_id, *_ = mapping_item prev_mapping = mapping_item if file_id == "-1": From 0c27b000aa6d1ffd88439078af4086ee0cd12542 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 5 Jun 2023 09:22:27 -0500 Subject: [PATCH 062/338] add support for prevrando (solc 0.8.18) --- CONTRIBUTING.md | 2 +- slither/core/declarations/solidity_variables.py | 4 +++- slither/solc_parsing/yul/evm_functions.py | 3 +++ tests/e2e/solc_parsing/test_ast_parsing.py | 1 + ...lobal_variables-0.8.18.sol-0.8.18-compact.zip | Bin 0 -> 2023 bytes ...obal_variables-0.8.18.sol-0.8.18-compact.json | 6 ++++++ .../test_data/global_variables-0.8.18.sol | 11 +++++++++++ 7 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/compile/global_variables-0.8.18.sol-0.8.18-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/global_variables-0.8.18.sol-0.8.18-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/global_variables-0.8.18.sol diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d1a9497f..c00fda8aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,7 +106,7 @@ For each new detector, at least one regression tests must be present. > - To run tests for a specific test case, run `pytest tests/e2e/solc_parsing/test_ast_parsing.py -k user_defined_value_type` (the filename is the argument). > - To run tests for a specific version, run `pytest tests/e2e/solc_parsing/test_ast_parsing.py -k 0.8.12`. > - To run tests for a specific compiler json format, run `pytest tests/e2e/solc_parsing/test_ast_parsing.py -k legacy` (can be legacy or compact). -> - The IDs of tests can be inspected using ``pytest tests/e2e/solc_parsing/test_ast_parsing.py --collect-only`. +> - The IDs of tests can be inspected using `pytest tests/e2e/solc_parsing/test_ast_parsing.py --collect-only`. ### Synchronization with crytic-compile diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 552cf9e7f..f6a0f0839 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -21,10 +21,11 @@ SOLIDITY_VARIABLES_COMPOSED = { "block.basefee": "uint", "block.coinbase": "address", "block.difficulty": "uint256", + "block.prevrandao": "uint256", "block.gaslimit": "uint256", "block.number": "uint256", "block.timestamp": "uint256", - "block.blockhash": "uint256", # alias for blockhash. It's a call + "block.blockhash": "bytes32", # alias for blockhash. It's a call "block.chainid": "uint256", "msg.data": "bytes", "msg.gas": "uint256", @@ -60,6 +61,7 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "log2(bytes32,bytes32,bytes32)": [], "log3(bytes32,bytes32,bytes32,bytes32)": [], "blockhash(uint256)": ["bytes32"], + "prevrandao()": ["uint256"], # the following need a special handling # as they are recognized as a SolidityVariableComposed # and converted to a SolidityFunction by SlithIR diff --git a/slither/solc_parsing/yul/evm_functions.py b/slither/solc_parsing/yul/evm_functions.py index dfb52a244..28ea70e93 100644 --- a/slither/solc_parsing/yul/evm_functions.py +++ b/slither/solc_parsing/yul/evm_functions.py @@ -51,6 +51,7 @@ evm_opcodes = [ "TIMESTAMP", "NUMBER", "DIFFICULTY", + "PREVRANDAO", "GASLIMIT", "CHAINID", "SELFBALANCE", @@ -168,6 +169,7 @@ builtins = [ ) ] + yul_funcs +# "identifier": [input_count, output_count] function_args = { "byte": [2, 1], "addmod": [3, 1], @@ -221,6 +223,7 @@ function_args = { "timestamp": [0, 1], "number": [0, 1], "difficulty": [0, 1], + "prevrandao": [0, 1], "gaslimit": [0, 1], } diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index a561343de..316f2cc38 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -308,6 +308,7 @@ ALL_TESTS = [ Test("units_and_global_variables-0.8.0.sol", VERSIONS_08), Test("units_and_global_variables-0.8.4.sol", make_version(8, 4, 6)), Test("units_and_global_variables-0.8.7.sol", make_version(8, 7, 9)), + Test("global_variables-0.8.18.sol", make_version(8, 18, 18)), Test( "push-all.sol", ALL_VERSIONS, diff --git a/tests/e2e/solc_parsing/test_data/compile/global_variables-0.8.18.sol-0.8.18-compact.zip b/tests/e2e/solc_parsing/test_data/compile/global_variables-0.8.18.sol-0.8.18-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..04dde0da9c01b3b5d61bed184e30c285e572dcdd GIT binary patch literal 2023 zcmb8wX&}=N0|)TmHb-TKa>TIY$dxk;WgCAL!rVfHEk_t8k!0nXE1L)*=fs~mQYngM z2uUqD|BhUV_qT3X>BoU*#)5@iApwf*vWXe?QYMHI;wy3OjdMbYv>Z>Dkr+TYY)y<) zAk3sKpyNePyfpvVb}eGHa>5v`q12ajpHwS;^jMNqUftu7ddNoas;#2#7Y(5^jMTTxyUTEcEN+Es#yzL4wJppOt-=qZ$3zdOOa`L6Yc5*c1?V* zLBc|XbaRS3Xirw9NbF2ouyokFw5pW+nkSU?aR(~Acv3|g2=6m+!q6b3i1?a8tV=RZ zE%erv%eYa&!e;EeY5vKwQ~{mdLDXL82V2%S+4MGeVOA!k{sm~+E-pLDjAQ+9-SG(d zK(^|I>U}%=_#}V(cVk}*&CAz}dfy%Hoj%pV8877Y!7SG&G!oiv*Dc-3@nSzR@*9=k zHhpWLFj(;oD{gu_Hj?x!x5 zuURqDb6Sn)nnoaD?l;a|XgcP`*Bon;?OC*I7_W9PX(Sd?jS@Rhf4HUZgs7K^hhFq>7Rqk`rpOB*nw!pU zMCrKJdJ2>ZyDwl=DqqG%V0wI5;i6$`L#9)19B}dVXXILroN0J^YFU)e3x?0v2c0^W zxgdyx*4R>7#7Xta#b0c?NFZ}q5@W3j?Kt^MXnlaLmiF^5_0ED!_w!6f{(jx_gRHgu zY`s07izK%en`PG0;0VflZ~3i%fh|~SYJ`3$-GyNo>y)~g-5S788>8pwGuB`p1_8-4 z@7~-xlCZ*c!P+_FN=?=5ha;f0GZkTWqkG8ZVqEQkJni531=1m7h)_{`3w3n#q5C(d z;v@qDL~U$A{ozgQ z`(*~NjvVYdXf3xPn>JezeM`@nXp)`b?5vbKLt|{Q35GTe_k+fK!}hNV(@!snq|Wb{ z?AXn`#TmY`n9BDIrh^-}33~lsvxj`SHI=>UYZ=4!#dCE{p0nPUjnUPGsC}m?Ui&ii zw*Dy!iMeOBd%TqU9bQB$f8jXYVbYrT%ro%lg!zwPXVr{<ump%om zej+p!arKaqBqHQy(R&dEUA2lOm;n-WR*!3L{W*S0?*j(B!~YPRVsxedvYwW95sL>8 zC-+nBE*d=&Al}wm4CYVFI6tZ+&#q1T?3$25T(LfJZS%|bCriy+P1k=7eF)8YVW~Ce zi?}W{V8kGOFYguuxq3WL98~DT7EiFQxwkom#?NQJX>tF#RkVgG>$8kBq<}cr83RK% zskZmu(?n^?3D&M~j~Tke=XbRVNQKXXx4p05G%-geiyPy-j0~5d3e9b!(pM8c;U$IX zk8@G~2!ey=>cAz*AuNj+-Aw-`n1z!=?%P)(R`4q2b{J32%5kRHMoE=*^E!-D@-QUu zx5x+63&QI>tVSl9Q;}_;B+1Wncd}UPTYJnUoUhIllmP~`1_)HwN2=6unZZ1z%X|^? zVs2;y@e_DLkr-P+(F5^oxgT+Zuewxyue3Mq1}61w5KlMx_2g#f`~eDF47*)02Q@md z_43V75y9WS>f&5(qFhIfI^Me<#H`KJ5^rm*mayCrhZM}#ox1cP@8<=qHQ}&~K9q8_ zCMq&akR`BK2@5xgVmza;pr4qpW5Q>jtcA9mJBmeYrayAGDVd=;Z}eET&8|>dqR*}x zOH@l^TMO(YF$CAR(()_keKWh_@*BI3W89G6@;Z>~c~(R4EBL2kP9A8%%Ek(`Uo)F` z$~o^r@+(h$c}Hp7ooiRyRWxx?PXVwtl1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/global_variables-0.8.18.sol b/tests/e2e/solc_parsing/test_data/global_variables-0.8.18.sol new file mode 100644 index 000000000..f21ae5d8f --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/global_variables-0.8.18.sol @@ -0,0 +1,11 @@ +contract C { + function f() public view returns (uint256) { + return block.prevrandao; + } + + function g() public view returns (uint256 ret) { + assembly { + ret := prevrandao() + } + } +} \ No newline at end of file From 30a4428e6bf65975ba1330ded69e8eb2ec246829 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 7 Jun 2023 07:42:03 -0500 Subject: [PATCH 063/338] use current scope instead of parent scope to determine if arith. is checked --- slither/core/cfg/scope.py | 6 +- slither/solc_parsing/declarations/function.py | 139 +++++++----------- 2 files changed, 56 insertions(+), 89 deletions(-) diff --git a/slither/core/cfg/scope.py b/slither/core/cfg/scope.py index d3ac4e836..3f9959851 100644 --- a/slither/core/cfg/scope.py +++ b/slither/core/cfg/scope.py @@ -7,8 +7,10 @@ if TYPE_CHECKING: # pylint: disable=too-few-public-methods class Scope: - def __init__(self, is_checked: bool, is_yul: bool, scope: Union["Scope", "Function"]) -> None: + def __init__( + self, is_checked: bool, is_yul: bool, parent_scope: Union["Scope", "Function"] + ) -> None: self.nodes: List["Node"] = [] self.is_checked = is_checked self.is_yul = is_yul - self.father = scope + self.father = parent_scope diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 5a29a9b50..af87892bc 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -354,7 +354,7 @@ class FunctionSolc(CallerContextExpression): ################################################################################### ################################################################################### - def _parse_if(self, if_statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_if(self, if_statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: # IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? falseStatement = None @@ -362,21 +362,15 @@ class FunctionSolc(CallerContextExpression): condition = if_statement["condition"] # Note: check if the expression could be directly # parsed here - condition_node = self._new_node( - NodeType.IF, condition["src"], node.underlying_node.scope - ) + condition_node = self._new_node(NodeType.IF, condition["src"], scope) condition_node.add_unparsed_expression(condition) link_underlying_nodes(node, condition_node) - true_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + true_scope = Scope(scope.is_checked, False, scope) trueStatement = self._parse_statement( if_statement["trueBody"], condition_node, true_scope ) if "falseBody" in if_statement and if_statement["falseBody"]: - false_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + false_scope = Scope(scope.is_checked, False, scope) falseStatement = self._parse_statement( if_statement["falseBody"], condition_node, false_scope ) @@ -385,22 +379,16 @@ class FunctionSolc(CallerContextExpression): condition = children[0] # Note: check if the expression could be directly # parsed here - condition_node = self._new_node( - NodeType.IF, condition["src"], node.underlying_node.scope - ) + condition_node = self._new_node(NodeType.IF, condition["src"], scope) condition_node.add_unparsed_expression(condition) link_underlying_nodes(node, condition_node) - true_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + true_scope = Scope(scope.is_checked, False, scope) trueStatement = self._parse_statement(children[1], condition_node, true_scope) if len(children) == 3: - false_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + false_scope = Scope(scope.is_checked, False, scope) falseStatement = self._parse_statement(children[2], condition_node, false_scope) - endIf_node = self._new_node(NodeType.ENDIF, if_statement["src"], node.underlying_node.scope) + endIf_node = self._new_node(NodeType.ENDIF, if_statement["src"], scope) link_underlying_nodes(trueStatement, endIf_node) if falseStatement: @@ -409,32 +397,26 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(condition_node, endIf_node) return endIf_node - def _parse_while(self, whilte_statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_while(self, whilte_statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: # WhileStatement = 'while' '(' Expression ')' Statement - node_startWhile = self._new_node( - NodeType.STARTLOOP, whilte_statement["src"], node.underlying_node.scope - ) + node_startWhile = self._new_node(NodeType.STARTLOOP, whilte_statement["src"], scope) - body_scope = Scope(node.underlying_node.scope.is_checked, False, node.underlying_node.scope) + body_scope = Scope(scope.is_checked, False, scope) if self.is_compact_ast: node_condition = self._new_node( - NodeType.IFLOOP, whilte_statement["condition"]["src"], node.underlying_node.scope + NodeType.IFLOOP, whilte_statement["condition"]["src"], scope ) node_condition.add_unparsed_expression(whilte_statement["condition"]) statement = self._parse_statement(whilte_statement["body"], node_condition, body_scope) else: children = whilte_statement[self.get_children("children")] expression = children[0] - node_condition = self._new_node( - NodeType.IFLOOP, expression["src"], node.underlying_node.scope - ) + node_condition = self._new_node(NodeType.IFLOOP, expression["src"], scope) node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition, body_scope) - node_endWhile = self._new_node( - NodeType.ENDLOOP, whilte_statement["src"], node.underlying_node.scope - ) + node_endWhile = self._new_node(NodeType.ENDLOOP, whilte_statement["src"], scope) link_underlying_nodes(node, node_startWhile) link_underlying_nodes(node_startWhile, node_condition) @@ -562,7 +544,7 @@ class FunctionSolc(CallerContextExpression): return pre, cond, post, body - def _parse_for(self, statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_for(self, statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: # ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement if self.is_compact_ast: @@ -570,17 +552,13 @@ class FunctionSolc(CallerContextExpression): else: pre, cond, post, body = self._parse_for_legacy_ast(statement) - node_startLoop = self._new_node( - NodeType.STARTLOOP, statement["src"], node.underlying_node.scope - ) - node_endLoop = self._new_node( - NodeType.ENDLOOP, statement["src"], node.underlying_node.scope - ) + node_startLoop = self._new_node(NodeType.STARTLOOP, statement["src"], scope) + node_endLoop = self._new_node(NodeType.ENDLOOP, statement["src"], scope) - last_scope = node.underlying_node.scope + last_scope = scope if pre: - pre_scope = Scope(node.underlying_node.scope.is_checked, False, last_scope) + pre_scope = Scope(scope.is_checked, False, last_scope) last_scope = pre_scope node_init_expression = self._parse_statement(pre, node, pre_scope) link_underlying_nodes(node_init_expression, node_startLoop) @@ -588,7 +566,7 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node, node_startLoop) if cond: - cond_scope = Scope(node.underlying_node.scope.is_checked, False, last_scope) + cond_scope = Scope(scope.is_checked, False, last_scope) last_scope = cond_scope node_condition = self._new_node(NodeType.IFLOOP, cond["src"], cond_scope) node_condition.add_unparsed_expression(cond) @@ -599,7 +577,7 @@ class FunctionSolc(CallerContextExpression): node_condition = None node_beforeBody = node_startLoop - body_scope = Scope(node.underlying_node.scope.is_checked, False, last_scope) + body_scope = Scope(scope.is_checked, False, last_scope) last_scope = body_scope node_body = self._parse_statement(body, node_beforeBody, body_scope) @@ -619,14 +597,10 @@ class FunctionSolc(CallerContextExpression): return node_endLoop - def _parse_dowhile(self, do_while_statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_dowhile(self, do_while_statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: - node_startDoWhile = self._new_node( - NodeType.STARTLOOP, do_while_statement["src"], node.underlying_node.scope - ) - condition_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + node_startDoWhile = self._new_node(NodeType.STARTLOOP, do_while_statement["src"], scope) + condition_scope = Scope(scope.is_checked, False, scope) if self.is_compact_ast: node_condition = self._new_node( @@ -644,7 +618,7 @@ class FunctionSolc(CallerContextExpression): node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition, condition_scope) - body_scope = Scope(node.underlying_node.scope.is_checked, False, condition_scope) + body_scope = Scope(scope.is_checked, False, condition_scope) node_endDoWhile = self._new_node(NodeType.ENDLOOP, do_while_statement["src"], body_scope) link_underlying_nodes(node, node_startDoWhile) @@ -660,29 +634,27 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node_condition, node_endDoWhile) return node_endDoWhile - def _parse_try_catch(self, statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_try_catch(self, statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: externalCall = statement.get("externalCall", None) if externalCall is None: raise ParsingError(f"Try/Catch not correctly parsed by Slither {statement}") - catch_scope = Scope( - node.underlying_node.scope.is_checked, False, node.underlying_node.scope - ) + catch_scope = Scope(scope.is_checked, False, scope) new_node = self._new_node(NodeType.TRY, statement["src"], catch_scope) new_node.add_unparsed_expression(externalCall) link_underlying_nodes(node, new_node) node = new_node for clause in statement.get("clauses", []): - self._parse_catch(clause, node) + self._parse_catch(clause, node, scope) return node - def _parse_catch(self, statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_catch(self, statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: block = statement.get("block", None) if block is None: raise ParsingError(f"Catch not correctly parsed by Slither {statement}") - try_scope = Scope(node.underlying_node.scope.is_checked, False, node.underlying_node.scope) + try_scope = Scope(scope.is_checked, False, scope) try_node = self._new_node(NodeType.CATCH, statement["src"], try_scope) link_underlying_nodes(node, try_node) @@ -699,7 +671,7 @@ class FunctionSolc(CallerContextExpression): return self._parse_statement(block, try_node, try_scope) - def _parse_variable_definition(self, statement: Dict, node: NodeSolc) -> NodeSolc: + def _parse_variable_definition(self, statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: try: local_var = LocalVariable() local_var.set_function(self._function) @@ -709,9 +681,7 @@ class FunctionSolc(CallerContextExpression): self._add_local_variable(local_var_parser) # local_var.analyze(self) - new_node = self._new_node( - NodeType.VARIABLE, statement["src"], node.underlying_node.scope - ) + new_node = self._new_node(NodeType.VARIABLE, statement["src"], scope) new_node.underlying_node.add_variable_declaration(local_var) link_underlying_nodes(node, new_node) return new_node @@ -741,7 +711,7 @@ class FunctionSolc(CallerContextExpression): "declarations": [variable], "initialValue": init, } - new_node = self._parse_variable_definition(new_statement, new_node) + new_node = self._parse_variable_definition(new_statement, new_node, scope) else: # If we have @@ -763,7 +733,7 @@ class FunctionSolc(CallerContextExpression): variables.append(variable) new_node = self._parse_variable_definition_init_tuple( - new_statement, i, new_node + new_statement, i, new_node, scope ) i = i + 1 @@ -795,9 +765,7 @@ class FunctionSolc(CallerContextExpression): "typeDescriptions": {"typeString": "tuple()"}, } node = new_node - new_node = self._new_node( - NodeType.EXPRESSION, statement["src"], node.underlying_node.scope - ) + new_node = self._new_node(NodeType.EXPRESSION, statement["src"], scope) new_node.add_unparsed_expression(expression) link_underlying_nodes(node, new_node) @@ -877,16 +845,14 @@ class FunctionSolc(CallerContextExpression): ], } node = new_node - new_node = self._new_node( - NodeType.EXPRESSION, statement["src"], node.underlying_node.scope - ) + new_node = self._new_node(NodeType.EXPRESSION, statement["src"], scope) new_node.add_unparsed_expression(expression) link_underlying_nodes(node, new_node) return new_node def _parse_variable_definition_init_tuple( - self, statement: Dict, index: int, node: NodeSolc + self, statement: Dict, index: int, node: NodeSolc, scope ) -> NodeSolc: local_var = LocalVariableInitFromTuple() local_var.set_function(self._function) @@ -896,7 +862,7 @@ class FunctionSolc(CallerContextExpression): self._add_local_variable(local_var_parser) - new_node = self._new_node(NodeType.VARIABLE, statement["src"], node.underlying_node.scope) + new_node = self._new_node(NodeType.VARIABLE, statement["src"], scope) new_node.underlying_node.add_variable_declaration(local_var) link_underlying_nodes(node, new_node) return new_node @@ -917,15 +883,15 @@ class FunctionSolc(CallerContextExpression): name = statement[self.get_key()] # SimpleStatement = VariableDefinition | ExpressionStatement if name == "IfStatement": - node = self._parse_if(statement, node) + node = self._parse_if(statement, node, scope) elif name == "WhileStatement": - node = self._parse_while(statement, node) + node = self._parse_while(statement, node, scope) elif name == "ForStatement": - node = self._parse_for(statement, node) + node = self._parse_for(statement, node, scope) elif name == "Block": - node = self._parse_block(statement, node) + node = self._parse_block(statement, node, scope) elif name == "UncheckedBlock": - node = self._parse_unchecked_block(statement, node) + node = self._parse_unchecked_block(statement, node, scope) elif name == "InlineAssembly": # Added with solc 0.6 - the yul code is an AST if "AST" in statement and not self.compilation_unit.core.skip_assembly: @@ -947,7 +913,7 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node, asm_node) node = asm_node elif name == "DoWhileStatement": - node = self._parse_dowhile(statement, node) + node = self._parse_dowhile(statement, node, scope) # For Continue / Break / Return / Throw # The is fixed later elif name == "Continue": @@ -988,7 +954,7 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node, new_node) node = new_node elif name in ["VariableDefinitionStatement", "VariableDeclarationStatement"]: - node = self._parse_variable_definition(statement, node) + node = self._parse_variable_definition(statement, node, scope) elif name == "ExpressionStatement": # assert len(statement[self.get_children('expression')]) == 1 # assert not 'attributes' in statement @@ -1002,7 +968,7 @@ class FunctionSolc(CallerContextExpression): link_underlying_nodes(node, new_node) node = new_node elif name == "TryStatement": - node = self._parse_try_catch(statement, node) + node = self._parse_try_catch(statement, node, scope) # elif name == 'TryCatchClause': # self._parse_catch(statement, node) elif name == "RevertStatement": @@ -1019,7 +985,7 @@ class FunctionSolc(CallerContextExpression): return node - def _parse_block(self, block: Dict, node: NodeSolc, check_arithmetic: bool = False) -> NodeSolc: + def _parse_block(self, block: Dict, node: NodeSolc, scope: Scope) -> NodeSolc: """ Return: Node @@ -1031,13 +997,12 @@ class FunctionSolc(CallerContextExpression): else: statements = block[self.get_children("children")] - check_arithmetic = check_arithmetic | node.underlying_node.scope.is_checked - new_scope = Scope(check_arithmetic, False, node.underlying_node.scope) + new_scope = Scope(scope.is_checked, False, scope) for statement in statements: node = self._parse_statement(statement, node, new_scope) return node - def _parse_unchecked_block(self, block: Dict, node: NodeSolc): + def _parse_unchecked_block(self, block: Dict, node: NodeSolc, scope): """ Return: Node @@ -1049,7 +1014,8 @@ class FunctionSolc(CallerContextExpression): else: statements = block[self.get_children("children")] - new_scope = Scope(False, False, node.underlying_node.scope) + new_scope = Scope(False, False, scope) + for statement in statements: node = self._parse_statement(statement, node, new_scope) return node @@ -1070,8 +1036,7 @@ class FunctionSolc(CallerContextExpression): self._function.is_empty = True else: self._function.is_empty = False - check_arithmetic = self.compilation_unit.solc_version >= "0.8.0" - self._parse_block(cfg, node, check_arithmetic=check_arithmetic) + self._parse_block(cfg, node, self.underlying_function) self._remove_incorrect_edges() self._remove_alone_endif() From 831b3b2d5d1578e47c531f2dc62ed0b3df4180e0 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan <60320285+Tiko7454@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:00:15 +0400 Subject: [PATCH 064/338] local variable location fix (#1942) * Local variable location fix When we had a function f() which returns a pair, the result passed to local variables didn't initialize the location attribute. For example: contract A { function f() public returns (int, bytes memory) { return (1, "asdf"); } function g() public { (int x, bytes memory y) = f(); } } the location of the local variable x as well as the location of the local variable y was None * moved the fixes to the proper file * removed useless newlines --- .../local_variable_init_from_tuple.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/slither/solc_parsing/variables/local_variable_init_from_tuple.py b/slither/solc_parsing/variables/local_variable_init_from_tuple.py index 1a551c695..f1c872848 100644 --- a/slither/solc_parsing/variables/local_variable_init_from_tuple.py +++ b/slither/solc_parsing/variables/local_variable_init_from_tuple.py @@ -16,3 +16,21 @@ class LocalVariableInitFromTupleSolc(VariableDeclarationSolc): # Todo: Not sure how to overcome this with mypy assert isinstance(self._variable, LocalVariableInitFromTuple) return self._variable + + def _analyze_variable_attributes(self, attributes: Dict) -> None: + """' + Variable Location + Can be storage/memory or default + """ + if "storageLocation" in attributes: + location = attributes["storageLocation"] + self.underlying_variable.set_location(location) + else: + if "memory" in attributes["type"]: + self.underlying_variable.set_location("memory") + elif "storage" in attributes["type"]: + self.underlying_variable.set_location("storage") + else: + self.underlying_variable.set_location("default") + + super()._analyze_variable_attributes(attributes) From 3ed6dee1a374d02212d0ff288e57c0e5442dcf0e Mon Sep 17 00:00:00 2001 From: Kevin Clancy Date: Wed, 7 Jun 2023 15:50:07 -0700 Subject: [PATCH 065/338] fix: make _convert_to_structure_to_list return a type instead of an ElementaryType's `type` field (#1935) * make _convert_to_structure_to_list return a type instead of an elementary type's type field * fix pylint warning preventing me from using elif after a return * re-arranged the assert and isinstance check * removed extra colon * reformatted --- slither/slithir/convert.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 665a7c8f9..63c3745eb 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1583,7 +1583,9 @@ def _convert_to_structure_to_list(return_type: Type) -> List[Type]: # } if isinstance(return_type, (MappingType, ArrayType)): return [] - return [return_type.type] + + assert isinstance(return_type, (ElementaryType, UserDefinedType, TypeAlias)) + return [return_type] def convert_type_of_high_and_internal_level_call( From adabce6180522059d25ced40b260c121eded0d4e Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Thu, 8 Jun 2023 19:47:53 +0200 Subject: [PATCH 066/338] Detect when ether is sent in Yul (#1909) * Detect when ether is sent in Yul * address pylint warning instead of supressing * fix guard clause * remove branch to appease pylint * check that call can send eth prior to reading args --------- Co-authored-by: alpharush <0xalpharush@protonmail.com> --- slither/detectors/attributes/locked_ether.py | 28 ++++++++++++++++-- ...LockedEther_0_4_25_locked_ether_sol__0.txt | 7 ++++- ...LockedEther_0_5_16_locked_ether_sol__0.txt | 7 ++++- ...LockedEther_0_6_11_locked_ether_sol__0.txt | 2 +- ..._LockedEther_0_7_6_locked_ether_sol__0.txt | 2 +- .../locked-ether/0.4.25/locked_ether.sol | 11 +++++++ .../0.4.25/locked_ether.sol-0.4.25.zip | Bin 3082 -> 3497 bytes .../locked-ether/0.5.16/locked_ether.sol | 11 +++++++ .../0.5.16/locked_ether.sol-0.5.16.zip | Bin 3063 -> 3457 bytes .../locked-ether/0.6.11/locked_ether.sol | 10 +++++++ .../0.6.11/locked_ether.sol-0.6.11.zip | Bin 3078 -> 3560 bytes .../locked-ether/0.7.6/locked_ether.sol | 10 +++++++ .../0.7.6/locked_ether.sol-0.7.6.zip | Bin 2998 -> 3478 bytes 13 files changed, 81 insertions(+), 7 deletions(-) diff --git a/slither/detectors/attributes/locked_ether.py b/slither/detectors/attributes/locked_ether.py index a6f882922..91ec68650 100644 --- a/slither/detectors/attributes/locked_ether.py +++ b/slither/detectors/attributes/locked_ether.py @@ -3,7 +3,7 @@ """ from typing import List -from slither.core.declarations.contract import Contract +from slither.core.declarations import Contract, SolidityFunction from slither.detectors.abstract_detector import ( AbstractDetector, DetectorClassification, @@ -17,7 +17,9 @@ from slither.slithir.operations import ( NewContract, LibraryCall, InternalCall, + SolidityCall, ) +from slither.slithir.variables import Constant from slither.utils.output import Output @@ -68,8 +70,28 @@ Every Ether sent to `Locked` will be lost.""" ): if ir.call_value and ir.call_value != 0: return False - if isinstance(ir, (LowLevelCall)): - if ir.function_name in ["delegatecall", "callcode"]: + if isinstance(ir, (LowLevelCall)) and ir.function_name in [ + "delegatecall", + "callcode", + ]: + return False + if isinstance(ir, SolidityCall): + call_can_send_ether = ir.function in [ + SolidityFunction( + "delegatecall(uint256,uint256,uint256,uint256,uint256,uint256)" + ), + SolidityFunction( + "callcode(uint256,uint256,uint256,uint256,uint256,uint256,uint256)" + ), + SolidityFunction( + "call(uint256,uint256,uint256,uint256,uint256,uint256,uint256)" + ), + ] + nonzero_call_value = call_can_send_ether and ( + not isinstance(ir.arguments[2], Constant) + or ir.arguments[2].value != 0 + ) + if nonzero_call_value: return False # If a new internal call or librarycall # Add it to the list to explore diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_4_25_locked_ether_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_4_25_locked_ether_sol__0.txt index edca6eb2e..680f77d0d 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_4_25_locked_ether_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_4_25_locked_ether_sol__0.txt @@ -1,5 +1,10 @@ Contract locking ether found: - Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol#26) has payable functions: + Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol#37) has payable functions: + - Locked.receive() (tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol#4-6) + But does not have a function to withdraw the ether + +Contract locking ether found: + Contract UnlockedAssembly (tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol#27-35) has payable functions: - Locked.receive() (tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol#4-6) But does not have a function to withdraw the ether diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_5_16_locked_ether_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_5_16_locked_ether_sol__0.txt index d1ff3314b..961ba8c48 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_5_16_locked_ether_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_5_16_locked_ether_sol__0.txt @@ -1,5 +1,10 @@ Contract locking ether found: - Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol#26) has payable functions: + Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol#37) has payable functions: + - Locked.receive() (tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol#4-6) + But does not have a function to withdraw the ether + +Contract locking ether found: + Contract UnlockedAssembly (tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol#27-35) has payable functions: - Locked.receive() (tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol#4-6) But does not have a function to withdraw the ether diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_6_11_locked_ether_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_6_11_locked_ether_sol__0.txt index 212015c29..079104879 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_6_11_locked_ether_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_6_11_locked_ether_sol__0.txt @@ -1,5 +1,5 @@ Contract locking ether found: - Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol#26) has payable functions: + Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol#36) has payable functions: - Locked.receive_eth() (tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol#4-6) But does not have a function to withdraw the ether diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_7_6_locked_ether_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_7_6_locked_ether_sol__0.txt index 8b6ddfa59..14835871f 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_7_6_locked_ether_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LockedEther_0_7_6_locked_ether_sol__0.txt @@ -1,5 +1,5 @@ Contract locking ether found: - Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.7.6/locked_ether.sol#26) has payable functions: + Contract OnlyLocked (tests/e2e/detectors/test_data/locked-ether/0.7.6/locked_ether.sol#36) has payable functions: - Locked.receive_eth() (tests/e2e/detectors/test_data/locked-ether/0.7.6/locked_ether.sol#4-6) But does not have a function to withdraw the ether diff --git a/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol b/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol index 65942ed2e..f3be911be 100644 --- a/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol +++ b/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol @@ -23,4 +23,15 @@ contract Unlocked is Locked, Send{ } +// Still reported because solidity < 0.6.0 doesn't have assembly in the AST +contract UnlockedAssembly is Locked{ + + function withdraw() public { + assembly { + let success := call(gas(), caller(),100,0,0,0,0) + } + } + +} + contract OnlyLocked is Locked{ } diff --git a/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol-0.4.25.zip b/tests/e2e/detectors/test_data/locked-ether/0.4.25/locked_ether.sol-0.4.25.zip index b6092ecdb88e0c093fca52733727fc3c9715fc5e..e3e6f6c2193b35ead58cb3ceb458bdeac28bca9e 100644 GIT binary patch delta 3388 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 S007)wle`N^20;w~00006^P}bf delta 2969 zcmV;K3ug4G8;TekP)h>@KL7#%4gfZdcUGwag~(tF007`l001PDYz-%oLMngpM-PRi zm0nlZdjJq|?-l5q5W}VAK!X$~yhYNz{x3$S;g((ndY>|}t(QfD>0DX%3?)eh2qMDV z%C@wv9=7dQwIh!2zm5U0T8cs0s5KJCc6PbrL z6p`Gd#^laN}4z1j;Ewe&CIpcnVR?t$XFn2lc$z7nS6g5di!6A9MSbP zZpc9JVUJ#%*cxGdXxJo`;PWqvjO1_mne0P}ezM|cw0rK)jLu2>b$fzQ$*Pui_VHKN zfg~2_YRmZ(AbODMz_sRUt?+Wb(Pqi|xjjM;7i(6*G`Xu|W`9u=!eEG-_=$V7h!QNX zs(+D1&ILyzF8F|O%Upl`Of&=_XkB>|#CLI%D^lfc#@otO1McjQme0L^6L7p8!%iuX z6C`rcP^iFydQPlnk)LV17oOi%2-cV3>Q*h-g6L&jvxbH7wBCz99}Hj04I9DBGbLGb zpb>l|xX^CE0#-|!nhq0!QD~Wwi3DvoJi3Y2t|xd~m(0Tar7;B`_{{r2yRfJ zA@?BL**}V)N-uu`bR`=0{#IAG_Shvhpxjrfxxuf;OcLN8G01xK=yXg&H8Ln4mxQ08 zKnuj@zjg?*Ss;p69E3CN3QEjl&0@l{*P9A^v;_z6OF{3AdCJ7B1<*HofAc!vCi;Bk zIV_%QS9ec%%B&O2XD`AbO{E8b7dE2um=oHrPDo=k@cw90Es4j6`Tqe7DK^2^!TJO_`QeWPSD2_=T%%BE6&?Mgvo8l~b;Y=jggxaamejFb;kmb! zjB`K%%t%$@bYVA(3uS@f78@Yf_nTSDJV&coz9c+5hLSv-3q%@H;@huGq^1ck?+JzS zLr$o2ajK$Hd$f7#^y;DfJS-CTw$GJgeUE?DYXF6;O{yZ1BUQ^`QK4U#lx>lZ9l*~S z1fF7ZCWFTIa}QuHE+V-bcWroMk&tR!ZvHU#yF)iVhL$Wvb-ZGQR)IzmWMzs;Mu&(lEJXZjASMd6MVn@TWTB~4GQW&PyG+$7^B~huZLv@l~l(bssmVz=K%Uo9qYcrLf@0WN->_OtRUhjVV`xTdC zAbaakT}5qTcu)Dlz#GhAOuXqgdjfyTeI>OHL0OEM-qW%(;5dR{Elsoz$fr92ufL963zYD!btHRU_KBt6QmAwncr^`P;?|2B|eHkhzqF*O9tL7Xp$0bw~ z<#evm-1;m>dBX>(pqhVXU(+=pmN43?O+?Hmk1$XaoHN*9{Y5L-dn)0CBwpet~T*F;H-Q#705TG4# zn{?du-ZyDVp;pv2CeGEwA<=I*{?RR5hQ+no%2N_@%^7^{zD|F4ipiDZ-y(8hIa2(L zT^?OZAD!5_iHgjlAaZ>6Iu=i<1Leubr@t!B3av~|1Oq-ZC|Aq6`(1BHaPDUUw=(gl zE9KEv{{JgHJOmIsE+~(s`AE|%YiEU<&7fS(FU(fpVQuv9S}#3nO^*F7ow)BZA07vW zkf}q z$C9wvI);br1i|TWYEmHB33{a3kY=Ty`j(*Z5Job|)mZSO8Efw0!3#=ew&FX>x>XCrRl7;7rAQHwM}|%L z_IAYkM2CM7!neg0V?E{)xKz!59pWzL<8RSfC_=oEZ~v+4jIwpgnL-VzZ6`a>c**8w ziMXn~zg>fjNt7x4Qx39i_$ zS!lA^L=9ke|7Oa*)bw|nUVQUjWw`My#%U4dKvazH2eQNVTn@i};0`H(bg9TdQXBs_ zOr~bLni58l%kA#gj;PIy)!AVo((gs;DMq4s!7mep`tn-D^r{S!JZ7J_G>~Ey%f#*J z_%&?S@2KB4?8=9$vk~xf*jeXE0xSRPD0zlZO928u13v%)01f~)jdxb50)@z63jhG% PPLo>=NCu({00000hq1`C diff --git a/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol b/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol index 0269ce855..e5671b7ad 100644 --- a/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol +++ b/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol @@ -23,4 +23,15 @@ contract Unlocked is Locked, Send{ } +// Still reported because solidity < 0.6.0 doesn't have assembly in the AST +contract UnlockedAssembly is Locked{ + + function withdraw() public { + assembly { + let success := call(gas(), caller(),100,0,0,0,0) + } + } + +} + contract OnlyLocked is Locked{ } diff --git a/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol-0.5.16.zip b/tests/e2e/detectors/test_data/locked-ether/0.5.16/locked_ether.sol-0.5.16.zip index 88255d730b0a6e7c46c18a15bb93bb7be61ba5e3..5dfba9e3fe6a261361334b8be8f71fb748a8b30e 100644 GIT binary patch delta 3340 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 diff --git a/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol b/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol index 7f02028e7..aef9ca6e7 100644 --- a/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol +++ b/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol @@ -23,4 +23,14 @@ contract Unlocked is Locked, Send{ } +contract UnlockedAssembly is Locked{ + + function withdraw() public { + assembly { + let success := call(gas(), caller(),100,0,0,0,0) + } + } + +} + contract OnlyLocked is Locked{ } diff --git a/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol-0.6.11.zip b/tests/e2e/detectors/test_data/locked-ether/0.6.11/locked_ether.sol-0.6.11.zip index 2408eeb82bab590d4fe3a2a8303bf31cc5528608..48b675d9a326ccc17e93d23e6e5688a6b86dc2e4 100644 GIT binary patch delta 3444 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 BZdCvP delta 2878 zcmV-E3&Hf38@3l1P)h>@KL7#%4gfcecUD(TaRm$u008Dlkr-5e@kbAZrIlV+*LwgE zaqkuAn-IgLTge!$df`E^ z?Ro1j46EM`Z}*duTw66krOU6zS8q;e1dtTox)zjgw1UXsr=oI8HyLI`Vy9nTSv)Cg zDX=l80T7y`ln?PINM2GE_(nrv+XVon9@c(M>t}E|X+U#+2(h*oTbsq8 ze(r>;_2H^rVjObwd9?^p z$w#XXjSg^RjDFr`<5p{m*w`?FKMJMq6e>#TOHT1%2k8-W zd><%|4&2|Lxxsink;s{bM}o%kM4>4K)ulf`keBR!87-ot8hk=j0;AZJ?asR9#z!!k zW07*&f0LGQZNz-i{hSbQelokO2m}5Ct#_xc*mRbia;2ts|iCo(V*?C*d-4 ztXl-6=3M#8k`NpaQv?1w^9XE0zP;^#m&sJ7BLpGwdua3)VTO*xUxARKP1dS+-Y?+O z$8ugs`11>%WLL8OcNXG!NrTV5%QI6#!cbvQsdk}(6ChAkQO9XCyDcV+}I8+zKFCu zpK!B1{~yd1cNE;a4QR3FaDHa94!ZO^P)5OrIPKO5PdgrElvK0ck2y1UX0{@ z8|Xk`S&Da}^GaGqZ*F>cC&M_|9tGxZ?)89SNyEL*bkXK~>Ms#dQpYtBxYGE)&}*sf zn7#E^X$*ywa`H?r=b~`ag#5k?fw3eW)!R$xY=8k2X@m8Nc4Dsp2IX9TDB%adb99wT zxyUx(_uklr77{x6_X?GDnL^SKPHo;d`D%8&3)akO9QuHx(U~<5%Jtk@`x|Xwa@q|K zMs%`M{Nmlidk2oE|8MRxl=`MgwA!{XIZaMvNKo|DVQH5bZg}#Q23t(C!$rIS>V?DN z!)PXJnWlE?RoW4ZK-JKH@nr;bR8V4_9bH&okbSPsZ_$aUl7|#Hh%E*H2)P!xAMwKQ+{8L z6Pr{>i^_dVUO0Cj$`^k4Y)KU}J(C%1XjfVye_K`H;`C8V)x-HCR77+2`K4f|CwcUj z$5IrDuQ7sPS5>Fq(x3Z2~Kq_nw`Px$xF_Y z1IJ4VxvB>=qd{M+A2ft2aJG%r= zA}#cIlJ%Z{3mZ+nS&5Ps^vWMm^)^9LF)oeCwvTZ@IT9IxvvYnv2qYAb6y)C$0gDv% zKl9=a+gW-z9HesN`&)$>&O8;aoA)0Xpu*4E!@O@!>D~Xr7TG0_8w2wGe4M>K&VqU8?LuX*^hT_Qk#tGyXKFAqfP9RovdOb8$pM^(mV zAu}sodzD9+OkM?Kdb?$|=>?(!UjZu`rEt!bHj0nlA&=2Y*VKCL%Dv53P67DU^ttXP z`In9vp!Y1}yqmf3PKf*m660hScN1~AwEqZE;f_NGGIAa)^_XW2q9m-ldkr?^5EbYu z%OB@|gYZcKVBcr$gyGh@s@1F=bFVLSG(Th|ESMk&9#SV^d>O+H!^9;g?Xgp3r!F7P z+XY`A6xVIsWLwIVLhp?L4TyXXrffHqH30e(Z)a|%fq#R3(i_OJzjx~gf0l@a)@A^c zME!93;qRhnvhR)?Ydy%`RJF@a>cLb|jvCZ|y7U-L=y|5Mk*er9GxCv6EMp>35)H3) zB!67?t6v)~r!J(oTp$9kGf0_6M>n>4b8&W4f4;7--~N?+8r|a;F$2FT1JN;cjXr1*SL542&DU zGm%_Di$MW8y0sF-``N`pW)xI=$1**e3u1I7)Jr$M*5jY_?uh1coqLnwy2#Sw&IRts z@-*=|R<9JAR13NterFSm2r8aKBnq@c)*;x=Uv0ADM$-WNgJ^S5O928u13v%~0ssyG cH;s2zS50vR3=04N=17xB4M+w~3jhEB0AYk@LjV8( From d0f12dc710ca488f0ccfbdf3989c884b587176db Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Thu, 8 Jun 2023 23:05:57 +0200 Subject: [PATCH 067/338] Fix bytes pop ir (#1926) --- slither/slithir/convert.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 63c3745eb..d40715c4f 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1363,11 +1363,12 @@ def convert_to_pop(ir: HighLevelCall, node: "Node") -> List[Operation]: # TODO the following is equivalent to length.points_to = arr # Should it be removed? ir_length.lvalue.points_to = arr - # Note bytes is an ElementaryType not ArrayType so in that case we use ir.destination.type + # Note bytes is an ElementaryType not ArrayType and bytes1 should be returned + # since bytes is bytes1[] without padding between the elements # while in other cases such as uint256[] (ArrayType) we use ir.destination.type.type # in this way we will have the type always set to the corresponding ElementaryType element_to_delete.set_type( - ir.destination.type + ElementaryType("bytes1") if isinstance(ir.destination.type, ElementaryType) else ir.destination.type.type ) From c8d20acca6f5039096907757832777f7d2b34bd7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 8 Jun 2023 21:03:45 -0500 Subject: [PATCH 068/338] do not recommend changing mutability for abstract contracts (#1952) --- slither/detectors/variables/unchanged_state_variables.py | 2 ++ slither/detectors/variables/unused_state_variables.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/slither/detectors/variables/unchanged_state_variables.py b/slither/detectors/variables/unchanged_state_variables.py index f12cc5784..0e73ab57b 100644 --- a/slither/detectors/variables/unchanged_state_variables.py +++ b/slither/detectors/variables/unchanged_state_variables.py @@ -87,6 +87,8 @@ class UnchangedStateVariables: def detect(self) -> None: """Detect state variables that could be constant or immutable""" for c in self.compilation_unit.contracts_derived: + if c.is_signature_only(): + continue variables = [] functions = [] diff --git a/slither/detectors/variables/unused_state_variables.py b/slither/detectors/variables/unused_state_variables.py index afb4e3ac5..830ca34ca 100644 --- a/slither/detectors/variables/unused_state_variables.py +++ b/slither/detectors/variables/unused_state_variables.py @@ -20,8 +20,6 @@ from slither.visitors.expression.export_values import ExportValues def detect_unused(contract: Contract) -> Optional[List[StateVariable]]: - if contract.is_signature_only(): - return None # Get all the variables read in all the functions and modifiers all_functions = [ @@ -73,6 +71,8 @@ class UnusedStateVars(AbstractDetector): """Detect unused state variables""" results = [] for c in self.compilation_unit.contracts_derived: + if c.is_signature_only(): + continue unusedVars = detect_unused(c) if unusedVars: for var in unusedVars: From fc9377d28cc3818213f4f5fa39a763c595b10a85 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 8 Jun 2023 21:04:23 -0500 Subject: [PATCH 069/338] fail if artifact does not existing (#1947) --- tests/e2e/solc_parsing/test_ast_parsing.py | 9 +++------ .../expected/yul-top-level-0.8.0.sol-0.8.0-compact.json | 5 +++++ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-top-level-0.8.0.sol-0.8.0-compact.json diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index a561343de..a1d294c1b 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -495,12 +495,9 @@ class TestASTParsing: actual = generate_output(sl) - try: - with open(expected, "r", encoding="utf8") as f: - expected = json.load(f) - except OSError: - pytest.xfail("the file for this test was not generated") - raise + assert os.path.isfile(expected), f"Expected file {expected} does not exist" + with open(expected, "r", encoding="utf8") as f: + expected = json.load(f) diff = DeepDiff(expected, actual, ignore_order=True, verbose_level=2, view="tree") if diff: diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-top-level-0.8.0.sol-0.8.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-top-level-0.8.0.sol-0.8.0-compact.json new file mode 100644 index 000000000..f9655dff5 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/yul-top-level-0.8.0.sol-0.8.0-compact.json @@ -0,0 +1,5 @@ +{ + "Test": { + "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file From 1e709fd5bbc43d39d2639d6d3d16bdd2e0f23d10 Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Sat, 10 Jun 2023 14:24:54 -0400 Subject: [PATCH 070/338] additional optimizations for similar_variables.py --- .../detectors/variables/similar_variables.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 9f8eaaa2d..4aef01b03 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -47,9 +47,7 @@ class SimilarVarsDetection(AbstractDetector): Returns: bool: true if names are similar """ - if len(seq1) != len(seq2): - return False - val = difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() + val = difflib.SequenceMatcher(a=seq1, b=seq2).ratio() ret = val > 0.90 return ret @@ -67,19 +65,21 @@ class SimilarVarsDetection(AbstractDetector): all_var = list(set(all_var + contract_var)) - ret = [] + ret = set() # pylint: disable=consider-using-enumerate for i in range(len(all_var)): v1 = all_var[i] _v1_name_lower = v1.name.lower() for j in range(i, len(all_var)): v2 = all_var[j] - if _v1_name_lower != v2.name.lower(): - if SimilarVarsDetection.similar(v1.name, v2.name): - if (v2, v1) not in ret: - ret.append((v1, v2)) + if len(v1.name) != len(v2.name): + continue + _v2_name_lower = v2.name.lower() + if _v1_name_lower != _v2_name_lower: + if SimilarVarsDetection.similar(_v1_name_lower, _v2_name_lower): + ret.add((v1, v2)) - return set(ret) + return ret def _detect(self) -> List[Output]: """Detect similar variables name From 314364eeb218d48c9fff6032dd2dd633fd4312f8 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 15 Jun 2023 14:13:25 -0700 Subject: [PATCH 071/338] chore: remove comments --- slither/printers/summary/ck.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index d896015b2..6f604790f 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -1,7 +1,4 @@ """ - - # TODO: Add in other CK metrics (NOC, DIT) - # TODO: Don't display all the general function metrics, but add those to complexity-dashboard CK Metrics are a suite of six software metrics proposed by Chidamber and Kemerer in 1994. These metrics are used to measure the complexity of a class. https://en.wikipedia.org/wiki/Programming_complexity From 975da91d333182b7a10d1be29993368073c1edb3 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 15 Jun 2023 14:20:18 -0700 Subject: [PATCH 072/338] chore: add type --- slither/printers/summary/martin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index 1bb59c4ff..b289a21f9 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -12,9 +12,9 @@ from slither.printers.abstract_printer import AbstractPrinter from slither.slithir.operations.high_level_call import HighLevelCall from slither.utils.myprettytable import make_pretty_table +from typing import Tuple - -def count_abstracts(contracts): +def count_abstracts(contracts) -> Tuple[int, int]: """ Count the number of abstract contracts Args: From 6f280c18b98c6ccee39f09a3f0b9381e0816ce5b Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 15 Jun 2023 14:36:19 -0700 Subject: [PATCH 073/338] chore: pylint --- slither/printers/summary/martin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index b289a21f9..693ec1575 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -9,10 +9,11 @@ Distance from the Main Sequence (D): abs(A + I - 1) """ -from slither.printers.abstract_printer import AbstractPrinter +from typing import Tuple from slither.slithir.operations.high_level_call import HighLevelCall from slither.utils.myprettytable import make_pretty_table -from typing import Tuple +from slither.printers.abstract_printer import AbstractPrinter + def count_abstracts(contracts) -> Tuple[int, int]: """ From 7cb7cb94ad00df6fe78775b656189643d896a993 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 15 Jun 2023 17:21:44 -0500 Subject: [PATCH 074/338] inform user if inheritance cannot be resolved (#1956) * inform user if inheritance cannot be resolved * lint * update explanation --- .../slither_compilation_unit_solc.py | 11 ++++++++++- .../contract_with_duplicate_names.sol | 2 ++ .../inheritance_resolution_error/import.sol | 1 + tests/unit/core/test_error_messages.py | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol create mode 100644 tests/unit/core/test_data/inheritance_resolution_error/import.sol create mode 100644 tests/unit/core/test_error_messages.py diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index f4258cd41..a739c6f97 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -33,6 +33,10 @@ logger = logging.getLogger("SlitherSolcParsing") logger.setLevel(logging.INFO) +class InheritanceResolutionError(SlitherException): + pass + + def _handle_import_aliases( symbol_aliases: Dict, import_directive: Import, scope: FileScope ) -> None: @@ -432,7 +436,12 @@ Please rename it, this name is reserved for Slither's internals""" target = contract_parser.underlying_contract.file_scope.get_contract_from_name( contract_name ) - assert target + if target == contract_parser.underlying_contract: + raise InheritanceResolutionError( + "Could not resolve contract inheritance. This is likely caused by an import renaming that collides with existing names (see https://github.com/crytic/slither/issues/1758)." + f"\n Try changing `contract {target}` ({target.source_mapping}) to a unique name." + ) + assert target, f"Contract {contract_name} not found" ancestors.append(target) elif i in self._contracts_by_id: ancestors.append(self._contracts_by_id[i]) diff --git a/tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol b/tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol new file mode 100644 index 000000000..d5c6816e2 --- /dev/null +++ b/tests/unit/core/test_data/inheritance_resolution_error/contract_with_duplicate_names.sol @@ -0,0 +1,2 @@ +import {ERC20 as ERC20_1} from "./import.sol"; +contract ERC20 is ERC20_1 {} \ No newline at end of file diff --git a/tests/unit/core/test_data/inheritance_resolution_error/import.sol b/tests/unit/core/test_data/inheritance_resolution_error/import.sol new file mode 100644 index 000000000..e3221165a --- /dev/null +++ b/tests/unit/core/test_data/inheritance_resolution_error/import.sol @@ -0,0 +1 @@ +contract ERC20 {} \ No newline at end of file diff --git a/tests/unit/core/test_error_messages.py b/tests/unit/core/test_error_messages.py new file mode 100644 index 000000000..d0d915d56 --- /dev/null +++ b/tests/unit/core/test_error_messages.py @@ -0,0 +1,18 @@ +from pathlib import Path +import pytest + + +from slither import Slither +from slither.solc_parsing.slither_compilation_unit_solc import InheritanceResolutionError + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" +INHERITANCE_ERROR_ROOT = Path(TEST_DATA_DIR, "inheritance_resolution_error") + + +def test_inheritance_resolution_error(solc_binary_path) -> None: + with pytest.raises(InheritanceResolutionError): + solc_path = solc_binary_path("0.8.0") + Slither( + Path(INHERITANCE_ERROR_ROOT, "contract_with_duplicate_names.sol").as_posix(), + solc=solc_path, + ) From ccad54263de5802c9893bd6eb151aa68d1a2cb95 Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Fri, 16 Jun 2023 00:21:59 +0200 Subject: [PATCH 075/338] Handle if crytic-compile returns an empty ast (#1961) --- slither/solc_parsing/slither_compilation_unit_solc.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index a739c6f97..00ac3a519 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -198,6 +198,13 @@ class SlitherCompilationUnitSolc(CallerContextExpression): # pylint: disable=too-many-branches,too-many-statements,too-many-locals def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) -> None: + if not data_loaded or data_loaded is None: + logger.error( + "crytic-compile returned an empty AST. " + "If you are trying to analyze a contract from etherscan or similar make sure it has source code available." + ) + return + if "nodeType" in data_loaded: self._is_compact_ast = True From 14c9761da2bb2c85ac08d12327ead1d4f77b2414 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 15 Jun 2023 15:26:29 -0700 Subject: [PATCH 076/338] feat: add CBO --- slither/printers/all_printers.py | 1 + slither/printers/summary/ck.py | 77 +++++++++++++++++++------------- slither/utils/myprettytable.py | 22 --------- 3 files changed, 46 insertions(+), 54 deletions(-) diff --git a/slither/printers/all_printers.py b/slither/printers/all_printers.py index 4e66351f8..7ac92327e 100644 --- a/slither/printers/all_printers.py +++ b/slither/printers/all_printers.py @@ -21,3 +21,4 @@ from .summary.evm import PrinterEVM from .summary.when_not_paused import PrinterWhenNotPaused from .summary.declaration import Declaration from .functions.dominator import Dominator +from .summary.martin import Martin diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index 6f604790f..77a8c420c 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -6,18 +6,19 @@ - Response For a Class (RFC) is a metric that measures the number of unique method calls within a class. - Number of Children (NOC) is a metric that measures the number of children a class has. - Depth of Inheritance Tree (DIT) is a metric that measures the number of parent classes a class has. + - Coupling Between Object Classes (CBO) is a metric that measures the number of classes a class is coupled to. Not implemented: - Lack of Cohesion of Methods (LCOM) is a metric that measures the lack of cohesion in methods. - Weighted Methods per Class (WMC) is a metric that measures the complexity of a class. - - Coupling Between Object Classes (CBO) is a metric that measures the number of classes a class is coupled to. """ from typing import Tuple -from slither.printers.abstract_printer import AbstractPrinter +from slither.utils.colors import bold from slither.utils.myprettytable import make_pretty_table from slither.slithir.operations.high_level_call import HighLevelCall -from slither.utils.colors import bold +from slither.printers.abstract_printer import AbstractPrinter +from slither.printers.summary.martin import compute_coupling def compute_dit(contract, depth=0): @@ -95,37 +96,41 @@ def compute_metrics(contracts): for inherited in contracts } - for c in contracts: - (state_variables, constants, immutables, public_getters) = count_variables(c) + # We pass 0 for the 2nd arg (abstractness) because we only care about the coupling metrics (Ca and Ce) + coupling = compute_coupling(contracts, 0) + + for contract in contracts: + (state_variables, constants, immutables, public_getters) = count_variables(contract) rfc = public_getters # add 1 for each public getter - metrics1[c.name] = { + metrics1[contract.name] = { "State variables": state_variables, "Constants": constants, "Immutables": immutables, } - metrics2[c.name] = { + metrics2[contract.name] = { "Public": 0, "External": 0, "Internal": 0, "Private": 0, } - metrics3[c.name] = { + metrics3[contract.name] = { "Mutating": 0, "View": 0, "Pure": 0, } - metrics4[c.name] = { + metrics4[contract.name] = { "External mutating": 0, "No auth or onlyOwner": 0, "No modifiers": 0, } - metrics5[c.name] = { + metrics5[contract.name] = { "Ext calls": 0, "RFC": 0, - "NOC": len(dependents[c.name]), - "DIT": compute_dit(c), + "NOC": len(dependents[contract.name]), + "DIT": compute_dit(contract), + "CBO": coupling[contract.name]["Dependents"] + coupling[contract.name]["Dependencies"], } - for func in c.functions: + for func in contract.functions: if func.name == "constructor": continue pure = func.pure @@ -147,29 +152,33 @@ def compute_metrics(contracts): # convert irs to string with target function and contract name external_calls = [] - for h in high_level_calls: - if hasattr(h.destination, "name"): - external_calls.append(f"{h.function_name}{h.destination.name}") + for high_level_call in high_level_calls: + if hasattr(high_level_call.destination, "name"): + external_calls.append( + f"{high_level_call.function_name}{high_level_call.destination.name}" + ) else: - external_calls.append(f"{h.function_name}{h.destination.type.type.name}") + external_calls.append( + f"{high_level_call.function_name}{high_level_call.destination.type.type.name}" + ) rfc += len(set(external_calls)) - metrics2[c.name]["Public"] += 1 if public else 0 - metrics2[c.name]["External"] += 1 if external else 0 - metrics2[c.name]["Internal"] += 1 if internal else 0 - metrics2[c.name]["Private"] += 1 if private else 0 + metrics2[contract.name]["Public"] += 1 if public else 0 + metrics2[contract.name]["External"] += 1 if external else 0 + metrics2[contract.name]["Internal"] += 1 if internal else 0 + metrics2[contract.name]["Private"] += 1 if private else 0 - metrics3[c.name]["Mutating"] += 1 if mutating else 0 - metrics3[c.name]["View"] += 1 if view else 0 - metrics3[c.name]["Pure"] += 1 if pure else 0 + metrics3[contract.name]["Mutating"] += 1 if mutating else 0 + metrics3[contract.name]["View"] += 1 if view else 0 + metrics3[contract.name]["Pure"] += 1 if pure else 0 - metrics4[c.name]["External mutating"] += 1 if external_public_mutating else 0 - metrics4[c.name]["No auth or onlyOwner"] += 1 if external_no_auth else 0 - metrics4[c.name]["No modifiers"] += 1 if external_no_modifiers else 0 + metrics4[contract.name]["External mutating"] += 1 if external_public_mutating else 0 + metrics4[contract.name]["No auth or onlyOwner"] += 1 if external_no_auth else 0 + metrics4[contract.name]["No modifiers"] += 1 if external_no_modifiers else 0 - metrics5[c.name]["Ext calls"] += len(external_calls) - metrics5[c.name]["RFC"] = rfc + metrics5[contract.name]["Ext calls"] += len(external_calls) + metrics5[contract.name]["RFC"] = rfc return metrics1, metrics2, metrics3, metrics4, metrics5 @@ -213,7 +222,7 @@ def no_auth(func) -> bool: class CKMetrics(AbstractPrinter): ARGUMENT = "ck" - HELP = "Computes the CK complexity metrics for each contract" + HELP = "Chidamber and Kemerer (CK) complexity metrics and related function attributes" WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#ck" @@ -246,8 +255,12 @@ class CKMetrics(AbstractPrinter): table3 = make_pretty_table(["Contract", *keys], metrics4, True) txt += str(table3) + "\n" - # metrics5: ext calls and rfc - txt += bold("\nExt calls and RFC\n") + # metrics5: ext calls and ck metrics + txt += bold("\nExternal calls and CK Metrics:\n") + txt += bold("Response For a Class (RFC)\n") + txt += bold("Number of Children (NOC)\n") + txt += bold("Depth of Inheritance Tree (DIT)\n") + txt += bold("Coupling Between Object Classes (CBO)\n") keys = list(metrics5[self.contracts[0].name].keys()) table4 = make_pretty_table(["Contract", *keys], metrics5, False) txt += str(table4) + "\n" diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index 6edb67def..8c5d1af33 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -78,25 +78,3 @@ def make_pretty_table_simple( for k, v in data.items(): table.add_row([k] + [v]) return table - - -# takes a dict of dicts and returns a dict of dicts with the keys transposed -# example: -# in: -# { -# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, -# "test": {"loc": 0, "sloc": 0, "cloc": 0}, -# "src": {"loc": 0, "sloc": 0, "cloc": 0}, -# } -# out: -# { -# 'loc': {'dep': 0, 'test': 0, 'src': 0}, -# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, -# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, -# } -def transpose(table): - any_key = list(table.keys())[0] - return { - inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} - for inner_key in table[any_key] - } From fa22c3460eab1f0e25f77d3767e1ddc193b0df31 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 15 Jun 2023 15:57:21 -0700 Subject: [PATCH 077/338] chore: update label --- slither/printers/summary/ck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index 77a8c420c..a9f80b354 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -244,7 +244,7 @@ class CKMetrics(AbstractPrinter): txt += str(table1) + "\n" # metrics4: function mutability counts - txt += bold("\nFunction mutatability\n") + txt += bold("\nState mutability\n") keys = list(metrics3[self.contracts[0].name].keys()) table2 = make_pretty_table(["Contract", *keys], metrics3, True) txt += str(table2) + "\n" From 3791467fb9a9460b4af6aa2b8324726511ba2ce2 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 16 Jun 2023 11:04:36 -0700 Subject: [PATCH 078/338] docs: fix docstring --- slither/utils/myprettytable.py | 44 ++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index 57e130884..dd3672f84 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -32,6 +32,14 @@ class MyPrettyTable: # @param body dict of row headers with a dict of the values # @param totals bool optional add Totals row def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: + """ + Converts a dict to a MyPrettyTable. Dict keys are the row headers. + Args: + data: dict of row headers with a dict of the values + column_header: str of column name for 1st column + Returns: + MyPrettyTable + """ table = MyPrettyTable(headers) for row in body: table_row = [row] + [body[row][key] for key in headers[1:]] @@ -40,22 +48,28 @@ def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPret table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) return table - -# takes a dict of dicts and returns a dict of dicts with the keys transposed -# example: -# in: -# { -# "dep": {"loc": 0, "sloc": 0, "cloc": 0}, -# "test": {"loc": 0, "sloc": 0, "cloc": 0}, -# "src": {"loc": 0, "sloc": 0, "cloc": 0}, -# } -# out: -# { -# 'loc': {'dep': 0, 'test': 0, 'src': 0}, -# 'sloc': {'dep': 0, 'test': 0, 'src': 0}, -# 'cloc': {'dep': 0, 'test': 0, 'src': 0}, -# } def transpose(table): + """ + Converts a dict of dicts to a dict of dicts with the keys transposed + Args: + table: dict of dicts + Returns: + dict of dicts + + Example: + in: + { + "dep": {"loc": 0, "sloc": 0, "cloc": 0}, + "test": {"loc": 0, "sloc": 0, "cloc": 0}, + "src": {"loc": 0, "sloc": 0, "cloc": 0}, + } + out: + { + 'loc': {'dep': 0, 'test': 0, 'src': 0}, + 'sloc': {'dep': 0, 'test': 0, 'src': 0}, + 'cloc': {'dep': 0, 'test': 0, 'src': 0}, + } + """ any_key = list(table.keys())[0] return { inner_key: {outer_key: table[outer_key][inner_key] for outer_key in table} From c3a674acdc874cd97aeb20fcd464b34ccf873626 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 16 Jun 2023 11:13:47 -0700 Subject: [PATCH 079/338] chore: black --- slither/utils/myprettytable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index dd3672f84..fec84ef0b 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -48,6 +48,7 @@ def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPret table.add_row(["Total"] + [sum([body[row][key] for row in body]) for key in headers[1:]]) return table + def transpose(table): """ Converts a dict of dicts to a dict of dicts with the keys transposed From 473576994024940ded6d895290c7e881f19efa6a Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Tue, 20 Jun 2023 11:48:45 +0400 Subject: [PATCH 080/338] Fixed issue which disallowed using operator[] with TopLevelVariables --- slither/slithir/operations/index.py | 7 +++++-- slither/slithir/variables/reference.py | 3 ++- .../local_variable_init_from_tuple.py | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/slither/slithir/operations/index.py b/slither/slithir/operations/index.py index f38a25927..4fcfb8a6d 100644 --- a/slither/slithir/operations/index.py +++ b/slither/slithir/operations/index.py @@ -3,6 +3,7 @@ from typing import List, Union from slither.core.declarations import SolidityVariableComposed from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables.variable import Variable +from slither.core.variables.top_level_variable import TopLevelVariable from slither.slithir.operations.lvalue import OperationWithLValue from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue, RVALUE, LVALUE from slither.slithir.variables.reference import ReferenceVariable @@ -13,8 +14,10 @@ class Index(OperationWithLValue): self, result: ReferenceVariable, left_variable: Variable, right_variable: RVALUE ) -> None: super().__init__() - assert is_valid_lvalue(left_variable) or left_variable == SolidityVariableComposed( - "msg.data" + assert ( + is_valid_lvalue(left_variable) + or left_variable == SolidityVariableComposed("msg.data") + or isinstance(left_variable, TopLevelVariable) ) assert is_valid_rvalue(right_variable) assert isinstance(result, ReferenceVariable) diff --git a/slither/slithir/variables/reference.py b/slither/slithir/variables/reference.py index 9ab51be65..2f99d322e 100644 --- a/slither/slithir/variables/reference.py +++ b/slither/slithir/variables/reference.py @@ -2,6 +2,7 @@ from typing import Optional, TYPE_CHECKING from slither.core.declarations import Contract, Enum, SolidityVariable, Function from slither.core.variables.variable import Variable +from slither.core.variables.top_level_variable import TopLevelVariable if TYPE_CHECKING: from slither.core.cfg.node import Node @@ -46,7 +47,7 @@ class ReferenceVariable(Variable): from slither.slithir.utils.utils import is_valid_lvalue assert is_valid_lvalue(points_to) or isinstance( - points_to, (SolidityVariable, Contract, Enum) + points_to, (SolidityVariable, Contract, Enum, TopLevelVariable) ) self._points_to = points_to diff --git a/slither/solc_parsing/variables/local_variable_init_from_tuple.py b/slither/solc_parsing/variables/local_variable_init_from_tuple.py index 1a551c695..f1c872848 100644 --- a/slither/solc_parsing/variables/local_variable_init_from_tuple.py +++ b/slither/solc_parsing/variables/local_variable_init_from_tuple.py @@ -16,3 +16,21 @@ class LocalVariableInitFromTupleSolc(VariableDeclarationSolc): # Todo: Not sure how to overcome this with mypy assert isinstance(self._variable, LocalVariableInitFromTuple) return self._variable + + def _analyze_variable_attributes(self, attributes: Dict) -> None: + """' + Variable Location + Can be storage/memory or default + """ + if "storageLocation" in attributes: + location = attributes["storageLocation"] + self.underlying_variable.set_location(location) + else: + if "memory" in attributes["type"]: + self.underlying_variable.set_location("memory") + elif "storage" in attributes["type"]: + self.underlying_variable.set_location("storage") + else: + self.underlying_variable.set_location("default") + + super()._analyze_variable_attributes(attributes) From 8a5aab62c9a0a4b9dde91eb9d0ffd847b8987bdb Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 11:03:42 -0500 Subject: [PATCH 081/338] reduce false positives on modifying storage array by value detector (#1962) Check the respective parameter's storage location for each argument --------- Co-authored-by: bossjoker1 <1397157763@qq.com> --- .../compiler_bugs/array_by_reference.py | 13 ++++++----- ...rence_0_4_25_array_by_reference_sol__0.txt | 14 +++++++----- ...rence_0_5_16_array_by_reference_sol__0.txt | 14 +++++++----- ...rence_0_6_11_array_by_reference_sol__0.txt | 14 +++++++----- ...erence_0_7_6_array_by_reference_sol__0.txt | 14 +++++++----- .../0.4.25/array_by_reference.sol | 21 ++++++++++++++++++ .../0.4.25/array_by_reference.sol-0.4.25.zip | Bin 4879 -> 6184 bytes .../0.5.16/array_by_reference.sol | 21 ++++++++++++++++++ .../0.5.16/array_by_reference.sol-0.5.16.zip | Bin 4925 -> 6194 bytes .../0.6.11/array_by_reference.sol | 21 ++++++++++++++++++ .../0.6.11/array_by_reference.sol-0.6.11.zip | Bin 4841 -> 6086 bytes .../0.7.6/array_by_reference.sol | 21 ++++++++++++++++++ .../0.7.6/array_by_reference.sol-0.7.6.zip | Bin 4741 -> 5972 bytes 13 files changed, 124 insertions(+), 29 deletions(-) diff --git a/slither/detectors/compiler_bugs/array_by_reference.py b/slither/detectors/compiler_bugs/array_by_reference.py index 04dfe085a..47e2af581 100644 --- a/slither/detectors/compiler_bugs/array_by_reference.py +++ b/slither/detectors/compiler_bugs/array_by_reference.py @@ -133,7 +133,7 @@ As a result, Bob's usage of the contract is incorrect.""" continue # Verify one of these parameters is an array in storage. - for arg in ir.arguments: + for (param, arg) in zip(ir.function.parameters, ir.arguments): # Verify this argument is a variable that is an array type. if not isinstance(arg, (StateVariable, LocalVariable)): continue @@ -141,8 +141,11 @@ As a result, Bob's usage of the contract is incorrect.""" continue # If it is a state variable OR a local variable referencing storage, we add it to the list. - if isinstance(arg, StateVariable) or ( - isinstance(arg, LocalVariable) and arg.location == "storage" + if ( + isinstance(arg, StateVariable) + or (isinstance(arg, LocalVariable) and arg.location == "storage") + ) and ( + isinstance(param.type, ArrayType) and param.location != "storage" ): results.append((node, arg, ir.function)) return results @@ -165,9 +168,9 @@ As a result, Bob's usage of the contract is incorrect.""" calling_node.function, " passes array ", affected_argument, - "by reference to ", + " by reference to ", invoked_function, - "which only takes arrays by value\n", + " which only takes arrays by value\n", ] res = self.generate_result(info) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt index f056bea10..5cb8add39 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt index 4264c809a..6e97d8cc2 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt index e71930b51..39574b5f5 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt index 7c0f9ccd9..74ea36a0c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol index 304af6a48..c2707601a 100644 --- a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol +++ b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol @@ -48,4 +48,25 @@ contract D { } +} + +contract E { + uint[1] public x; // storage + uint[1] public y; // storage + + function f() public { + uint[1] memory temp; + setByValue(temp, x); // can set temp, but cannot set x + setByRef(temp, y); // can set temp and y + } + + function setByValue(uint[1] memory arr, uint[1] memory arr2) internal { + arr[0] = 1; + arr2[0] = 2; + } + + function setByRef(uint[1] memory arr, uint[1] storage arr2) internal { + arr[0] = 2; + arr2[0] = 3; + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol-0.4.25.zip b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol-0.4.25.zip index d9daf8f4d7dc27c4f371b018a31cc9736180c278..96bdaa0f85c484feec1e0f47ea8e3409f0cd1dc9 100644 GIT binary patch delta 5938 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 G0001;R*ZlE From cec07db510e6064dea17a349839880d98adc4121 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 11:12:06 -0500 Subject: [PATCH 082/338] feat: add `--unstructured` to slither-read-storage; retrieve custom storage layouts (#1963) Retrieve storage values of constant arguments passed to SLOAD. If a call to keccack is made, the expression is evaluated and treated as a constant. --------- Co-authored-by: webthethird --- slither/printers/guidance/echidna.py | 17 +- .../expressions/expression_parsing.py | 2 + slither/tools/read_storage/__main__.py | 7 + slither/tools/read_storage/read_storage.py | 315 ++++++++++++++++-- slither/tools/read_storage/utils/utils.py | 2 + slither/utils/integer_conversion.py | 4 +- .../visitors/expression/constants_folding.py | 71 ++-- tests/conftest.py | 6 +- .../tools/{check-erc => check_erc}/erc20.sol | 0 .../tools/{check-erc => check_erc}/test_1.txt | 0 .../safeAdd/safeAdd.sol | 0 .../safeAdd/spec.md | 0 .../{check-kspec => check_kspec}/test_1.txt | 0 .../contractV1.sol | 0 .../contractV1_struct.sol | 0 .../contractV2.sol | 0 .../contractV2_bug.sol | 0 .../contractV2_bug2.sol | 0 .../contractV2_struct.sol | 0 .../contractV2_struct_bug.sol | 0 .../contract_initialization.sol | 0 .../contract_v1_var_init.sol | 0 .../contract_v2_constant.sol | 0 .../proxy.sol | 0 .../test_1.txt | 0 .../test_10.txt | 0 .../test_11.txt | 0 .../test_12.txt | 0 .../test_13.txt | 0 .../test_2.txt | 0 .../test_3.txt | 0 .../test_4.txt | 0 .../test_5.txt | 0 .../test_6.txt | 0 .../test_7.txt | 0 .../test_8.txt | 0 .../test_9.txt | 0 tests/tools/read-storage/conftest.py | 56 ++++ ...ge_layout-0.8.10.sol => StorageLayout.sol} | 3 +- .../test_data/TEST_unstructured_storage.json | 56 ++++ .../test_data/UnstructuredStorageLayout.abi | 1 + .../test_data/UnstructuredStorageLayout.bin | 1 + .../test_data/UnstructuredStorageLayout.sol | 141 ++++++++ tests/tools/read-storage/test_read_storage.py | 66 +--- tests/unit/core/test_constant_folding.py | 59 ++-- .../constant_folding_binop.sol | 2 + 46 files changed, 680 insertions(+), 129 deletions(-) rename tests/tools/{check-erc => check_erc}/erc20.sol (100%) rename tests/tools/{check-erc => check_erc}/test_1.txt (100%) rename tests/tools/{check-kspec => check_kspec}/safeAdd/safeAdd.sol (100%) rename tests/tools/{check-kspec => check_kspec}/safeAdd/spec.md (100%) rename tests/tools/{check-kspec => check_kspec}/test_1.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV1.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV1_struct.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV2.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV2_bug.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV2_bug2.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV2_struct.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contractV2_struct_bug.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contract_initialization.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contract_v1_var_init.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/contract_v2_constant.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/proxy.sol (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_1.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_10.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_11.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_12.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_13.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_2.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_3.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_4.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_5.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_6.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_7.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_8.txt (100%) rename tests/tools/{check-upgradeability => check_upgradeability}/test_9.txt (100%) create mode 100644 tests/tools/read-storage/conftest.py rename tests/tools/read-storage/test_data/{storage_layout-0.8.10.sol => StorageLayout.sol} (95%) create mode 100644 tests/tools/read-storage/test_data/TEST_unstructured_storage.json create mode 100644 tests/tools/read-storage/test_data/UnstructuredStorageLayout.abi create mode 100644 tests/tools/read-storage/test_data/UnstructuredStorageLayout.bin create mode 100644 tests/tools/read-storage/test_data/UnstructuredStorageLayout.sol diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index acbf5b015..25e0968cd 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -32,7 +32,7 @@ from slither.slithir.operations import ( from slither.slithir.operations.binary import Binary from slither.slithir.variables import Constant from slither.utils.output import Output -from slither.visitors.expression.constants_folding import ConstantFolding +from slither.visitors.expression.constants_folding import ConstantFolding, NotConstant def _get_name(f: Union[Function, Variable]) -> str: @@ -178,11 +178,16 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n all_cst_used_in_binary[str(ir.type)].append( ConstantValue(str(r.value), str(r.type)) ) - if isinstance(ir.variable_left, Constant) and isinstance(ir.variable_right, Constant): - if ir.lvalue: - type_ = ir.lvalue.type - cst = ConstantFolding(ir.expression, type_).result() - all_cst_used.append(ConstantValue(str(cst.value), str(type_))) + if isinstance(ir.variable_left, Constant) or isinstance( + ir.variable_right, Constant + ): + if ir.lvalue: + try: + type_ = ir.lvalue.type + cst = ConstantFolding(ir.expression, type_).result() + all_cst_used.append(ConstantValue(str(cst.value), str(type_))) + except NotConstant: + pass if isinstance(ir, TypeConversion): if isinstance(ir.variable, Constant): if isinstance(ir.type, TypeAlias): diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index 945a60b8f..4d2cfc00f 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -433,6 +433,8 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression) type_candidate = ElementaryType("uint256") else: type_candidate = ElementaryType("string") + elif type_candidate.startswith("rational_const "): + type_candidate = ElementaryType("uint256") elif type_candidate.startswith("int_const "): type_candidate = ElementaryType("uint256") elif type_candidate.startswith("bool"): diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index f6635ab4b..8415ae185 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -104,6 +104,12 @@ def parse_args() -> argparse.Namespace: default="latest", ) + parser.add_argument( + "--unstructured", + action="store_true", + help="Include unstructured storage slots", + ) + cryticparser.init(parser) return parser.parse_args() @@ -133,6 +139,7 @@ def main() -> None: rpc_info = RpcInfo(args.rpc_url, block) srs = SlitherReadStorage(contracts, args.max_depth, rpc_info) + srs.unstructured = bool(args.unstructured) # Remove target prefix e.g. rinkeby:0x0 -> 0x0. address = target[target.find(":") + 1 :] # Default to implementation address unless a storage address is given. diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index 72331f66a..8c0cf515d 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -15,9 +15,21 @@ from web3.middleware import geth_poa_middleware 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.cfg.node import NodeType from slither.core.variables.state_variable import StateVariable from slither.core.variables.structure_variable import StructureVariable +from slither.core.expressions import ( + AssignmentOperation, + Literal, + Identifier, + BinaryOperation, + UnaryOperation, + TupleExpression, + TypeConversion, + CallExpression, +) from slither.utils.myprettytable import MyPrettyTable +from slither.visitors.expression.constants_folding import ConstantFolding, NotConstant from .utils import coerce_type, get_offset_value, get_storage_data @@ -72,7 +84,7 @@ class RpcInfo: return self._block -# pylint: disable=too-many-instance-attributes +# pylint: disable=too-many-instance-attributes,too-many-public-methods class SlitherReadStorage: def __init__(self, contracts: List[Contract], max_depth: int, rpc_info: RpcInfo = None) -> None: self._checksum_address: Optional[ChecksumAddress] = None @@ -81,9 +93,11 @@ class SlitherReadStorage: self._max_depth: int = max_depth self._slot_info: Dict[str, SlotInfo] = {} self._target_variables: List[Tuple[Contract, StateVariable]] = [] + self._constant_storage_slots: List[Tuple[Contract, StateVariable]] = [] self.rpc_info: Optional[RpcInfo] = rpc_info self.storage_address: Optional[str] = None self.table: Optional[MyPrettyTable] = None + self.unstructured: bool = False @property def contracts(self) -> List[Contract]: @@ -114,6 +128,11 @@ class SlitherReadStorage: """Storage variables (not constant or immutable) and their associated contract.""" return self._target_variables + @property + def constant_slots(self) -> List[Tuple[Contract, StateVariable]]: + """Constant bytes32 variables and their associated contract.""" + return self._constant_storage_slots + @property def slot_info(self) -> Dict[str, SlotInfo]: """Contains the location, type, size, offset, and value of contract slots.""" @@ -133,9 +152,48 @@ class SlitherReadStorage: elif isinstance(type_, ArrayType): elems = self._all_array_slots(var, contract, type_, info.slot) tmp[var.name].elems = elems - + if self.unstructured: + tmp.update(self.get_unstructured_layout()) self._slot_info = tmp + def get_unstructured_layout(self) -> Dict[str, SlotInfo]: + tmp: Dict[str, SlotInfo] = {} + for _, var in self.constant_slots: + var_name = var.name + try: + exp = var.expression + if isinstance( + exp, + ( + BinaryOperation, + UnaryOperation, + Identifier, + TupleExpression, + TypeConversion, + CallExpression, + ), + ): + exp = ConstantFolding(exp, "bytes32").result() + if isinstance(exp, Literal): + slot = coerce_type("int", exp.value) + else: + continue + offset = 0 + type_string, size = self.find_constant_slot_storage_type(var) + if type_string: + tmp[var.name] = SlotInfo( + name=var_name, type_string=type_string, slot=slot, size=size, offset=offset + ) + self.log += ( + f"\nSlot Name: {var_name}\nType: bytes32" + f"\nStorage Type: {type_string}\nSlot: {str(exp)}\n" + ) + logger.info(self.log) + self.log = "" + except NotConstant: + continue + return tmp + # TODO: remove this pylint exception (montyly) # pylint: disable=too-many-locals def get_storage_slot( @@ -144,7 +202,8 @@ class SlitherReadStorage: contract: Contract, **kwargs: Any, ) -> Union[SlotInfo, None]: - """Finds the storage slot of a variable in a given contract. + """ + Finds the storage slot of a variable in a given contract. Args: target_variable (`StateVariable`): The variable to retrieve the slot for. contracts (`Contract`): The contract that contains the given state variable. @@ -230,6 +289,78 @@ class SlitherReadStorage: if slot_info: self._slot_info[f"{contract.name}.{var.name}"] = slot_info + def find_constant_slot_storage_type( + self, var: StateVariable + ) -> Tuple[Optional[str], Optional[int]]: + """ + Given a constant bytes32 StateVariable, tries to determine which variable type is stored there, using the + heuristic that if a function reads from the slot and returns a value, it probably stores that type of value. + Also uses the StorageSlot library as a heuristic when a function has no return but uses the library's getters. + Args: + var (StateVariable): The constant bytes32 storage slot. + + Returns: + type (str): The type of value stored in the slot. + size (int): The type's size in bits. + """ + assert var.is_constant and var.type == ElementaryType("bytes32") + storage_type = None + size = None + funcs = [] + for c in self.contracts: + c_funcs = c.get_functions_reading_from_variable(var) + c_funcs.extend( + f + for f in c.functions + if any(str(v.expression) == str(var.expression) for v in f.variables) + ) + c_funcs = list(set(c_funcs)) + funcs.extend(c_funcs) + fallback = [f for f in var.contract.functions if f.is_fallback] + funcs += fallback + for func in funcs: + rets = func.return_type if func.return_type is not None else [] + for ret in rets: + size, _ = ret.storage_size + if size <= 32: + return str(ret), size * 8 + for node in func.all_nodes(): + exp = node.expression + # Look for use of the common OpenZeppelin StorageSlot library + if f"getAddressSlot({var.name})" in str(exp): + return "address", 160 + if f"getBooleanSlot({var.name})" in str(exp): + return "bool", 1 + if f"getBytes32Slot({var.name})" in str(exp): + return "bytes32", 256 + if f"getUint256Slot({var.name})" in str(exp): + return "uint256", 256 + # Look for variable assignment in assembly loaded from a hardcoded slot + if ( + isinstance(exp, AssignmentOperation) + and isinstance(exp.expression_left, Identifier) + and isinstance(exp.expression_right, CallExpression) + and "sload" in str(exp.expression_right.called) + and str(exp.expression_right.arguments[0]) == str(var.expression) + ): + if func.is_fallback: + return "address", 160 + storage_type = exp.expression_left.value.type.name + size, _ = exp.expression_left.value.type.storage_size + return storage_type, size * 8 + # Look for variable storage in assembly stored to a hardcoded slot + if ( + isinstance(exp, CallExpression) + and "sstore" in str(exp.called) + and isinstance(exp.arguments[0], Identifier) + and isinstance(exp.arguments[1], Identifier) + and str(exp.arguments[0].value.expression) == str(var.expression) + ): + storage_type = exp.arguments[1].value.type.name + size, _ = exp.arguments[1].value.type.storage_size + return storage_type, size * 8 + return storage_type, size + def walk_slot_info(self, func: Callable) -> None: stack = list(self.slot_info.values()) while stack: @@ -242,7 +373,8 @@ class SlitherReadStorage: func(slot_info) def get_slot_values(self, slot_info: SlotInfo) -> None: - """Fetches the slot value of `SlotInfo` object + """ + Fetches the slot value of `SlotInfo` object :param slot_info: """ assert self.rpc_info is not None @@ -257,25 +389,162 @@ class SlitherReadStorage: ) logger.info(f"\nValue: {slot_info.value}\n") - def get_all_storage_variables(self, func: Callable = None) -> None: - """Fetches all storage variables from a list of contracts. + def get_all_storage_variables(self, func: Callable = lambda x: x) -> None: + """ + Fetches all storage variables from a list of contracts. kwargs: func (Callable, optional): A criteria to filter functions e.g. name. """ for contract in self.contracts: - self._target_variables.extend( - filter( - func, - [ - (contract, var) - for var in contract.state_variables_ordered - if not var.is_constant and not var.is_immutable - ], - ) + for var in contract.state_variables_ordered: + if func(var): + if not var.is_constant and not var.is_immutable: + self._target_variables.append((contract, var)) + elif ( + self.unstructured + and var.is_constant + and var.type == ElementaryType("bytes32") + ): + self._constant_storage_slots.append((contract, var)) + if self.unstructured: + hardcoded_slot = self.find_hardcoded_slot_in_fallback(contract) + if hardcoded_slot is not None: + self._constant_storage_slots.append((contract, hardcoded_slot)) + + def find_hardcoded_slot_in_fallback(self, contract: Contract) -> Optional[StateVariable]: + """ + Searches the contract's fallback function for a sload from a literal storage slot, i.e., + `let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)`. + + Args: + contract: a Contract object, which should have a fallback function. + + Returns: + A newly created StateVariable representing the Literal bytes32 slot, if one is found, otherwise None. + """ + fallback = None + for func in contract.functions_entry_points: + if func.is_fallback: + fallback = func + break + if fallback is None: + return None + queue = [fallback.entry_point] + visited = [] + while len(queue) > 0: + node = queue.pop(0) + visited.append(node) + queue.extend(son for son in node.sons if son not in visited) + if node.type == NodeType.ASSEMBLY and isinstance(node.inline_asm, str): + return SlitherReadStorage.find_hardcoded_slot_in_asm_str(node.inline_asm, contract) + if node.type == NodeType.EXPRESSION: + sv = self.find_hardcoded_slot_in_exp(node.expression, contract) + if sv is not None: + return sv + return None + + @staticmethod + def find_hardcoded_slot_in_asm_str( + inline_asm: str, contract: Contract + ) -> Optional[StateVariable]: + """ + Searches a block of assembly code (given as a string) for a sload from a literal storage slot. + Does not work if the argument passed to sload does not start with "0x", i.e., `sload(add(1,1))` + or `and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)`. + + Args: + inline_asm: a string containing all the code in an assembly node (node.inline_asm for solc < 0.6.0). + + Returns: + A newly created StateVariable representing the Literal bytes32 slot, if one is found, otherwise None. + """ + asm_split = inline_asm.split("\n") + for asm in asm_split: + if "sload(" in asm: # Only handle literals + arg = asm.split("sload(")[1].split(")")[0] + if arg.startswith("0x"): + exp = Literal(arg, ElementaryType("bytes32")) + sv = StateVariable() + sv.name = "fallback_sload_hardcoded" + sv.expression = exp + sv.is_constant = True + sv.type = exp.type + sv.set_contract(contract) + return sv + return None + + def find_hardcoded_slot_in_exp( + self, exp: "Expression", contract: Contract + ) -> Optional[StateVariable]: + """ + Parses an expression to see if it contains a sload from a literal storage slot, + unrolling nested expressions if necessary to determine which slot it loads from. + Args: + exp: an Expression object to search. + contract: the Contract containing exp. + + Returns: + A newly created StateVariable representing the Literal bytes32 slot, if one is found, otherwise None. + """ + if isinstance(exp, AssignmentOperation): + exp = exp.expression_right + while isinstance(exp, BinaryOperation): + exp = next( + (e for e in exp.expressions if isinstance(e, (CallExpression, BinaryOperation))), + exp.expression_left, ) + while isinstance(exp, CallExpression) and len(exp.arguments) > 0: + called = exp.called + exp = exp.arguments[0] + if "sload" in str(called): + break + if isinstance( + exp, + ( + BinaryOperation, + UnaryOperation, + Identifier, + TupleExpression, + TypeConversion, + CallExpression, + ), + ): + try: + exp = ConstantFolding(exp, "bytes32").result() + except NotConstant: + return None + if ( + isinstance(exp, Literal) + and isinstance(exp.type, ElementaryType) + and exp.type.name in ["bytes32", "uint256"] + ): + sv = StateVariable() + sv.name = "fallback_sload_hardcoded" + value = exp.value + str_value = str(value) + if str_value.isdecimal(): + value = int(value) + if isinstance(value, (int, bytes)): + if isinstance(value, bytes): + str_value = "0x" + value.hex() + value = int(str_value, 16) + exp = Literal(str_value, ElementaryType("bytes32")) + state_var_slots = [ + self.get_variable_info(contract, var)[0] + for contract, var in self.target_variables + ] + if value in state_var_slots: + return None + sv.expression = exp + sv.is_constant = True + sv.type = ElementaryType("bytes32") + sv.set_contract(contract) + return sv + return None def convert_slot_info_to_rows(self, slot_info: SlotInfo) -> None: - """Convert and append slot info to table. Create table if it + """ + Convert and append slot info to table. Create table if it does not yet exist :param slot_info: """ @@ -293,7 +562,8 @@ class SlitherReadStorage: def _find_struct_var_slot( elems: List[StructureVariable], slot_as_bytes: bytes, struct_var: str ) -> Tuple[str, str, bytes, int, int]: - """Finds the slot of a structure variable. + """ + Finds the slot of a structure variable. Args: elems (List[StructureVariable]): Ordered list of structure variables. slot_as_bytes (bytes): The slot of the struct to begin searching at. @@ -335,7 +605,8 @@ class SlitherReadStorage: deep_key: int = None, struct_var: str = None, ) -> Tuple[str, str, bytes, int, int]: - """Finds the slot of array's index. + """ + Finds the slot of array's index. Args: target_variable (`StateVariable`): The array that contains the target variable. slot (bytes): The starting slot of the array. @@ -438,7 +709,8 @@ class SlitherReadStorage: deep_key: Union[int, str] = None, struct_var: str = None, ) -> Tuple[str, str, bytes, int, int]: - """Finds the data slot of a target variable within a mapping. + """ + Finds the data slot of a target variable within a mapping. target_variable (`StateVariable`): The mapping that contains the target variable. slot (bytes): The starting slot of the mapping. key (Union[int, str]): The key the variable is stored at. @@ -509,7 +781,7 @@ class SlitherReadStorage: ) info += info_tmp - # TODO: suppory mapping with dynamic arrays + # TODO: support mapping with dynamic arrays # mapping(elem => elem) elif isinstance(target_variable_type.type_to, ElementaryType): @@ -615,7 +887,8 @@ class SlitherReadStorage: return elems def _get_array_length(self, type_: Type, slot: int) -> int: - """Gets the length of dynamic and fixed arrays. + """ + Gets the length of dynamic and fixed arrays. Args: type_ (`AbstractType`): The array type. slot (int): Slot a dynamic array's length is stored at. diff --git a/slither/tools/read_storage/utils/utils.py b/slither/tools/read_storage/utils/utils.py index 4a04a5b6d..20e7c1372 100644 --- a/slither/tools/read_storage/utils/utils.py +++ b/slither/tools/read_storage/utils/utils.py @@ -37,6 +37,8 @@ def coerce_type( (Union[int, bool, str, ChecksumAddress, hex]): The type representation of the value. """ if "int" in solidity_type: + if str(value).startswith("0x"): + return to_int(hexstr=value) return to_int(value) if "bool" in solidity_type: return bool(to_int(value)) diff --git a/slither/utils/integer_conversion.py b/slither/utils/integer_conversion.py index e4dff333c..99064f564 100644 --- a/slither/utils/integer_conversion.py +++ b/slither/utils/integer_conversion.py @@ -4,7 +4,9 @@ from typing import Union from slither.exceptions import SlitherError -def convert_string_to_fraction(val: Union[str, int]) -> Fraction: +def convert_string_to_fraction(val: Union[str, bytes, int]) -> Fraction: + if isinstance(val, bytes): + return int.from_bytes(val, byteorder="big") if isinstance(val, int): return Fraction(val) if val.startswith(("0x", "0X")): diff --git a/slither/visitors/expression/constants_folding.py b/slither/visitors/expression/constants_folding.py index 12eb6be9d..b1fa570c6 100644 --- a/slither/visitors/expression/constants_folding.py +++ b/slither/visitors/expression/constants_folding.py @@ -1,5 +1,6 @@ from fractions import Fraction from typing import Union +from Crypto.Hash import keccak from slither.core import expressions from slither.core.expressions import ( @@ -11,9 +12,9 @@ from slither.core.expressions import ( UnaryOperation, TupleExpression, TypeConversion, + CallExpression, ) from slither.core.variables import Variable - from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int from slither.visitors.expression.expression import ExpressionVisitor from slither.core.solidity_types.elementary_type import ElementaryType @@ -65,23 +66,31 @@ class ConstantFolding(ExpressionVisitor): value = value & (2**256 - 1) return Literal(value, self._type) + # pylint: disable=import-outside-toplevel def _post_identifier(self, expression: Identifier) -> None: - if not isinstance(expression.value, Variable): - return - if not expression.value.is_constant: + from slither.core.declarations.solidity_variables import SolidityFunction + + if isinstance(expression.value, Variable): + if expression.value.is_constant: + expr = expression.value.expression + # assumption that we won't have infinite loop + # Everything outside of literal + if isinstance( + expr, + (BinaryOperation, UnaryOperation, Identifier, TupleExpression, TypeConversion), + ): + cf = ConstantFolding(expr, self._type) + expr = cf.result() + assert isinstance(expr, Literal) + set_val(expression, convert_string_to_int(expr.converted_value)) + else: + raise NotConstant + elif isinstance(expression.value, SolidityFunction): + set_val(expression, expression.value) + else: raise NotConstant - expr = expression.value.expression - # assumption that we won't have infinite loop - # Everything outside of literal - if isinstance( - expr, (BinaryOperation, UnaryOperation, Identifier, TupleExpression, TypeConversion) - ): - cf = ConstantFolding(expr, self._type) - expr = cf.result() - assert isinstance(expr, Literal) - set_val(expression, convert_string_to_int(expr.converted_value)) - # pylint: disable=too-many-branches + # pylint: disable=too-many-branches,too-many-statements def _post_binary_operation(self, expression: BinaryOperation) -> None: expression_left = expression.expression_left expression_right = expression.expression_right @@ -95,7 +104,6 @@ class ConstantFolding(ExpressionVisitor): (Literal, BinaryOperation, UnaryOperation, Identifier, TupleExpression, TypeConversion), ): raise NotConstant - left = get_val(expression_left) right = get_val(expression_right) @@ -183,7 +191,9 @@ class ConstantFolding(ExpressionVisitor): raise NotConstant def _post_literal(self, expression: Literal) -> None: - if expression.converted_value in ["true", "false"]: + if str(expression.type) == "bool": + set_val(expression, expression.converted_value) + elif str(expression.type) == "string": set_val(expression, expression.converted_value) else: try: @@ -195,7 +205,14 @@ class ConstantFolding(ExpressionVisitor): raise NotConstant def _post_call_expression(self, expression: expressions.CallExpression) -> None: - raise NotConstant + called = get_val(expression.called) + args = [get_val(arg) for arg in expression.arguments] + if called.name == "keccak256(bytes)": + digest = keccak.new(digest_bits=256) + digest.update(str(args[0]).encode("utf-8")) + set_val(expression, digest.digest()) + else: + raise NotConstant def _post_conditional_expression(self, expression: expressions.ConditionalExpression) -> None: raise NotConstant @@ -247,10 +264,24 @@ class ConstantFolding(ExpressionVisitor): expr = expression.expression if not isinstance( expr, - (Literal, BinaryOperation, UnaryOperation, Identifier, TupleExpression, TypeConversion), + ( + Literal, + BinaryOperation, + UnaryOperation, + Identifier, + TupleExpression, + TypeConversion, + CallExpression, + ), ): raise NotConstant cf = ConstantFolding(expr, self._type) expr = cf.result() assert isinstance(expr, Literal) - set_val(expression, convert_string_to_fraction(expr.converted_value)) + if str(expression.type).startswith("uint") and isinstance(expr.value, bytes): + value = int.from_bytes(expr.value, "big") + elif str(expression.type).startswith("byte") and isinstance(expr.value, int): + value = int.to_bytes(expr.value, 32, "big") + else: + value = convert_string_to_fraction(expr.converted_value) + set_val(expression, value) diff --git a/tests/conftest.py b/tests/conftest.py index 5ea228fd3..63fccfa12 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,12 @@ # pylint: disable=redefined-outer-name import os -from pathlib import Path -import tempfile import shutil +import tempfile +from pathlib import Path from contextlib import contextmanager -import pytest from filelock import FileLock from solc_select import solc_select +import pytest from slither import Slither diff --git a/tests/tools/check-erc/erc20.sol b/tests/tools/check_erc/erc20.sol similarity index 100% rename from tests/tools/check-erc/erc20.sol rename to tests/tools/check_erc/erc20.sol diff --git a/tests/tools/check-erc/test_1.txt b/tests/tools/check_erc/test_1.txt similarity index 100% rename from tests/tools/check-erc/test_1.txt rename to tests/tools/check_erc/test_1.txt diff --git a/tests/tools/check-kspec/safeAdd/safeAdd.sol b/tests/tools/check_kspec/safeAdd/safeAdd.sol similarity index 100% rename from tests/tools/check-kspec/safeAdd/safeAdd.sol rename to tests/tools/check_kspec/safeAdd/safeAdd.sol diff --git a/tests/tools/check-kspec/safeAdd/spec.md b/tests/tools/check_kspec/safeAdd/spec.md similarity index 100% rename from tests/tools/check-kspec/safeAdd/spec.md rename to tests/tools/check_kspec/safeAdd/spec.md diff --git a/tests/tools/check-kspec/test_1.txt b/tests/tools/check_kspec/test_1.txt similarity index 100% rename from tests/tools/check-kspec/test_1.txt rename to tests/tools/check_kspec/test_1.txt diff --git a/tests/tools/check-upgradeability/contractV1.sol b/tests/tools/check_upgradeability/contractV1.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV1.sol rename to tests/tools/check_upgradeability/contractV1.sol diff --git a/tests/tools/check-upgradeability/contractV1_struct.sol b/tests/tools/check_upgradeability/contractV1_struct.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV1_struct.sol rename to tests/tools/check_upgradeability/contractV1_struct.sol diff --git a/tests/tools/check-upgradeability/contractV2.sol b/tests/tools/check_upgradeability/contractV2.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV2.sol rename to tests/tools/check_upgradeability/contractV2.sol diff --git a/tests/tools/check-upgradeability/contractV2_bug.sol b/tests/tools/check_upgradeability/contractV2_bug.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV2_bug.sol rename to tests/tools/check_upgradeability/contractV2_bug.sol diff --git a/tests/tools/check-upgradeability/contractV2_bug2.sol b/tests/tools/check_upgradeability/contractV2_bug2.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV2_bug2.sol rename to tests/tools/check_upgradeability/contractV2_bug2.sol diff --git a/tests/tools/check-upgradeability/contractV2_struct.sol b/tests/tools/check_upgradeability/contractV2_struct.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV2_struct.sol rename to tests/tools/check_upgradeability/contractV2_struct.sol diff --git a/tests/tools/check-upgradeability/contractV2_struct_bug.sol b/tests/tools/check_upgradeability/contractV2_struct_bug.sol similarity index 100% rename from tests/tools/check-upgradeability/contractV2_struct_bug.sol rename to tests/tools/check_upgradeability/contractV2_struct_bug.sol diff --git a/tests/tools/check-upgradeability/contract_initialization.sol b/tests/tools/check_upgradeability/contract_initialization.sol similarity index 100% rename from tests/tools/check-upgradeability/contract_initialization.sol rename to tests/tools/check_upgradeability/contract_initialization.sol diff --git a/tests/tools/check-upgradeability/contract_v1_var_init.sol b/tests/tools/check_upgradeability/contract_v1_var_init.sol similarity index 100% rename from tests/tools/check-upgradeability/contract_v1_var_init.sol rename to tests/tools/check_upgradeability/contract_v1_var_init.sol diff --git a/tests/tools/check-upgradeability/contract_v2_constant.sol b/tests/tools/check_upgradeability/contract_v2_constant.sol similarity index 100% rename from tests/tools/check-upgradeability/contract_v2_constant.sol rename to tests/tools/check_upgradeability/contract_v2_constant.sol diff --git a/tests/tools/check-upgradeability/proxy.sol b/tests/tools/check_upgradeability/proxy.sol similarity index 100% rename from tests/tools/check-upgradeability/proxy.sol rename to tests/tools/check_upgradeability/proxy.sol diff --git a/tests/tools/check-upgradeability/test_1.txt b/tests/tools/check_upgradeability/test_1.txt similarity index 100% rename from tests/tools/check-upgradeability/test_1.txt rename to tests/tools/check_upgradeability/test_1.txt diff --git a/tests/tools/check-upgradeability/test_10.txt b/tests/tools/check_upgradeability/test_10.txt similarity index 100% rename from tests/tools/check-upgradeability/test_10.txt rename to tests/tools/check_upgradeability/test_10.txt diff --git a/tests/tools/check-upgradeability/test_11.txt b/tests/tools/check_upgradeability/test_11.txt similarity index 100% rename from tests/tools/check-upgradeability/test_11.txt rename to tests/tools/check_upgradeability/test_11.txt diff --git a/tests/tools/check-upgradeability/test_12.txt b/tests/tools/check_upgradeability/test_12.txt similarity index 100% rename from tests/tools/check-upgradeability/test_12.txt rename to tests/tools/check_upgradeability/test_12.txt diff --git a/tests/tools/check-upgradeability/test_13.txt b/tests/tools/check_upgradeability/test_13.txt similarity index 100% rename from tests/tools/check-upgradeability/test_13.txt rename to tests/tools/check_upgradeability/test_13.txt diff --git a/tests/tools/check-upgradeability/test_2.txt b/tests/tools/check_upgradeability/test_2.txt similarity index 100% rename from tests/tools/check-upgradeability/test_2.txt rename to tests/tools/check_upgradeability/test_2.txt diff --git a/tests/tools/check-upgradeability/test_3.txt b/tests/tools/check_upgradeability/test_3.txt similarity index 100% rename from tests/tools/check-upgradeability/test_3.txt rename to tests/tools/check_upgradeability/test_3.txt diff --git a/tests/tools/check-upgradeability/test_4.txt b/tests/tools/check_upgradeability/test_4.txt similarity index 100% rename from tests/tools/check-upgradeability/test_4.txt rename to tests/tools/check_upgradeability/test_4.txt diff --git a/tests/tools/check-upgradeability/test_5.txt b/tests/tools/check_upgradeability/test_5.txt similarity index 100% rename from tests/tools/check-upgradeability/test_5.txt rename to tests/tools/check_upgradeability/test_5.txt diff --git a/tests/tools/check-upgradeability/test_6.txt b/tests/tools/check_upgradeability/test_6.txt similarity index 100% rename from tests/tools/check-upgradeability/test_6.txt rename to tests/tools/check_upgradeability/test_6.txt diff --git a/tests/tools/check-upgradeability/test_7.txt b/tests/tools/check_upgradeability/test_7.txt similarity index 100% rename from tests/tools/check-upgradeability/test_7.txt rename to tests/tools/check_upgradeability/test_7.txt diff --git a/tests/tools/check-upgradeability/test_8.txt b/tests/tools/check_upgradeability/test_8.txt similarity index 100% rename from tests/tools/check-upgradeability/test_8.txt rename to tests/tools/check_upgradeability/test_8.txt diff --git a/tests/tools/check-upgradeability/test_9.txt b/tests/tools/check_upgradeability/test_9.txt similarity index 100% rename from tests/tools/check-upgradeability/test_9.txt rename to tests/tools/check_upgradeability/test_9.txt diff --git a/tests/tools/read-storage/conftest.py b/tests/tools/read-storage/conftest.py new file mode 100644 index 000000000..3e2cfb400 --- /dev/null +++ b/tests/tools/read-storage/conftest.py @@ -0,0 +1,56 @@ +""" +Testing utilities for the read-storage tool +""" + +import shutil +import subprocess +from time import sleep +from typing import Generator +from dataclasses import dataclass +from web3 import Web3 +import pytest + + +@dataclass +class GanacheInstance: + def __init__(self, provider: str, eth_address: str, eth_privkey: str): + self.provider = provider + self.eth_address = eth_address + self.eth_privkey = eth_privkey + + +@pytest.fixture(scope="module", name="ganache") +def fixture_ganache() -> Generator[GanacheInstance, None, None]: + """Fixture that runs ganache""" + if not shutil.which("ganache"): + raise Exception( + "ganache was not found in PATH, you can install it with `npm install -g ganache`" + ) + + # Address #1 when ganache is run with `--wallet.seed test`, it starts with 1000 ETH + eth_address = "0xae17D2dD99e07CA3bF2571CCAcEAA9e2Aefc2Dc6" + eth_privkey = "0xe48ba530a63326818e116be262fd39ae6dcddd89da4b1f578be8afd4e8894b8d" + eth = int(1e18 * 1e6) + port = 8545 + with subprocess.Popen( + f"""ganache + --port {port} + --chain.networkId 1 + --chain.chainId 1 + --account {eth_privkey},{eth} + """.replace( + "\n", " " + ), + shell=True, + ) as p: + + sleep(3) + yield GanacheInstance(f"http://127.0.0.1:{port}", eth_address, eth_privkey) + p.kill() + p.wait() + + +@pytest.fixture(scope="module", name="web3") +def fixture_web3(ganache: GanacheInstance): + w3 = Web3(Web3.HTTPProvider(ganache.provider, request_kwargs={"timeout": 30})) + return w3 diff --git a/tests/tools/read-storage/test_data/storage_layout-0.8.10.sol b/tests/tools/read-storage/test_data/StorageLayout.sol similarity index 95% rename from tests/tools/read-storage/test_data/storage_layout-0.8.10.sol rename to tests/tools/read-storage/test_data/StorageLayout.sol index 28d1428eb..0940b6769 100644 --- a/tests/tools/read-storage/test_data/storage_layout-0.8.10.sol +++ b/tests/tools/read-storage/test_data/StorageLayout.sol @@ -1,5 +1,6 @@ +pragma solidity 0.8.10; // overwrite abi and bin: -// solc tests/storage-layout/storage_layout-0.8.10.sol --abi --bin -o tests/storage-layout --overwrite +// solc StorageLayout.sol --abi --bin --overwrite contract StorageLayout { uint248 packedUint = 1; bool packedBool = true; diff --git a/tests/tools/read-storage/test_data/TEST_unstructured_storage.json b/tests/tools/read-storage/test_data/TEST_unstructured_storage.json new file mode 100644 index 000000000..6dbdbddca --- /dev/null +++ b/tests/tools/read-storage/test_data/TEST_unstructured_storage.json @@ -0,0 +1,56 @@ +{ + "masterCopy": { + "name": "masterCopy", + "type_string": "address", + "slot": 0, + "size": 160, + "offset": 0, + "value": "0x0000000000000000000000000000000000000000", + "elems": {} + }, + "ADMIN_SLOT": { + "name": "ADMIN_SLOT", + "type_string": "address", + "slot": 7616251639890160809447714111544359812065171195189364993079081710756264753419, + "size": 160, + "offset": 0, + "value": "0xae17D2dD99e07CA3bF2571CCAcEAA9e2Aefc2Dc6", + "elems": {} + }, + "IMPLEMENTATION_SLOT": { + "name": "IMPLEMENTATION_SLOT", + "type_string": "address", + "slot": 24440054405305269366569402256811496959409073762505157381672968839269610695612, + "size": 160, + "offset": 0, + "value": "0x54006763154c764da4AF42a8c3cfc25Ea29765D5", + "elems": {} + }, + "ROLLBACK_SLOT": { + "name": "ROLLBACK_SLOT", + "type_string": "bool", + "slot": 33048860383849004559742813297059419343339852917517107368639918720169455489347, + "size": 1, + "offset": 0, + "value": true, + "elems": {} + }, + "BEACON_SLOT": { + "name": "BEACON_SLOT", + "type_string": "address", + "slot": 74152234768234802001998023604048924213078445070507226371336425913862612794704, + "size": 160, + "offset": 0, + "value": "0x54006763154c764da4AF42a8c3cfc25Ea29765D5", + "elems": {} + }, + "fallback_sload_hardcoded": { + "name": "fallback_sload_hardcoded", + "type_string": "address", + "slot": 89532207833283453166981358064394884954800891875771469636219037672473505217783, + "size": 160, + "offset": 0, + "value": "0x54006763154c764da4AF42a8c3cfc25Ea29765D5", + "elems": {} + } +} \ No newline at end of file diff --git a/tests/tools/read-storage/test_data/UnstructuredStorageLayout.abi b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.abi new file mode 100644 index 000000000..9b579f254 --- /dev/null +++ b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.abi @@ -0,0 +1 @@ +[{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/tests/tools/read-storage/test_data/UnstructuredStorageLayout.bin b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.bin new file mode 100644 index 000000000..9f20de74c --- /dev/null +++ b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061030b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002f5760003560e01c8063975057e71461009757610030565b5b600180035473ffffffffffffffffffffffffffffffffffffffff600054167fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7543660008037600080366000845af43d806000803e816000811461009257816000f35b816000fd5b61009f6100a1565b005b60006100ab6101a8565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146100e657600080fd5b60007f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b9050600033905080825560007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b905060007354006763154c764da4af42a8c3cfc25ea29765d59050808255807fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75561018460016101d6565b6101a17354006763154c764da4af42a8c3cfc25ea29765d5610220565b5050505050565b6000807f10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b9050805491505090565b806102037f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b61025e565b60000160006101000a81548160ff02191690831515021790555050565b600060017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5160001c61025291906102a1565b60001b90508181555050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102ac82610268565b91506102b783610268565b9250828210156102ca576102c9610272565b5b82820390509291505056fea2646970667358221220f079473c1b94744ac2818f521ccef06187a433d996633e61e51a86dfb60cc6ff64736f6c634300080a0033 \ No newline at end of file diff --git a/tests/tools/read-storage/test_data/UnstructuredStorageLayout.sol b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.sol new file mode 100644 index 000000000..81b14a119 --- /dev/null +++ b/tests/tools/read-storage/test_data/UnstructuredStorageLayout.sol @@ -0,0 +1,141 @@ +pragma solidity 0.8.10; +// overwrite abi and bin: +// solc UnstructuredStorageLayout.sol --abi --bin --overwrite + +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } +} + +contract UnstructuredStorageLayout { + + bytes32 constant ADMIN_SLOT = keccak256("org.zeppelinos.proxy.admin"); + // This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. + bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 + bytes32 private constant ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; + bytes32 constant BEACON_SLOT = bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1); + + address internal masterCopy; + + function _admin() internal view returns (address admin) { + bytes32 slot = ADMIN_SLOT; + assembly { + admin := sload(slot) + } + } + + function _implementation() internal view returns (address) { + address _impl; + bytes32 slot = IMPLEMENTATION_SLOT; + assembly { + _impl := sload(slot) + } + return _impl; + } + + function _set_rollback(bool _rollback) internal { + StorageSlot.getBooleanSlot(ROLLBACK_SLOT).value = _rollback; + } + + function _set_beacon(address _beacon) internal { + bytes32 slot = bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1); + assembly { + sstore(slot, _beacon) + } + } + + function store() external { + address admin = _admin(); + require(admin == address(0)); + + bytes32 admin_slot = ADMIN_SLOT; + address sender = msg.sender; + assembly { + sstore(admin_slot, sender) + } + + bytes32 impl_slot = IMPLEMENTATION_SLOT; + address _impl = address(0x0054006763154c764da4af42a8c3cfc25ea29765d5); + assembly { + sstore(impl_slot, _impl) + sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, _impl) + } + + _set_rollback(true); + _set_beacon(address(0x0054006763154c764da4af42a8c3cfc25ea29765d5)); + } + + // Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7" + fallback() external { + assembly { // solium-disable-line + let nonsense := sload(sub(1,1)) + let _masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff) + let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) + calldatacopy(0x0, 0x0, calldatasize()) + let success := delegatecall(gas(), contractLogic, 0x0, calldatasize(), 0, 0) + let retSz := returndatasize() + returndatacopy(0, 0, retSz) + switch success + case 0 { + revert(0, retSz) + } + default { + return(0, retSz) + } + } + } +} diff --git a/tests/tools/read-storage/test_read_storage.py b/tests/tools/read-storage/test_read_storage.py index ea04a91fe..b056ad056 100644 --- a/tests/tools/read-storage/test_read_storage.py +++ b/tests/tools/read-storage/test_read_storage.py @@ -1,14 +1,9 @@ -import json import re -import shutil -import subprocess -from time import sleep +import json from pathlib import Path -from typing import Generator import pytest from deepdiff import DeepDiff -from web3 import Web3 from web3.contract import Contract from slither import Slither @@ -16,50 +11,6 @@ from slither.tools.read_storage import SlitherReadStorage, RpcInfo TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" -# pylint: disable=too-few-public-methods -class GanacheInstance: - def __init__(self, provider: str, eth_address: str, eth_privkey: str): - self.provider = provider - self.eth_address = eth_address - self.eth_privkey = eth_privkey - - -@pytest.fixture(scope="module", name="web3") -def fixture_web3(ganache: GanacheInstance): - w3 = Web3(Web3.HTTPProvider(ganache.provider, request_kwargs={"timeout": 30})) - return w3 - - -@pytest.fixture(scope="module", name="ganache") -def fixture_ganache() -> Generator[GanacheInstance, None, None]: - """Fixture that runs ganache""" - if not shutil.which("ganache"): - raise Exception( - "ganache was not found in PATH, you can install it with `npm install -g ganache`" - ) - - # Address #1 when ganache is run with `--wallet.seed test`, it starts with 1000 ETH - eth_address = "0xae17D2dD99e07CA3bF2571CCAcEAA9e2Aefc2Dc6" - eth_privkey = "0xe48ba530a63326818e116be262fd39ae6dcddd89da4b1f578be8afd4e8894b8d" - eth = int(1e18 * 1e6) - port = 8545 - with subprocess.Popen( - f"""ganache - --port {port} - --chain.networkId 1 - --chain.chainId 1 - --account {eth_privkey},{eth} - """.replace( - "\n", " " - ), - shell=True, - ) as p: - - sleep(3) - yield GanacheInstance(f"http://127.0.0.1:{port}", eth_address, eth_privkey) - p.kill() - p.wait() - def get_source_file(file_path) -> str: with open(file_path, "r", encoding="utf8") as f: @@ -89,24 +40,29 @@ def deploy_contract(w3, ganache, contract_bin, contract_abi) -> Contract: # pylint: disable=too-many-locals +@pytest.mark.parametrize( + "test_contract, storage_file", + [("StorageLayout", "storage_layout"), ("UnstructuredStorageLayout", "unstructured_storage")], +) @pytest.mark.usefixtures("web3", "ganache") -def test_read_storage(web3, ganache, solc_binary_path) -> None: +def test_read_storage(test_contract, storage_file, web3, ganache, solc_binary_path) -> None: solc_path = solc_binary_path(version="0.8.10") assert web3.is_connected() - bin_path = Path(TEST_DATA_DIR, "StorageLayout.bin").as_posix() - abi_path = Path(TEST_DATA_DIR, "StorageLayout.abi").as_posix() + bin_path = Path(TEST_DATA_DIR, f"{test_contract}.bin").as_posix() + abi_path = Path(TEST_DATA_DIR, f"{test_contract}.abi").as_posix() bytecode = get_source_file(bin_path) abi = get_source_file(abi_path) contract = deploy_contract(web3, ganache, bytecode, abi) contract.functions.store().transact({"from": ganache.eth_address}) address = contract.address - sl = Slither(Path(TEST_DATA_DIR, "storage_layout-0.8.10.sol").as_posix(), solc=solc_path) + sl = Slither(Path(TEST_DATA_DIR, f"{test_contract}.sol").as_posix(), solc=solc_path) contracts = sl.contracts rpc_info: RpcInfo = RpcInfo(ganache.provider) srs = SlitherReadStorage(contracts, 100, rpc_info) + srs.unstructured = True srs.storage_address = address srs.get_all_storage_variables() srs.get_storage_layout() @@ -116,7 +72,7 @@ def test_read_storage(web3, ganache, solc_binary_path) -> None: slot_infos_json = srs.to_json() json.dump(slot_infos_json, file, indent=4) - expected_file = Path(TEST_DATA_DIR, "TEST_storage_layout.json").as_posix() + expected_file = Path(TEST_DATA_DIR, f"TEST_{storage_file}.json").as_posix() with open(expected_file, "r", encoding="utf8") as f: expected = json.load(f) diff --git a/tests/unit/core/test_constant_folding.py b/tests/unit/core/test_constant_folding.py index 489b4e0ec..6c0cc8295 100644 --- a/tests/unit/core/test_constant_folding.py +++ b/tests/unit/core/test_constant_folding.py @@ -21,39 +21,40 @@ def test_constant_folding_rational(solc_binary_path): variable_a = contract.get_state_variable_from_name("a") assert str(variable_a.type) == "uint256" - assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "10" + assert ConstantFolding(variable_a.expression, "uint256").result().value == 10 variable_b = contract.get_state_variable_from_name("b") assert str(variable_b.type) == "int128" - assert str(ConstantFolding(variable_b.expression, "int128").result()) == "2" + assert ConstantFolding(variable_b.expression, "int128").result().value == 2 variable_c = contract.get_state_variable_from_name("c") assert str(variable_c.type) == "int64" - assert str(ConstantFolding(variable_c.expression, "int64").result()) == "3" + assert ConstantFolding(variable_c.expression, "int64").result().value == 3 variable_d = contract.get_state_variable_from_name("d") assert str(variable_d.type) == "int256" - assert str(ConstantFolding(variable_d.expression, "int256").result()) == "1500" + assert ConstantFolding(variable_d.expression, "int256").result().value == 1500 variable_e = contract.get_state_variable_from_name("e") assert str(variable_e.type) == "uint256" assert ( - str(ConstantFolding(variable_e.expression, "uint256").result()) - == "57896044618658097711785492504343953926634992332820282019728792003956564819968" + ConstantFolding(variable_e.expression, "uint256").result().value + == 57896044618658097711785492504343953926634992332820282019728792003956564819968 ) variable_f = contract.get_state_variable_from_name("f") assert str(variable_f.type) == "uint256" assert ( - str(ConstantFolding(variable_f.expression, "uint256").result()) - == "115792089237316195423570985008687907853269984665640564039457584007913129639935" + ConstantFolding(variable_f.expression, "uint256").result().value + == 115792089237316195423570985008687907853269984665640564039457584007913129639935 ) variable_g = contract.get_state_variable_from_name("g") assert str(variable_g.type) == "int64" - assert str(ConstantFolding(variable_g.expression, "int64").result()) == "-7" + assert ConstantFolding(variable_g.expression, "int64").result().value == -7 +# pylint: disable=too-many-locals def test_constant_folding_binary_expressions(solc_binary_path): sl = Slither( Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_binop.sol").as_posix(), @@ -63,51 +64,65 @@ def test_constant_folding_binary_expressions(solc_binary_path): variable_a = contract.get_state_variable_from_name("a") assert str(variable_a.type) == "uint256" - assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "0" + assert ConstantFolding(variable_a.expression, "uint256").result().value == 0 variable_b = contract.get_state_variable_from_name("b") assert str(variable_b.type) == "uint256" - assert str(ConstantFolding(variable_b.expression, "uint256").result()) == "3" + assert ConstantFolding(variable_b.expression, "uint256").result().value == 3 variable_c = contract.get_state_variable_from_name("c") assert str(variable_c.type) == "uint256" - assert str(ConstantFolding(variable_c.expression, "uint256").result()) == "3" + assert ConstantFolding(variable_c.expression, "uint256").result().value == 3 variable_d = contract.get_state_variable_from_name("d") assert str(variable_d.type) == "bool" - assert str(ConstantFolding(variable_d.expression, "bool").result()) == "False" + assert ConstantFolding(variable_d.expression, "bool").result().value is False variable_e = contract.get_state_variable_from_name("e") assert str(variable_e.type) == "bool" - assert str(ConstantFolding(variable_e.expression, "bool").result()) == "False" + assert ConstantFolding(variable_e.expression, "bool").result().value is False variable_f = contract.get_state_variable_from_name("f") assert str(variable_f.type) == "bool" - assert str(ConstantFolding(variable_f.expression, "bool").result()) == "True" + assert ConstantFolding(variable_f.expression, "bool").result().value is True variable_g = contract.get_state_variable_from_name("g") assert str(variable_g.type) == "bool" - assert str(ConstantFolding(variable_g.expression, "bool").result()) == "False" + assert ConstantFolding(variable_g.expression, "bool").result().value is False variable_h = contract.get_state_variable_from_name("h") assert str(variable_h.type) == "bool" - assert str(ConstantFolding(variable_h.expression, "bool").result()) == "False" + assert ConstantFolding(variable_h.expression, "bool").result().value is False variable_i = contract.get_state_variable_from_name("i") assert str(variable_i.type) == "bool" - assert str(ConstantFolding(variable_i.expression, "bool").result()) == "True" + assert ConstantFolding(variable_i.expression, "bool").result().value is True variable_j = contract.get_state_variable_from_name("j") assert str(variable_j.type) == "bool" - assert str(ConstantFolding(variable_j.expression, "bool").result()) == "False" + assert ConstantFolding(variable_j.expression, "bool").result().value is False variable_k = contract.get_state_variable_from_name("k") assert str(variable_k.type) == "bool" - assert str(ConstantFolding(variable_k.expression, "bool").result()) == "True" + assert ConstantFolding(variable_k.expression, "bool").result().value is True variable_l = contract.get_state_variable_from_name("l") assert str(variable_l.type) == "uint256" assert ( - str(ConstantFolding(variable_l.expression, "uint256").result()) - == "115792089237316195423570985008687907853269984665640564039457584007913129639935" + ConstantFolding(variable_l.expression, "uint256").result().value + == 115792089237316195423570985008687907853269984665640564039457584007913129639935 ) + + IMPLEMENTATION_SLOT = contract.get_state_variable_from_name("IMPLEMENTATION_SLOT") + assert str(IMPLEMENTATION_SLOT.type) == "bytes32" + assert ( + int.from_bytes( + ConstantFolding(IMPLEMENTATION_SLOT.expression, "bytes32").result().value, + byteorder="big", + ) + == 24440054405305269366569402256811496959409073762505157381672968839269610695612 + ) + + variable_m = contract.get_state_variable_from_name("m") + assert str(variable_m.type) == "bytes2" + assert ConstantFolding(variable_m.expression, "bytes2").result().value == "ab" diff --git a/tests/unit/core/test_data/constant_folding/constant_folding_binop.sol b/tests/unit/core/test_data/constant_folding/constant_folding_binop.sol index 923418ce7..3935585b8 100644 --- a/tests/unit/core/test_data/constant_folding/constant_folding_binop.sol +++ b/tests/unit/core/test_data/constant_folding/constant_folding_binop.sol @@ -11,4 +11,6 @@ contract BinOp { bool j = true && false; bool k = true || false; uint l = uint(1) - uint(2); + bytes32 IMPLEMENTATION_SLOT = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1); + bytes2 m = "ab"; } \ No newline at end of file From eacbf5c224fb85a5f70263d32937700468ee28ff Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 11:35:47 -0500 Subject: [PATCH 083/338] Create dependabot.yml (#1972) --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..dd3015cbc --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "dev" + schedule: + interval: "weekly" From d56f66338051eb07b2f280a1dd2f355ab6f95394 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 11:36:16 -0500 Subject: [PATCH 084/338] create release action with sigstore (#1957) --- .github/workflows/publish.yml | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..529752f80 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,54 @@ +name: Publish to PyPI + +on: + release: + types: [published] + +jobs: + build-release: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Build distributions + run: | + python -m pip install --upgrade pip + python -m pip install build + python -m build + - name: Upload distributions + uses: actions/upload-artifact@v3 + with: + name: slither-dists + path: dist/ + + publish: + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write # For trusted publishing + codesigning. + contents: write # For attaching signing artifacts to the release. + needs: + - build-release + steps: + - name: fetch dists + uses: actions/download-artifact@v3 + with: + name: slither-dists + path: dist/ + + - name: publish + uses: pypa/gh-action-pypi-publish@v1.8.6 + + - name: sign + uses: sigstore/gh-action-sigstore-python@v1.2.3 + with: + inputs: ./dist/*.tar.gz ./dist/*.whl + release-signing-artifacts: true + bundle-only: true From 7f7ff770d7c558916fee1d530f6d5a0ec7e36e38 Mon Sep 17 00:00:00 2001 From: Paul Razvan Berg Date: Tue, 20 Jun 2023 21:56:44 +0300 Subject: [PATCH 085/338] docs: update recommendation for msg.value-inside-a-loop (#1971) --- slither/detectors/statements/msg_value_in_loop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/statements/msg_value_in_loop.py b/slither/detectors/statements/msg_value_in_loop.py index 55bd9bfc2..83c5658ca 100644 --- a/slither/detectors/statements/msg_value_in_loop.py +++ b/slither/detectors/statements/msg_value_in_loop.py @@ -79,7 +79,7 @@ contract MsgValueInLoop{ # endregion wiki_exploit_scenario WIKI_RECOMMENDATION = """ -Track msg.value through a local variable and decrease its amount on every iteration/usage. +Provide an explicit array of amounts alongside the receivers array, and check that the sum of all amounts matches `msg.value`. """ def _detect(self) -> List[Output]: From 068eee83412ad15823be79900dfd1e033056d072 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 17:25:40 -0500 Subject: [PATCH 086/338] add test --- tests/unit/core/test_arithmetic.py | 30 ++++++++++++++++++- .../arithmetic_usage/unchecked_scope.sol | 17 +++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/unit/core/test_data/arithmetic_usage/unchecked_scope.sol diff --git a/tests/unit/core/test_arithmetic.py b/tests/unit/core/test_arithmetic.py index 6de63d767..f82885aa8 100644 --- a/tests/unit/core/test_arithmetic.py +++ b/tests/unit/core/test_arithmetic.py @@ -2,7 +2,8 @@ from pathlib import Path from slither import Slither from slither.utils.arithmetic import unchecked_arithemtic_usage - +from slither.slithir.operations import Binary, Unary, Assignment +from slither.slithir.variables.temporary import TemporaryVariable TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "arithmetic_usage" @@ -14,3 +15,30 @@ def test_arithmetic_usage(solc_binary_path) -> None: assert { f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0]) } == {"2b4bc73cf59d486dd9043e840b5028b679354dd9", "e4ecd4d0fda7e762d29aceb8425f2c5d4d0bf962"} + + +def test_arithmetic_usage(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.15") + slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix(), solc=solc_path) + + assert { + f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0]) + } == {"2b4bc73cf59d486dd9043e840b5028b679354dd9", "e4ecd4d0fda7e762d29aceb8425f2c5d4d0bf962"} + + +def test_scope_is_checked(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.15") + slither = Slither(Path(TEST_DATA_DIR, "unchecked_scope.sol").as_posix(), solc=solc_path) + func = slither.get_contract_from_name("TestScope")[0].get_function_from_full_name( + "scope(uint256)" + ) + bin_op_is_checked = {} + for node in func.nodes: + for op in node.irs: + if isinstance(op, (Binary, Unary)): + bin_op_is_checked[op.lvalue] = op.node.scope.is_checked + if isinstance(op, Assignment) and isinstance(op.rvalue, TemporaryVariable): + if op.lvalue.name.startswith("checked"): + assert bin_op_is_checked[op.rvalue] is True + else: + assert bin_op_is_checked[op.rvalue] is False diff --git a/tests/unit/core/test_data/arithmetic_usage/unchecked_scope.sol b/tests/unit/core/test_data/arithmetic_usage/unchecked_scope.sol new file mode 100644 index 000000000..f0cee1f10 --- /dev/null +++ b/tests/unit/core/test_data/arithmetic_usage/unchecked_scope.sol @@ -0,0 +1,17 @@ +contract TestScope { + function scope(uint256 x) public { + uint checked1 = x - x; + unchecked { + uint unchecked1 = x - x; + if (true) { + uint unchecked2 = x - x; + + } + for (uint i = 0; i < 10; i++) { + uint unchecked3 = x - x; + + } + } + uint checked2 = x - x; + } +} \ No newline at end of file From 96b103225f4867caca8fe699ab97ee8cc8727910 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 20 Jun 2023 17:34:14 -0500 Subject: [PATCH 087/338] fix merge/fmt --- slither/solc_parsing/declarations/function.py | 8 +++++--- tests/unit/core/test_arithmetic.py | 9 --------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index aeb05cd05..35ca51aeb 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -726,7 +726,9 @@ class FunctionSolc(CallerContextExpression): self._parse_catch(clause, node, catch_scope, False) return node - def _parse_catch(self, statement: Dict, node: NodeSolc, scope: Scope, add_param: bool) -> NodeSolc: + def _parse_catch( + self, statement: Dict, node: NodeSolc, scope: Scope, add_param: bool + ) -> NodeSolc: block = statement.get("block", None) if block is None: @@ -874,7 +876,7 @@ class FunctionSolc(CallerContextExpression): self.get_children("children"): [variable, init], } - new_node = self._parse_variable_definition(new_statement, new_node) + new_node = self._parse_variable_definition(new_statement, new_node, scope) else: # If we have # var (a, b) = f() @@ -893,7 +895,7 @@ class FunctionSolc(CallerContextExpression): variables.append(variable) new_node = self._parse_variable_definition_init_tuple( - new_statement, i, new_node + new_statement, i, new_node, scope ) i = i + 1 var_identifiers = [] diff --git a/tests/unit/core/test_arithmetic.py b/tests/unit/core/test_arithmetic.py index f82885aa8..760b6d397 100644 --- a/tests/unit/core/test_arithmetic.py +++ b/tests/unit/core/test_arithmetic.py @@ -8,15 +8,6 @@ from slither.slithir.variables.temporary import TemporaryVariable TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "arithmetic_usage" -def test_arithmetic_usage(solc_binary_path) -> None: - solc_path = solc_binary_path("0.8.15") - slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix(), solc=solc_path) - - assert { - f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0]) - } == {"2b4bc73cf59d486dd9043e840b5028b679354dd9", "e4ecd4d0fda7e762d29aceb8425f2c5d4d0bf962"} - - def test_arithmetic_usage(solc_binary_path) -> None: solc_path = solc_binary_path("0.8.15") slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix(), solc=solc_path) From 8e0e7b79e7603c73fa50e43342cf96e3cf57228d Mon Sep 17 00:00:00 2001 From: xfu Date: Wed, 21 Jun 2023 08:54:37 -0500 Subject: [PATCH 088/338] fix event canonical_name --- slither/core/declarations/event.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/core/declarations/event.py b/slither/core/declarations/event.py index 9d42ac224..1b58ff63b 100644 --- a/slither/core/declarations/event.py +++ b/slither/core/declarations/event.py @@ -45,7 +45,7 @@ class Event(ContractLevel, SourceMapping): Returns: str: contract.func_name(type1,type2) """ - return self.contract.name + self.full_name + return self.contract.name + "." + self.full_name @property def elems(self) -> List["EventVariable"]: From 1b5e2e932765316fba8a1166d893a9f1e8d9b746 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 21 Jun 2023 08:56:07 -0500 Subject: [PATCH 089/338] update detector tests to reflect event fmt --- ...lShadowing_0_4_25_shadowing_builtin_symbols_sol__0.txt | 4 ++-- ...lShadowing_0_5_16_shadowing_builtin_symbols_sol__0.txt | 4 ++-- ...alShadowing_0_4_25_shadowing_local_variable_sol__0.txt | 2 +- ...alShadowing_0_5_16_shadowing_local_variable_sol__0.txt | 2 +- ...alShadowing_0_6_11_shadowing_local_variable_sol__0.txt | 2 +- ...calShadowing_0_7_6_shadowing_local_variable_sol__0.txt | 2 +- ...r_NamingConvention_0_4_25_naming_convention_sol__0.txt | 4 ++-- ...r_NamingConvention_0_5_16_naming_convention_sol__0.txt | 4 ++-- ...r_NamingConvention_0_6_11_naming_convention_sol__0.txt | 4 ++-- ...or_NamingConvention_0_7_6_naming_convention_sol__0.txt | 4 ++-- ...edERC20EventParameters_0_4_25_erc20_indexed_sol__0.txt | 8 ++++---- ...edERC20EventParameters_0_5_16_erc20_indexed_sol__0.txt | 8 ++++---- ...edERC20EventParameters_0_6_11_erc20_indexed_sol__0.txt | 8 ++++---- ...xedERC20EventParameters_0_7_6_erc20_indexed_sol__0.txt | 8 ++++---- 14 files changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_4_25_shadowing_builtin_symbols_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_4_25_shadowing_builtin_symbols_sol__0.txt index 7c94735da..283b93ee5 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_4_25_shadowing_builtin_symbols_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_4_25_shadowing_builtin_symbols_sol__0.txt @@ -12,12 +12,12 @@ FurtherExtendedContract.this (tests/e2e/detectors/test_data/shadowing-builtin/0. BaseContract.now (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#5) (state variable) shadows built-in symbol" -BaseContractrevert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol" - ExtendedContract.assert(bool).msg (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#14) (local variable) shadows built-in symbol" ExtendedContract.assert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#13-15) (function) shadows built-in symbol" +BaseContract.revert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol" + FurtherExtendedContract.require().sha3 (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#26) (local variable) shadows built-in symbol" FurtherExtendedContract.blockhash (tests/e2e/detectors/test_data/shadowing-builtin/0.4.25/shadowing_builtin_symbols.sol#19) (state variable) shadows built-in symbol" diff --git a/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_5_16_shadowing_builtin_symbols_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_5_16_shadowing_builtin_symbols_sol__0.txt index f576e19e0..2780f9e62 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_5_16_shadowing_builtin_symbols_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_BuiltinSymbolShadowing_0_5_16_shadowing_builtin_symbols_sol__0.txt @@ -10,12 +10,12 @@ FurtherExtendedContract.this (tests/e2e/detectors/test_data/shadowing-builtin/0. BaseContract.now (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#5) (state variable) shadows built-in symbol" -BaseContractrevert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol" - ExtendedContract.assert(bool).msg (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#14) (local variable) shadows built-in symbol" ExtendedContract.assert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#13-15) (function) shadows built-in symbol" +BaseContract.revert(bool) (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol" + FurtherExtendedContract.require().sha3 (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#26) (local variable) shadows built-in symbol" FurtherExtendedContract.blockhash (tests/e2e/detectors/test_data/shadowing-builtin/0.5.16/shadowing_builtin_symbols.sol#19) (state variable) shadows built-in symbol" diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_4_25_shadowing_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_4_25_shadowing_local_variable_sol__0.txt index 913acf4ea..0f98475aa 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_4_25_shadowing_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_4_25_shadowing_local_variable_sol__0.txt @@ -10,7 +10,7 @@ FurtherExtendedContract.shadowingParent(uint256).y (tests/e2e/detectors/test_dat - BaseContract.y (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#5) (state variable) FurtherExtendedContract.shadowingParent(uint256).v (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#25) shadows: - - ExtendedContractv() (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#13) (event) + - ExtendedContract.v() (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#13) (event) FurtherExtendedContract.shadowingParent(uint256).w (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#25) shadows: - FurtherExtendedContract.w() (tests/e2e/detectors/test_data/shadowing-local/0.4.25/shadowing_local_variable.sol#20-23) (modifier) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_5_16_shadowing_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_5_16_shadowing_local_variable_sol__0.txt index 7fcbe83d2..56d139bea 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_5_16_shadowing_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_5_16_shadowing_local_variable_sol__0.txt @@ -10,7 +10,7 @@ FurtherExtendedContract.shadowingParent(uint256).y (tests/e2e/detectors/test_dat - BaseContract.y (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#5) (state variable) FurtherExtendedContract.shadowingParent(uint256).v (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#25) shadows: - - ExtendedContractv() (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#13) (event) + - ExtendedContract.v() (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#13) (event) FurtherExtendedContract.shadowingParent(uint256).w (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#25) shadows: - FurtherExtendedContract.w() (tests/e2e/detectors/test_data/shadowing-local/0.5.16/shadowing_local_variable.sol#20-23) (modifier) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_6_11_shadowing_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_6_11_shadowing_local_variable_sol__0.txt index b4de3265f..a52ac48af 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_6_11_shadowing_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_6_11_shadowing_local_variable_sol__0.txt @@ -5,7 +5,7 @@ FurtherExtendedContract.shadowingParent(uint256).y (tests/e2e/detectors/test_dat - BaseContract.y (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#5) (state variable) FurtherExtendedContract.shadowingParent(uint256).v (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#25) shadows: - - ExtendedContractv() (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#13) (event) + - ExtendedContract.v() (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#13) (event) FurtherExtendedContract.shadowingParent(uint256).w (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#25) shadows: - FurtherExtendedContract.w() (tests/e2e/detectors/test_data/shadowing-local/0.6.11/shadowing_local_variable.sol#20-23) (modifier) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_7_6_shadowing_local_variable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_7_6_shadowing_local_variable_sol__0.txt index 43ecfab68..e618b988c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_7_6_shadowing_local_variable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_LocalShadowing_0_7_6_shadowing_local_variable_sol__0.txt @@ -5,7 +5,7 @@ FurtherExtendedContract.shadowingParent(uint256).y (tests/e2e/detectors/test_dat - BaseContract.y (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#5) (state variable) FurtherExtendedContract.shadowingParent(uint256).v (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#25) shadows: - - ExtendedContractv() (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#13) (event) + - ExtendedContract.v() (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#13) (event) FurtherExtendedContract.shadowingParent(uint256).w (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#25) shadows: - FurtherExtendedContract.w() (tests/e2e/detectors/test_data/shadowing-local/0.7.6/shadowing_local_variable.sol#20-23) (modifier) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt index 0419c1b9a..ed4177ca1 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt @@ -18,10 +18,10 @@ Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-co Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#56) is not in mixedCase -Event namingevent_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords - Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords + Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#41-43) is not in mixedCase Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#30-33) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt index c5fd1f30f..35c11193f 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt @@ -18,10 +18,10 @@ Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-co Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#56) is not in mixedCase -Event namingevent_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords - Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords + Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#41-43) is not in mixedCase Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#30-33) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt index 1bbe28843..f692e211b 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt @@ -18,10 +18,10 @@ Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-co Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#56) is not in mixedCase -Event namingevent_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#23) is not in CapWords - Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#23) is not in CapWords + Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#41-43) is not in mixedCase Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#30-33) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt index 5f560ba51..af17cabe8 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt @@ -18,10 +18,10 @@ Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-co Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#56) is not in mixedCase -Event namingevent_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#23) is not in CapWords - Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#23) is not in CapWords + Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#41-43) is not in mixedCase Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#30-33) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_4_25_erc20_indexed_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_4_25_erc20_indexed_sol__0.txt index a571ef77a..b4097bd10 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_4_25_erc20_indexed_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_4_25_erc20_indexed_sol__0.txt @@ -1,8 +1,8 @@ -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#19)does not index parameter to +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#20)does not index parameter owner -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#20)does not index parameter owner +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#19)does not index parameter from -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#19)does not index parameter from +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#20)does not index parameter spender -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#20)does not index parameter spender +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.4.25/erc20_indexed.sol#19)does not index parameter to diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_5_16_erc20_indexed_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_5_16_erc20_indexed_sol__0.txt index 09171d188..77ab9c2bd 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_5_16_erc20_indexed_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_5_16_erc20_indexed_sol__0.txt @@ -1,8 +1,8 @@ -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#19)does not index parameter to +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#20)does not index parameter owner -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#20)does not index parameter owner +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#19)does not index parameter from -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#19)does not index parameter from +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#20)does not index parameter spender -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#20)does not index parameter spender +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.5.16/erc20_indexed.sol#19)does not index parameter to diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_6_11_erc20_indexed_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_6_11_erc20_indexed_sol__0.txt index c0cbe9270..9e11f44c8 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_6_11_erc20_indexed_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_6_11_erc20_indexed_sol__0.txt @@ -1,8 +1,8 @@ -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#19)does not index parameter to +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#20)does not index parameter owner -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#20)does not index parameter owner +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#19)does not index parameter from -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#19)does not index parameter from +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#20)does not index parameter spender -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#20)does not index parameter spender +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.6.11/erc20_indexed.sol#19)does not index parameter to diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_7_6_erc20_indexed_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_7_6_erc20_indexed_sol__0.txt index 532a8b6cd..8083e8f71 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_7_6_erc20_indexed_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnindexedERC20EventParameters_0_7_6_erc20_indexed_sol__0.txt @@ -1,8 +1,8 @@ -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#19)does not index parameter to +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#20)does not index parameter owner -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#20)does not index parameter owner +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#19)does not index parameter from -ERC20 event IERC20BadTransfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#19)does not index parameter from +ERC20 event IERC20Bad.Approval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#20)does not index parameter spender -ERC20 event IERC20BadApproval(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#20)does not index parameter spender +ERC20 event IERC20Bad.Transfer(address,address,uint256) (tests/e2e/detectors/test_data/erc20-indexed/0.7.6/erc20_indexed.sol#19)does not index parameter to From e1febdd74ecd2c26fbf1524d872034b57b15e3e2 Mon Sep 17 00:00:00 2001 From: bossjoker1 <1397157763@qq.com> Date: Wed, 21 Jun 2023 09:34:59 -0500 Subject: [PATCH 090/338] Check the respective parameter's storage location for each argument --- .../compiler_bugs/array_by_reference.py | 13 ++++++----- ...rence_0_4_25_array_by_reference_sol__0.txt | 14 +++++++----- ...rence_0_5_16_array_by_reference_sol__0.txt | 14 +++++++----- ...rence_0_6_11_array_by_reference_sol__0.txt | 14 +++++++----- ...erence_0_7_6_array_by_reference_sol__0.txt | 14 +++++++----- .../0.4.25/array_by_reference.sol | 21 ++++++++++++++++++ .../0.4.25/array_by_reference.sol-0.4.25.zip | Bin 4879 -> 6184 bytes .../0.5.16/array_by_reference.sol | 21 ++++++++++++++++++ .../0.5.16/array_by_reference.sol-0.5.16.zip | Bin 4925 -> 6194 bytes .../0.6.11/array_by_reference.sol | 21 ++++++++++++++++++ .../0.6.11/array_by_reference.sol-0.6.11.zip | Bin 4841 -> 6086 bytes .../0.7.6/array_by_reference.sol | 21 ++++++++++++++++++ .../0.7.6/array_by_reference.sol-0.7.6.zip | Bin 4741 -> 5972 bytes 13 files changed, 124 insertions(+), 29 deletions(-) diff --git a/slither/detectors/compiler_bugs/array_by_reference.py b/slither/detectors/compiler_bugs/array_by_reference.py index 04dfe085a..47e2af581 100644 --- a/slither/detectors/compiler_bugs/array_by_reference.py +++ b/slither/detectors/compiler_bugs/array_by_reference.py @@ -133,7 +133,7 @@ As a result, Bob's usage of the contract is incorrect.""" continue # Verify one of these parameters is an array in storage. - for arg in ir.arguments: + for (param, arg) in zip(ir.function.parameters, ir.arguments): # Verify this argument is a variable that is an array type. if not isinstance(arg, (StateVariable, LocalVariable)): continue @@ -141,8 +141,11 @@ As a result, Bob's usage of the contract is incorrect.""" continue # If it is a state variable OR a local variable referencing storage, we add it to the list. - if isinstance(arg, StateVariable) or ( - isinstance(arg, LocalVariable) and arg.location == "storage" + if ( + isinstance(arg, StateVariable) + or (isinstance(arg, LocalVariable) and arg.location == "storage") + ) and ( + isinstance(param.type, ArrayType) and param.location != "storage" ): results.append((node, arg, ir.function)) return results @@ -165,9 +168,9 @@ As a result, Bob's usage of the contract is incorrect.""" calling_node.function, " passes array ", affected_argument, - "by reference to ", + " by reference to ", invoked_function, - "which only takes arrays by value\n", + " which only takes arrays by value\n", ] res = self.generate_result(info) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt index f056bea10..5cb8add39 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_4_25_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt index 4264c809a..6e97d8cc2 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_5_16_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.5.16/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt index e71930b51..39574b5f5 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_6_11_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.6.11/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt index 7c0f9ccd9..74ea36a0c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_ArrayByReference_0_7_6_array_by_reference_sol__0.txt @@ -1,12 +1,14 @@ -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value -D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +C.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#4-8) passes array C.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#2) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28)which only takes arrays by value +D.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#42-48) passes array D.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#39) by reference to C.setByValueAndReturn(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#25-28) which only takes arrays by value -C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11)by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23)which only takes arrays by value +C.g() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#10-15) passes array C.g().y (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#11) by reference to C.setByValue(uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#21-23) which only takes arrays by value + +E.f() (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#57-61) passes array E.x (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#54) by reference to E.setByValue(uint256[1],uint256[1]) (tests/e2e/detectors/test_data/array-by-reference/0.7.6/array_by_reference.sol#63-66) which only takes arrays by value diff --git a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol index 304af6a48..c2707601a 100644 --- a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol +++ b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol @@ -48,4 +48,25 @@ contract D { } +} + +contract E { + uint[1] public x; // storage + uint[1] public y; // storage + + function f() public { + uint[1] memory temp; + setByValue(temp, x); // can set temp, but cannot set x + setByRef(temp, y); // can set temp and y + } + + function setByValue(uint[1] memory arr, uint[1] memory arr2) internal { + arr[0] = 1; + arr2[0] = 2; + } + + function setByRef(uint[1] memory arr, uint[1] storage arr2) internal { + arr[0] = 2; + arr2[0] = 3; + } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol-0.4.25.zip b/tests/e2e/detectors/test_data/array-by-reference/0.4.25/array_by_reference.sol-0.4.25.zip index d9daf8f4d7dc27c4f371b018a31cc9736180c278..96bdaa0f85c484feec1e0f47ea8e3409f0cd1dc9 100644 GIT binary patch delta 5938 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 G0001;R*ZlE From b89ca1a1e05130b05832fe3696799f88f86828e9 Mon Sep 17 00:00:00 2001 From: 0xGusMcCrae <0xGusMcCrae@protonmail.com> Date: Wed, 21 Jun 2023 15:30:41 -0400 Subject: [PATCH 091/338] linting --- slither/detectors/variables/similar_variables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py index 4aef01b03..dccaf09c4 100644 --- a/slither/detectors/variables/similar_variables.py +++ b/slither/detectors/variables/similar_variables.py @@ -77,7 +77,7 @@ class SimilarVarsDetection(AbstractDetector): _v2_name_lower = v2.name.lower() if _v1_name_lower != _v2_name_lower: if SimilarVarsDetection.similar(_v1_name_lower, _v2_name_lower): - ret.add((v1, v2)) + ret.add((v1, v2)) return ret From c919cdae037ca4e7d6091235d1bdf3ee5097b804 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:55:37 +0400 Subject: [PATCH 092/338] added reachability field for node which indicates whether the node is reachable from the ENTRY_POINT --- slither/core/cfg/node.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py index 2a48bd235..475e2f138 100644 --- a/slither/core/cfg/node.py +++ b/slither/core/cfg/node.py @@ -193,6 +193,8 @@ class Node(SourceMapping): # pylint: disable=too-many-public-methods self.file_scope: "FileScope" = file_scope self._function: Optional["Function"] = None + self._is_reachable: bool = False + ################################################################################### ################################################################################### # region General's properties @@ -234,6 +236,13 @@ class Node(SourceMapping): # pylint: disable=too-many-public-methods def function(self) -> "Function": return self._function + @property + def is_reachable(self) -> bool: + return self._is_reachable + + def set_is_reachable(self, new_is_reachable: bool) -> None: + self._is_reachable = new_is_reachable + # endregion ################################################################################### ################################################################################### From 7b9024f96b12d885248b83b8faeb0edf9d326056 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:56:25 +0400 Subject: [PATCH 093/338] the reachability is updated as the last step of cfg parsing --- slither/solc_parsing/declarations/function.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 35ca51aeb..1ecfd3bf6 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1100,6 +1100,13 @@ class FunctionSolc(CallerContextExpression): node = self._parse_statement(statement, node, new_scope) return node + def _update_reachability(self, node: Node): + if node.is_reachable: + return + node.set_is_reachable(True) + for son in node.sons: + self._update_reachability(son) + def _parse_cfg(self, cfg: Dict) -> None: assert cfg[self.get_key()] == "Block" @@ -1120,6 +1127,8 @@ class FunctionSolc(CallerContextExpression): self._remove_incorrect_edges() self._remove_alone_endif() + self._update_reachability(self._function.entry_point) + # endregion ################################################################################### ################################################################################### From 49a31173ee0e08fbdf740fd571d1344ed87e61d8 Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 16:58:55 +0400 Subject: [PATCH 094/338] now we intersect only reachable fathers' dominators --- slither/core/dominators/utils.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 4dd55749d..463eac4b7 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -9,11 +9,17 @@ if TYPE_CHECKING: def intersection_predecessor(node: "Node") -> Set["Node"]: if not node.fathers: return set() - ret = node.fathers[0].dominators - for pred in node.fathers[1:]: - ret = ret.intersection(pred.dominators) - return ret + if not any(father.is_reachable for father in node.fathers): + return set() + ret = set() + for pred in node.fathers: + ret = ret.union(pred.dominators) + + for pred in node.fathers: + if pred.is_reachable: + ret = ret.intersection(pred.dominators) + return ret def _compute_dominators(nodes: List["Node"]) -> None: changed = True @@ -84,6 +90,8 @@ def compute_dominance_frontier(nodes: List["Node"]) -> None: for node in nodes: if len(node.fathers) >= 2: for father in node.fathers: + if not father.is_reachable: + continue runner = father # Corner case: if there is a if without else # we need to add update the conditional node From d75d8d8d8e411515944989ea09c235386d66d30d Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Thu, 22 Jun 2023 17:03:48 +0400 Subject: [PATCH 095/338] changed by black --- slither/core/dominators/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 463eac4b7..77ff22611 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -21,6 +21,7 @@ def intersection_predecessor(node: "Node") -> Set["Node"]: ret = ret.intersection(pred.dominators) return ret + def _compute_dominators(nodes: List["Node"]) -> None: changed = True From a6fb92f17962cb8811782921163561b94cb7a6bd Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:19:31 +0200 Subject: [PATCH 096/338] Bound function search to first parameter type --- slither/solc_parsing/declarations/using_for_top_level.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/using_for_top_level.py b/slither/solc_parsing/declarations/using_for_top_level.py index 8ac5b4462..3b7bb280c 100644 --- a/slither/solc_parsing/declarations/using_for_top_level.py +++ b/slither/solc_parsing/declarations/using_for_top_level.py @@ -112,7 +112,12 @@ class UsingForTopLevelSolc(CallerContextExpression): # pylint: disable=too-few- self, operator: str, function_name: str, type_name: TypeAliasTopLevel ) -> None: for tl_function in self.compilation_unit.functions_top_level: - if tl_function.name == function_name: + # The library function is bound to the first parameter's type + if ( + tl_function.name == function_name + and tl_function.parameters + and type_name == tl_function.parameters[0].type + ): type_name.operators[operator] = tl_function break From 3f1db7af7799da2172b9b8e93b839131602ec91c Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:21:03 +0200 Subject: [PATCH 097/338] Look for library functions in the current scope --- slither/solc_parsing/declarations/using_for_top_level.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/using_for_top_level.py b/slither/solc_parsing/declarations/using_for_top_level.py index 3b7bb280c..fe72e5780 100644 --- a/slither/solc_parsing/declarations/using_for_top_level.py +++ b/slither/solc_parsing/declarations/using_for_top_level.py @@ -111,7 +111,7 @@ class UsingForTopLevelSolc(CallerContextExpression): # pylint: disable=too-few- def _analyze_operator( self, operator: str, function_name: str, type_name: TypeAliasTopLevel ) -> None: - for tl_function in self.compilation_unit.functions_top_level: + for tl_function in self._using_for.file_scope.functions: # The library function is bound to the first parameter's type if ( tl_function.name == function_name From f2accfd77d3d256be0e300c376abdbb7fc2443b9 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:32:26 +0200 Subject: [PATCH 098/338] Add test --- tests/e2e/solc_parsing/test_ast_parsing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index b694d1044..307e6736f 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -458,6 +458,7 @@ ALL_TESTS = [ "assembly-functions.sol", ["0.6.9", "0.7.6", "0.8.16"], ), + Test("user_defined_operators-0.8.19.sol", ["0.8.19"]), ] # create the output folder if needed try: From ace672e27d1e97375cc7359b1f7a05d240a6ca6d Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:41:29 +0200 Subject: [PATCH 099/338] Rename tests to run to ALL_TESTS --- tests/e2e/detectors/test_detectors.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py index d003e7ce0..a34f1932e 100644 --- a/tests/e2e/detectors/test_detectors.py +++ b/tests/e2e/detectors/test_detectors.py @@ -56,7 +56,7 @@ def id_test(test_item: Test): return f"{test_item.detector.__name__}-{test_item.solc_ver}-{test_item.test_file}" -ALL_TEST_OBJECTS = [ +ALL_TESTS = [ Test( all_detectors.UninitializedFunctionPtrsConstructor, "uninitialized_function_ptr_constructor.sol", @@ -1656,7 +1656,7 @@ GENERIC_PATH = "/GENERIC_PATH" TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" # pylint: disable=too-many-locals -@pytest.mark.parametrize("test_item", ALL_TEST_OBJECTS, ids=id_test) +@pytest.mark.parametrize("test_item", ALL_TESTS, ids=id_test) def test_detector(test_item: Test, snapshot): test_dir_path = Path( TEST_DATA_DIR, @@ -1704,5 +1704,5 @@ if __name__ == "__main__": "To generate the zip artifacts run\n\tpython tests/e2e/tests/test_detectors.py --compile" ) elif sys.argv[1] == "--compile": - for next_test in ALL_TEST_OBJECTS: + for next_test in ALL_TESTS: _generate_compile(next_test, skip_existing=True) From 940a0a17d911af07dc2994dc224cdc1fc034973d Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:42:49 +0200 Subject: [PATCH 100/338] Update CONTRIBUTING.md --- CONTRIBUTING.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c00fda8aa..0ebaa8d05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,7 @@ For each new detector, at least one regression tests must be present. 1. Create a folder in `tests/e2e/detectors/test_data` with the detector's argument name. 2. Create a test contract in `tests/e2e/detectors/test_data//`. -3. Update `ALL_TEST` in `tests/e2e/detectors/test_detectors.py` +3. Update `ALL_TESTS` in `tests/e2e/detectors/test_detectors.py` 4. Run `python tests/e2e/detectors/test_detectors.py --compile` to create a zip file of the compilation artifacts. 5. `pytest tests/e2e/detectors/test_detectors.py --insta update-new`. This will generate a snapshot of the detector output in `tests/e2e/detectors/snapshots/`. If updating an existing detector, run `pytest tests/e2e/detectors/test_detectors.py --insta review` and accept or reject the updates. 6. Run `pytest tests/e2e/detectors/test_detectors.py` to ensure everything worked. Then, add and commit the files to git. @@ -97,8 +97,9 @@ For each new detector, at least one regression tests must be present. 1. Create a test in `tests/e2e/solc_parsing/` 2. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git. -3. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/e2e/solc_parsing/expected_json`. Add the generated files to git. -4. Run `pytest tests/e2e/solc_parsing/test_ast_parsing.py` and check that everything worked. +3. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py` +4. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/e2e/solc_parsing/expected_json`. Add the generated files to git. +5. Run `pytest tests/e2e/solc_parsing/test_ast_parsing.py` and check that everything worked. > ##### Helpful commands for parsing tests > From e1fd6702f9bb41a16e664c3bcad340cbc3046e6c Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 23 Jun 2023 09:48:08 +0200 Subject: [PATCH 101/338] Minor --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ebaa8d05..5cf02136b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,7 +81,7 @@ For each new detector, at least one regression tests must be present. 1. Create a folder in `tests/e2e/detectors/test_data` with the detector's argument name. 2. Create a test contract in `tests/e2e/detectors/test_data//`. -3. Update `ALL_TESTS` in `tests/e2e/detectors/test_detectors.py` +3. Update `ALL_TESTS` in `tests/e2e/detectors/test_detectors.py`. 4. Run `python tests/e2e/detectors/test_detectors.py --compile` to create a zip file of the compilation artifacts. 5. `pytest tests/e2e/detectors/test_detectors.py --insta update-new`. This will generate a snapshot of the detector output in `tests/e2e/detectors/snapshots/`. If updating an existing detector, run `pytest tests/e2e/detectors/test_detectors.py --insta review` and accept or reject the updates. 6. Run `pytest tests/e2e/detectors/test_detectors.py` to ensure everything worked. Then, add and commit the files to git. @@ -97,7 +97,7 @@ For each new detector, at least one regression tests must be present. 1. Create a test in `tests/e2e/solc_parsing/` 2. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git. -3. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py` +3. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py`. 4. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/e2e/solc_parsing/expected_json`. Add the generated files to git. 5. Run `pytest tests/e2e/solc_parsing/test_ast_parsing.py` and check that everything worked. From 8b0fd32cbe32b6e873bccc07de5231f8793e1686 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 23 Jun 2023 09:33:05 -0500 Subject: [PATCH 102/338] use enum instead of value in config, lint --- slither/__main__.py | 1 - slither/utils/command_line.py | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 4fcfd896d..d9201a90d 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -36,7 +36,6 @@ from slither.utils.output_capture import StandardOutputCapture from slither.utils.colors import red, set_colorization_enabled from slither.utils.command_line import ( FailOnLevel, - migrate_config_options, output_detectors, output_results_to_markdown, output_detectors_json, diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 8518ada4a..082472582 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -54,7 +54,7 @@ defaults_flag_in_config = { "exclude_low": False, "exclude_medium": False, "exclude_high": False, - "fail_on": FailOnLevel.PEDANTIC.value, + "fail_on": FailOnLevel.PEDANTIC, "json": None, "sarif": None, "json-types": ",".join(DEFAULT_JSON_OUTPUT_TYPES), @@ -118,22 +118,22 @@ def migrate_config_options(args: argparse.Namespace, key: str, elem): if key.startswith("fail_") and getattr(args, "fail_on") == defaults_flag_in_config["fail_on"]: if key == "fail_pedantic": pedantic_setting = elem - fail_on = pedantic_setting and FailOnLevel.PEDANTIC or FailOnLevel.NONE + fail_on = FailOnLevel.PEDANTIC if pedantic_setting else FailOnLevel.NONE setattr(args, "fail_on", fail_on) - logger.info( - "Migrating fail_pedantic: {} as fail_on: {}".format(pedantic_setting, fail_on.value) - ) - elif key == "fail_low" and elem == True: + logger.info(f"Migrating fail_pedantic: {pedantic_setting} as fail_on: {fail_on.value}") + elif key == "fail_low" and elem is True: logger.info("Migrating fail_low: true -> fail_on: low") setattr(args, "fail_on", FailOnLevel.LOW) - elif key == "fail_medium" and elem == True: + + elif key == "fail_medium" and elem is True: logger.info("Migrating fail_medium: true -> fail_on: medium") setattr(args, "fail_on", FailOnLevel.MEDIUM) - elif key == "fail_high" and elem == True: + + elif key == "fail_high" and elem is True: logger.info("Migrating fail_high: true -> fail_on: high") setattr(args, "fail_on", FailOnLevel.HIGH) else: - logger.warn(yellow("Key {} was deprecated but no migration was provided".format(key))) + logger.warning(yellow(f"Key {key} was deprecated but no migration was provided")) def output_to_markdown( From 0e86f3d3045fd3669e19824ff950b160438c26c1 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 23 Jun 2023 11:23:22 -0500 Subject: [PATCH 103/338] 0.9.4 --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 70d4f71fd..798d43936 100644 --- a/setup.py +++ b/setup.py @@ -8,15 +8,15 @@ setup( description="Slither is a Solidity static analysis framework written in Python 3.", url="https://github.com/crytic/slither", author="Trail of Bits", - version="0.9.3", + version="0.9.4", packages=find_packages(), python_requires=">=3.8", install_requires=[ "packaging", "prettytable>=3.3.0", "pycryptodome>=3.4.6", - # "crytic-compile>=0.3.1,<0.4.0", - "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile", + "crytic-compile>=0.3.2,<0.4.0", + # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile", "web3>=6.0.0", "eth-abi>=4.0.0", "eth-typing>=3.0.0", From 14824e86485c4d7b63da7ef13b5ffa60485d56d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 16:32:15 +0000 Subject: [PATCH 104/338] Bump cachix/cachix-action from 10 to 12 Bumps [cachix/cachix-action](https://github.com/cachix/cachix-action) from 10 to 12. - [Release notes](https://github.com/cachix/cachix-action/releases) - [Commits](https://github.com/cachix/cachix-action/compare/v10...v12) --- updated-dependencies: - dependency-name: cachix/cachix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09582eed9..164aa5ba7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: - name: Set up cachix if: matrix.type == 'dapp' - uses: cachix/cachix-action@v10 + uses: cachix/cachix-action@v12 with: name: dapp From eec0c7ddce8dba70abf78e77a806d819573b7c8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 16:32:18 +0000 Subject: [PATCH 105/338] Bump cachix/install-nix-action from 20 to 22 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 20 to 22. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v20...v22) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09582eed9..ba5326f67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v20 + uses: cachix/install-nix-action@v22 - name: Set up cachix if: matrix.type == 'dapp' From 3ed6f283d0bb592e21394779e7cea36ff1d51aa5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 16:32:25 +0000 Subject: [PATCH 106/338] Bump actions/deploy-pages from 1 to 2 Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 1 to 2. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v1...v2) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 20676e031..f6d66aa0a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,4 +43,4 @@ jobs: path: './html/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v2 From c73ac8932a0cafd2f660b24a3f76189b960343e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 16:32:29 +0000 Subject: [PATCH 107/338] Bump docker/build-push-action from 3 to 4 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 4. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7e6f88f1e..4cb1adcb1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Docker Build and Push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: platforms: linux/amd64,linux/arm64/v8,linux/arm/v7 target: final From 272c80182799cc9303b7f4185c191d7721e97dd7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 23 Jun 2023 16:19:14 -0500 Subject: [PATCH 108/338] update readme's --- README.md | 210 ++++++++++++++------------- slither/tools/interface/README.md | 21 +++ slither/tools/interface/__main__.py | 9 +- slither/tools/read_storage/README.md | 33 +++-- 4 files changed, 159 insertions(+), 114 deletions(-) create mode 100644 slither/tools/interface/README.md diff --git a/README.md b/README.md index bce20bfb0..503f99f00 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Slither, the Solidity source analyzer + Logo [![Build Status](https://img.shields.io/github/actions/workflow/status/crytic/slither/ci.yml?branch=master)](https://github.com/crytic/slither/actions?query=workflow%3ACI) @@ -20,26 +21,29 @@ Slither is a Solidity static analysis framework written in Python3. It runs a su ## Features -* Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md)) -* Identifies where the error condition occurs in the source code -* Easily integrates into continuous integration and Hardhat/Foundry builds -* Built-in 'printers' quickly report crucial contract information -* Detector API to write custom analyses in Python -* Ability to analyze contracts written with Solidity >= 0.4 -* Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses -* Correctly parses 99.9% of all public Solidity code -* Average execution time of less than 1 second per contract -* Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) +- Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md)) +- Identifies where the error condition occurs in the source code +- Easily integrates into continuous integration and Hardhat/Foundry builds +- Built-in 'printers' quickly report crucial contract information +- Detector API to write custom analyses in Python +- Ability to analyze contracts written with Solidity >= 0.4 +- Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses +- Correctly parses 99.9% of all public Solidity code +- Average execution time of less than 1 second per contract +- Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) ## Usage Run Slither on a Hardhat/Foundry/Dapp/Brownie application: + ```bash slither . ``` + This is the preferred option if your project has dependencies as Slither relies on the underlying compilation framework to compile source code. However, you can run Slither on a single file that does not import dependencies: + ```bash slither tests/uninitialized.sol ``` @@ -79,118 +83,122 @@ docker run -it -v /home/share:/share trailofbits/eth-security-toolbox ``` ### Integration + - For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action). - To generate a Markdown report, use `slither [target] --checklist`. - To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`) ## Detectors - Num | Detector | What it Detects | Impact | Confidence --- | --- | --- | --- | --- 1 | `abiencoderv2-array` | [Storage abiencoderv2 array](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array) | High | High 2 | `arbitrary-send-erc20` | [transferFrom uses arbitrary `from`](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom) | High | High 3 | `array-by-reference` | [Modifying storage array by value](https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value) | High | High -4 | `incorrect-shift` | [The order of parameters in a shift instruction is incorrect.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) | High | High -5 | `multiple-constructors` | [Multiple constructor schemes](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) | High | High -6 | `name-reused` | [Contract's name reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) | High | High -7 | `protected-vars` | [Detected unprotected variables](https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables) | High | High -8 | `public-mappings-nested` | [Public mappings with nested variables](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) | High | High -9 | `rtlo` | [Right-To-Left-Override control character is used](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) | High | High -10 | `shadowing-state` | [State variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) | High | High -11 | `suicidal` | [Functions allowing anyone to destruct the contract](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) | High | High -12 | `uninitialized-state` | [Uninitialized state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) | High | High -13 | `uninitialized-storage` | [Uninitialized storage variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) | High | High -14 | `unprotected-upgrade` | [Unprotected upgradeable contract](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) | High | High -15 | `codex` | [Use Codex to find vulnerabilities.](https://github.com/crytic/slither/wiki/Detector-Documentation#codex) | High | Low -16 | `arbitrary-send-erc20-permit` | [transferFrom uses arbitrary from with permit](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit) | High | Medium -17 | `arbitrary-send-eth` | [Functions that send Ether to arbitrary destinations](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) | High | Medium -18 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium -19 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium -20 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium -21 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium -22 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium -23 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium -24 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium -25 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium -26 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High -27 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High -28 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High -29 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High -30 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High -31 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High -32 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High -33 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High -34 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High -35 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High -36 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium -37 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium -38 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium -39 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium -40 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium -41 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium -42 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium -43 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium -44 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium -45 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium -46 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium -47 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High -48 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High -49 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High -50 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High -51 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High -52 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High -53 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium -54 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium -55 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium -56 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium -57 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium -58 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium -59 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium -60 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium -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 | `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 +4 | `encode-packed-collision` | [ABI encodePacked Collision](https://github.com/crytic/slither/wiki/Detector-Documentation#abi-encodePacked-collision) | High | High +5 | `incorrect-shift` | [The order of parameters in a shift instruction is incorrect.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) | High | High +6 | `multiple-constructors` | [Multiple constructor schemes](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) | High | High +7 | `name-reused` | [Contract's name reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) | High | High +8 | `protected-vars` | [Detected unprotected variables](https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables) | High | High +9 | `public-mappings-nested` | [Public mappings with nested variables](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) | High | High +10 | `rtlo` | [Right-To-Left-Override control character is used](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) | High | High +11 | `shadowing-state` | [State variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) | High | High +12 | `suicidal` | [Functions allowing anyone to destruct the contract](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) | High | High +13 | `uninitialized-state` | [Uninitialized state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) | High | High +14 | `uninitialized-storage` | [Uninitialized storage variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) | High | High +15 | `unprotected-upgrade` | [Unprotected upgradeable contract](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) | High | High +16 | `codex` | [Use Codex to find vulnerabilities.](https://github.com/crytic/slither/wiki/Detector-Documentation#codex) | High | Low +17 | `arbitrary-send-erc20-permit` | [transferFrom uses arbitrary from with permit](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit) | High | Medium +18 | `arbitrary-send-eth` | [Functions that send Ether to arbitrary destinations](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) | High | Medium +19 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium +20 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium +21 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium +22 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium +23 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium +24 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium +25 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium +26 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium +27 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High +28 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High +29 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High +30 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High +31 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High +32 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High +33 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High +34 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High +35 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High +36 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High +37 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium +38 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium +39 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium +40 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium +41 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium +42 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium +43 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium +44 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium +45 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium +46 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium +47 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium +48 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High +49 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High +50 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High +51 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High +52 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High +53 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High +54 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium +55 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium +56 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium +57 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium +58 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium +59 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium +60 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium +61 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium +62 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High +63 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High +64 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High +65 | `cyclomatic-complexity` | [Detects functions with high (> 11) cyclomatic complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) | Informational | High +66 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High +67 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High +68 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High +69 | `incorrect-using-for` | [Detects using-for statement usage when no function from a given library matches a given type](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-using-for-usage) | Informational | High +70 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High +71 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High +72 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High +73 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High +74 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High +75 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High +76 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High +77 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High +78 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium +79 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium +80 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium +81 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium +82 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium +83 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it.](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High +84 | `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 +85 | `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 +86 | `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 +87 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Detector-Documentation#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 - The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run. - The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results ## Printers - ### Quick Review Printers - `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary) - `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) - `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary) +15 | `loc` | [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) ### In-Depth Review Printers - `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph) - `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg) - `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) - `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization) -- `when-not-paused`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused). +- `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused). To run a printer, use `--print` and a comma-separated list of printers. @@ -204,32 +212,36 @@ See the [Printer documentation](https://github.com/crytic/slither/wiki/Printer-d - `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance) - `slither-format`: [Automatic patch generation](https://github.com/crytic/slither/wiki/Slither-format) - `slither-read-storage`: [Read storage values from contracts](./slither/tools/read_storage/README.md) +- `slither-interface`: [Generate an interface for a contract](./slither/tools/interface/README.md) See the [Tool documentation](https://github.com/crytic/slither/wiki/Tool-Documentation) for additional tools. [Contact us](https://www.trailofbits.com/contact/) to get help on building custom tools. ## API Documentation + Documentation on Slither's internals is available [here](https://crytic.github.io/slither/slither.html). ## Getting Help Feel free to stop by our [Slack channel](https://empireslacking.herokuapp.com) (#ethereum) for help using or extending Slither. -* The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract. +- The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract. -* The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses. +- The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses. -* The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses. +- The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses. -* The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation. +- The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation. ## FAQ How do I exclude mocks or tests? + - View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering). How do I fix "unknown file" or compilation issues? + - Because slither requires the solc AST, it must have all dependencies available. If a contract has dependencies, `slither contract.sol` will fail. Instead, use `slither .` in the parent directory of `contracts/` (you should see `contracts/` when you run `ls`). @@ -244,9 +256,11 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt ## Publications ### Trail of Bits publication + - [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 --- | --- | --- | --- | --- [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 diff --git a/slither/tools/interface/README.md b/slither/tools/interface/README.md new file mode 100644 index 000000000..a77e780b0 --- /dev/null +++ b/slither/tools/interface/README.md @@ -0,0 +1,21 @@ +# Slither-interface + +Generates code for a Solidity interface from contract + +## Usage + +Run `slither-interface `. + +## CLI Interface +```shell +positional arguments: + contract_source The name of the contract (case sensitive) followed by the deployed contract address if verified on etherscan or project directory/filename for local contracts. + +optional arguments: + -h, --help show this help message and exit + --unroll-structs Whether to use structures' underlying types instead of the user-defined type + --exclude-events Excludes event signatures in the interface + --exclude-errors Excludes custom error signatures in the interface + --exclude-enums Excludes enum definitions in the interface + --exclude-structs Exclude struct definitions in the interface +``` \ No newline at end of file diff --git a/slither/tools/interface/__main__.py b/slither/tools/interface/__main__.py index e56c4b3eb..0705f0373 100644 --- a/slither/tools/interface/__main__.py +++ b/slither/tools/interface/__main__.py @@ -86,10 +86,11 @@ def main() -> None: ) # add version pragma - interface = ( - f"pragma solidity {_contract.compilation_unit.pragma_directives[0].version};\n\n" - + interface - ) + if _contract.compilation_unit.pragma_directives: + interface = ( + f"pragma solidity {_contract.compilation_unit.pragma_directives[0].version};\n\n" + + interface + ) # write interface to file export = Path("crytic-export", "interfaces") diff --git a/slither/tools/read_storage/README.md b/slither/tools/read_storage/README.md index 677b2c772..dd7ef2865 100644 --- a/slither/tools/read_storage/README.md +++ b/slither/tools/read_storage/README.md @@ -8,20 +8,29 @@ Slither-read-storage is a tool to retrieve the storage slots and values of entir ```shell positional arguments: - contract_source (DIR) ADDRESS The deployed contract address if verified on etherscan. Prepend project directory for unverified contracts. + contract_source The deployed contract address if verified on etherscan. Prepend project directory for unverified contracts. optional arguments: - --variable-name VARIABLE_NAME The name of the variable whose value will be returned. - --rpc-url RPC_URL An endpoint for web3 requests. - --key KEY The key/ index whose value will be returned from a mapping or array. - --deep-key DEEP_KEY The key/ index whose value will be returned from a deep mapping or multidimensional array. - --struct-var STRUCT_VAR The name of the variable whose value will be returned from a struct. - --storage-address STORAGE_ADDRESS The address of the storage contract (if a proxy pattern is used). - --contract-name CONTRACT_NAME The name of the logic contract. - --json FILE Write the entire storage layout in JSON format to the specified FILE - --value Toggle used to include values in output. - --max-depth MAX_DEPTH Max depth to search in data structure. - --block BLOCK_NUMBER Block number to retrieve storage from (requires archive rpc node) + -h, --help show this help message and exit + --variable-name VARIABLE_NAME + The name of the variable whose value will be returned. + --rpc-url RPC_URL An endpoint for web3 requests. + --key KEY The key/ index whose value will be returned from a mapping or array. + --deep-key DEEP_KEY The key/ index whose value will be returned from a deep mapping or multidimensional array. + --struct-var STRUCT_VAR + The name of the variable whose value will be returned from a struct. + --storage-address STORAGE_ADDRESS + The address of the storage contract (if a proxy pattern is used). + --contract-name CONTRACT_NAME + The name of the logic contract. + --json JSON Save the result in a JSON file. + --value Toggle used to include values in output. + --table Print table view of storage layout + --silent Silence log outputs + --max-depth MAX_DEPTH + Max depth to search in data structure. + --block BLOCK The block number to read storage from. Requires an archive node to be provided as the RPC url. + --unstructured Include unstructured storage slots ``` ### Examples From b6d1de43ca9abd1e9ed5e64da4cd6133fb240208 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 23 Jun 2023 16:31:26 -0500 Subject: [PATCH 109/338] fix bullet point --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 503f99f00..17fdb02b5 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ For more information, see - `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary) - `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) - `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary) -15 | `loc` | [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) +- `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) ### In-Depth Review Printers - `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph) From 273cca4167ab0f057252c754a629e8d81af992c6 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sat, 24 Jun 2023 10:50:11 -0500 Subject: [PATCH 110/338] fix logo on pypi (#1999) PyPI needs a link to properly render the logo xref https://github.com/pypi/warehouse/issues/5246 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 17fdb02b5..cb815561e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Slither, the Solidity source analyzer -Logo +Logo [![Build Status](https://img.shields.io/github/actions/workflow/status/crytic/slither/ci.yml?branch=master)](https://github.com/crytic/slither/actions?query=workflow%3ACI) [![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com) From 6e156718d3d9594b738d10565daf3cfb83277a4f Mon Sep 17 00:00:00 2001 From: "t.avagyan" Date: Mon, 26 Jun 2023 09:17:17 +0400 Subject: [PATCH 111/338] fixed dfs --- slither/solc_parsing/declarations/function.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 1ecfd3bf6..3df121e8f 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -315,6 +315,8 @@ class FunctionSolc(CallerContextExpression): self._remove_alone_endif() + self._update_reachability(self._function.entry_point) + # endregion ################################################################################### ################################################################################### @@ -1127,8 +1129,6 @@ class FunctionSolc(CallerContextExpression): self._remove_incorrect_edges() self._remove_alone_endif() - self._update_reachability(self._function.entry_point) - # endregion ################################################################################### ################################################################################### From cee0c6bd73c004208a86ed1880edc3757bb0227d Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Mon, 26 Jun 2023 09:30:43 +0400 Subject: [PATCH 112/338] added nullcheck for functions not having entry point (non implemented functions) --- slither/solc_parsing/declarations/function.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 3df121e8f..b3821388b 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -315,7 +315,8 @@ class FunctionSolc(CallerContextExpression): self._remove_alone_endif() - self._update_reachability(self._function.entry_point) + if self._function.entry_point: + self._update_reachability(self._function.entry_point) # endregion ################################################################################### From 6cb36a2efdf820ca143f9c371b274659271a9889 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 26 Jun 2023 13:23:53 -0500 Subject: [PATCH 113/338] use published release of solc-select --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 798d43936..9695a8fc0 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ setup( "coverage[toml]", "filelock", "pytest-insta", - "solc-select@git+https://github.com/crytic/solc-select.git@query-artifact-path#egg=solc-select", + "solc-select>=1.0.4", ], "doc": [ "pdoc", From cbe6716afde4696bc1c31dec36332db47cd89f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 26 Jun 2023 18:53:43 -0300 Subject: [PATCH 114/338] Fix execution in Python 3.11 This fixes the following error: ValueError: mutable default for field src is not allowed: use default_factory --- slither/utils/loc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/utils/loc.py b/slither/utils/loc.py index 0e51dfa46..dde91578b 100644 --- a/slither/utils/loc.py +++ b/slither/utils/loc.py @@ -1,4 +1,4 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field from pathlib import Path from typing import List, Tuple @@ -19,9 +19,9 @@ class LoCInfo: @dataclass class LoC: - src: LoCInfo = LoCInfo() - dep: LoCInfo = LoCInfo() - test: LoCInfo = LoCInfo() + src: LoCInfo = field(default_factory=LoCInfo) + dep: LoCInfo = field(default_factory=LoCInfo) + test: LoCInfo = field(default_factory=LoCInfo) def to_pretty_table(self) -> MyPrettyTable: table = MyPrettyTable(["", "src", "dep", "test"]) From fa5963239efe4022d307fb290e899dd0f19866c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 26 Jun 2023 19:00:14 -0300 Subject: [PATCH 115/338] workflows: ci: run on Python 3.8 ~ 3.11 --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09582eed9..fcad34341 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,7 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest", "windows-2022"] + python: ["3.8", "3.9", "3.10", "3.11"] type: ["cli", "dapp", "data_dependency", @@ -53,10 +54,10 @@ jobs: type: truffle steps: - uses: actions/checkout@v3 - - name: Set up Python 3.8 + - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: ${{ matrix.python }} - name: Install dependencies run: | pip install ".[test]" From af5e801973ec8a040f53b0cd453b949e659f6234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 26 Jun 2023 19:02:19 -0300 Subject: [PATCH 116/338] workflows: test: run on Python 3.8 ~ 3.11 --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a003eb168..e4de97197 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,12 +25,13 @@ jobs: matrix: os: ["ubuntu-latest", "windows-2022"] type: ["unit", "integration", "tool"] + python: ["3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 - - name: Set up Python 3.8 + - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: ${{ matrix.python }} cache: "pip" cache-dependency-path: setup.py @@ -74,7 +75,7 @@ jobs: uses: ./.github/actions/upload-coverage # only aggregate test coverage over linux-based tests to avoid any OS-specific filesystem information stored in # coverage metadata. - if: ${{ matrix.os == 'ubuntu-latest' }} + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.8' }} coverage: needs: From 98480090dba6e4595c61a1dcb9d05f75b28fefbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Mon, 26 Jun 2023 19:14:35 -0300 Subject: [PATCH 117/338] workflows: ci, tests: only run on 3.8 and 3.11 for PRs This keeps CI jobs reasonable in PRs while testing the full set of versions in the scheduled jobs and merges to dev and master. --- .github/workflows/ci.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fcad34341..76438ec73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest", "windows-2022"] - python: ["3.8", "3.9", "3.10", "3.11"] + python: ${{ (github.event_name == 'pull_request' && fromJSON('["3.8", "3.11"]')) || fromJSON('["3.8", "3.9", "3.10", "3.11"]') }} type: ["cli", "dapp", "data_dependency", diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e4de97197..b3754bfd7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: matrix: os: ["ubuntu-latest", "windows-2022"] type: ["unit", "integration", "tool"] - python: ["3.8", "3.9", "3.10", "3.11"] + python: ${{ (github.event_name == 'pull_request' && fromJSON('["3.8", "3.11"]')) || fromJSON('["3.8", "3.9", "3.10", "3.11"]') }} steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python }} From 1f40e9269b0c3dc23d45ad2ee8e86237d266c4f9 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 27 Jun 2023 08:20:54 -0500 Subject: [PATCH 118/338] 0.9.5 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9695a8fc0..e7019b1aa 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setup( description="Slither is a Solidity static analysis framework written in Python 3.", url="https://github.com/crytic/slither", author="Trail of Bits", - version="0.9.4", + version="0.9.5", packages=find_packages(), python_requires=">=3.8", install_requires=[ From 5c40c52ba1caae8e2de12b0742247248333e6007 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sat, 1 Jul 2023 13:42:54 -0500 Subject: [PATCH 119/338] fix(cache-array-length): handle when `HighLevelCall` is a `StateVariable` --- .../operations/cache_array_length.py | 25 +++++++++++------- ...yLength_0_8_17_CacheArrayLength_sol__0.txt | 20 +++++++------- .../0.8.17/CacheArrayLength.sol | 6 +++++ .../0.8.17/CacheArrayLength.sol-0.8.17.zip | Bin 8898 -> 9536 bytes 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py index da73d3fd5..e4d8cf2c6 100644 --- a/slither/detectors/operations/cache_array_length.py +++ b/slither/detectors/operations/cache_array_length.py @@ -4,7 +4,6 @@ from slither.core.cfg.node import Node, NodeType from slither.core.declarations import Function from slither.core.expressions import BinaryOperation, Identifier, MemberAccess, UnaryOperation from slither.core.solidity_types import ArrayType -from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables import StateVariable from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.slithir.operations import Length, Delete, HighLevelCall @@ -134,7 +133,12 @@ contract C and op.expression.expression.value == array ): return True - if isinstance(op, HighLevelCall) and not op.function.view and not op.function.pure: + if ( + isinstance(op, HighLevelCall) + and isinstance(op.function, Function) + and not op.function.view + and not op.function.pure + ): return True for son in node.sons: @@ -144,7 +148,7 @@ contract C return False @staticmethod - def _handle_loops(nodes: List[Node], non_optimal_array_len_usages: List[SourceMapping]) -> None: + def _handle_loops(nodes: List[Node], non_optimal_array_len_usages: List[Node]) -> None: """ For each loop, checks if it has a comparison with `length` array member and, if it has, checks whether that array size could potentially change in that loop. @@ -180,21 +184,21 @@ contract C non_optimal_array_len_usages.append(if_node) @staticmethod - def _get_non_optimal_array_len_usages_for_function(f: Function) -> List[SourceMapping]: + def _get_non_optimal_array_len_usages_for_function(f: Function) -> List[Node]: """ Finds non-optimal usages of array length in loop conditions in a given function. """ - non_optimal_array_len_usages: List[SourceMapping] = [] + non_optimal_array_len_usages: List[Node] = [] CacheArrayLength._handle_loops(f.nodes, non_optimal_array_len_usages) return non_optimal_array_len_usages @staticmethod - def _get_non_optimal_array_len_usages(functions: List[Function]) -> List[SourceMapping]: + def _get_non_optimal_array_len_usages(functions: List[Function]) -> List[Node]: """ Finds non-optimal usages of array length in loop conditions in given functions. """ - non_optimal_array_len_usages: List[SourceMapping] = [] + non_optimal_array_len_usages: List[Node] = [] for f in functions: non_optimal_array_len_usages += ( @@ -211,9 +215,10 @@ contract C ) for usage in non_optimal_array_len_usages: info = [ - "Loop condition at ", - usage, - " should use cached array length instead of referencing `length` member " + "Loop condition ", + f"`{usage.source_mapping.content}` ", + f"({usage.source_mapping}) ", + "should use cached array length instead of referencing `length` member " "of the storage array.\n ", ] res = self.generate_result(info) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt index 63d4b883c..456c702a5 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt @@ -1,18 +1,20 @@ -Loop condition at i < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#36) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#109) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at i_scope_22 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#166) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#161) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at j_scope_11 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#108) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#172) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at i_scope_6 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#79) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#126) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at i_scope_21 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#160) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#133) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at k_scope_9 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#98) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#68) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at k_scope_17 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#132) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#99) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at j_scope_15 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#125) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#167) should use cached array length instead of referencing `length` member of the storage array. -Loop condition at i_scope_4 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#67) should use cached array length instead of referencing `length` member of the storage array. +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#37) should use cached array length instead of referencing `length` member of the storage array. + +Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#80) should use cached array length instead of referencing `length` member of the storage array. diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol index 704d6bed9..ea3c4120e 100644 --- a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol +++ b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol @@ -9,6 +9,7 @@ contract CacheArrayLength S[] array; S[] array2; + uint public x; function h() external { @@ -167,5 +168,10 @@ contract CacheArrayLength { this.h_view(); } + // array not modified and it cannot be changed in a function call since x is a public state variable + for (uint i = 0; i < array.length; i++) // warning should appear + { + this.x(); + } } } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip b/tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol-0.8.17.zip index dafdfc43167f9eb622fed98bdc69e91d02f89dfa..c5cb9f283c8f9b19a05070afca2c3bc14cd981fd 100644 GIT binary patch delta 9472 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 S007AQlW-zT2Gk?~0002!U~$j@ delta 8829 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 From e0233a70efe4b12f16458a9a648dbd65a1b61126 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:23:19 +0000 Subject: [PATCH 120/338] Bump actions/setup-python from 3 to 4 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/black.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/linter.yml | 2 +- .github/workflows/pylint.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index df51a3ddf..33a1666b2 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d99aa49fc..b59aacd66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} - name: Install dependencies diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index f972cbcd1..b352a8301 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -33,7 +33,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.8 diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 983c176a9..207f98eac 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -27,7 +27,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.8 From f22836c5f06a96b37b92c50dd1b32e8c05cac110 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:23:24 +0000 Subject: [PATCH 121/338] Bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.6 to 1.8.7. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.6...v1.8.7) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 529752f80..f7d9ff9e7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: path: dist/ - name: publish - uses: pypa/gh-action-pypi-publish@v1.8.6 + uses: pypa/gh-action-pypi-publish@v1.8.7 - name: sign uses: sigstore/gh-action-sigstore-python@v1.2.3 From 9ecc66ddf81cb4e0bfe19dd53197c25634467401 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 5 Jul 2023 21:59:17 -0500 Subject: [PATCH 122/338] fix regression that caused retdata to be flagged --- .../unchecked_low_level_return_values.py | 62 ++++++++++++++++-- .../operations/unused_return_values.py | 6 +- .../0.7.6/unchecked_lowlevel.sol | 8 ++- .../0.7.6/unchecked_lowlevel.sol-0.7.6.zip | Bin 2436 -> 2753 bytes 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/slither/detectors/operations/unchecked_low_level_return_values.py b/slither/detectors/operations/unchecked_low_level_return_values.py index 0537ebbf2..c1fb1a868 100644 --- a/slither/detectors/operations/unchecked_low_level_return_values.py +++ b/slither/detectors/operations/unchecked_low_level_return_values.py @@ -1,15 +1,24 @@ """ Module detecting unused return values from low level """ -from slither.detectors.abstract_detector import DetectorClassification -from slither.detectors.operations.unused_return_values import UnusedReturnValues +from typing import List + +from slither.core.cfg.node import Node from slither.slithir.operations import LowLevelCall -from slither.slithir.operations.operation import Operation + +from slither.core.declarations.function_contract import FunctionContract +from slither.core.variables.state_variable import StateVariable +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.utils.output import Output -class UncheckedLowLevel(UnusedReturnValues): +class UncheckedLowLevel(AbstractDetector): """ - If the return value of a send is not checked, it might lead to losing ether + If the return value of a low-level call is not checked, it might lead to losing ether """ ARGUMENT = "unchecked-lowlevel" @@ -38,5 +47,44 @@ If the low level is used to prevent blocking operations, consider logging failed WIKI_RECOMMENDATION = "Ensure that the return value of a low-level call is checked or logged." - def _is_instance(self, ir: Operation) -> bool: # pylint: disable=no-self-use - return isinstance(ir, LowLevelCall) + @staticmethod + def detect_unused_return_values(f: FunctionContract) -> List[Node]: + """ + Return the nodes where the return value of a call is unused + Args: + f (Function) + Returns: + list(Node) + """ + values_returned = [] + nodes_origin = {} + for n in f.nodes: + for ir in n.irs: + if isinstance(ir, LowLevelCall): + # if a return value is stored in a state variable, it's ok + if ir.lvalue and not isinstance(ir.lvalue, StateVariable): + values_returned.append(ir.lvalue) + nodes_origin[ir.lvalue] = ir + + for read in ir.read: + if read in values_returned: + values_returned.remove(read) + + return [nodes_origin[value].node for value in values_returned] + + def _detect(self) -> List[Output]: + """Detect low level calls where the success value is not checked""" + results = [] + for c in self.compilation_unit.contracts_derived: + for f in c.functions_and_modifiers: + unused_return = UncheckedLowLevel.detect_unused_return_values(f) + if unused_return: + + for node in unused_return: + info: DETECTOR_INFO = [f, " ignores return value by ", node, "\n"] + + res = self.generate_result(info) + + results.append(res) + + return results diff --git a/slither/detectors/operations/unused_return_values.py b/slither/detectors/operations/unused_return_values.py index 80be98b45..783a44807 100644 --- a/slither/detectors/operations/unused_return_values.py +++ b/slither/detectors/operations/unused_return_values.py @@ -101,10 +101,8 @@ contract MyConc{ def _detect(self) -> List[Output]: """Detect high level calls which return a value that are never used""" results = [] - for c in self.compilation_unit.contracts: - for f in c.functions + c.modifiers: - if f.contract_declarer != c: - continue + for c in self.compilation_unit.contracts_derived: + for f in c.functions_and_modifiers: unused_return = self.detect_unused_return_values(f) if unused_return: diff --git a/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol b/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol index 96712b077..cd6f78e98 100644 --- a/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol +++ b/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol @@ -4,8 +4,14 @@ contract MyConc{ } function good(address payable dst) external payable{ - (bool ret, bytes memory _) = dst.call{value:msg.value}(""); + (bool ret, ) = dst.call{value:msg.value}(""); require(ret); } + function good2(address payable dst) external payable{ + (bool ret, ) = dst.call{value:msg.value}(""); + if (!ret) { + revert(); + } + } } diff --git a/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol-0.7.6.zip b/tests/e2e/detectors/test_data/unchecked-lowlevel/0.7.6/unchecked_lowlevel.sol-0.7.6.zip index 530d247c4f4af07568e1b56c088632f1a7807cb3..bccb47182ef5c2d7ed86af2a327775c317856a86 100644 GIT binary patch delta 2487 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 From f3be9efad61672ba5e97189f73b055f7734d455a Mon Sep 17 00:00:00 2001 From: sam bacha Date: Thu, 6 Jul 2023 07:51:56 -0700 Subject: [PATCH 123/338] docs(readme): add new docs link (#2010) * docs(readme): add new docs link Fix the status badges and include a link to the documentation page that is now generated * docs(citation): create CITATION.cff This creates a `CITATION.cff` file. The information is taken from arXiv's bibtex for the whitepaper: ```bibtex @inproceedings{Feist_2019, doi = {10.1109/wetseb.2019.00008}, url = {https://doi.org/10.1109%2Fwetseb.2019.00008}, year = 2019, month = {may}, publisher = {{IEEE} }, author = {Josselin Feist and Gustavo Grieco and Alex Groce}, title = {Slither: A Static Analysis Framework for Smart Contracts}, booktitle = {2019 {IEEE}/{ACM} 2nd International Workshop on Emerging Trends in Software Engineering for Blockchain ({WETSEB})} } ``` --- CITATION.cff | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 60 +++++++++++++++++++++++++++++++----------------- 2 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..605bd60e5 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,64 @@ +cff-version: 1.2.0 +title: Slither Analyzer +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - given-names: Josselin + family-names: Feist + - given-names: Gustavo + family-names: Grieco + - given-names: Alex + family-names: Groce +identifiers: + - type: doi + value: 10.48550/arXiv.1908.09878 + description: arXiv.1908.09878 + - type: url + value: 'https://arxiv.org/abs/1908.09878' + description: arxiv + - type: doi + value: 10.1109/wetseb.2019.00008 +repository-code: 'https://github.com/crytic/slither' +url: 'https://www.trailofbits.com/' +repository-artifact: 'https://github.com/crytic/slither/releases' +abstract: >- + Slither is a static analysis framework designed to provide + rich information about Ethereum smart contracts. + + It works by converting Solidity smart contracts into an + intermediate representation called SlithIR. + + SlithIR uses Static Single Assignment (SSA) form and a + reduced instruction set to ease implementation of analyses + while preserving semantic information that would be lost + in transforming Solidity to bytecode. + + Slither allows for the application of commonly used + program analysis techniques like dataflow and taint + tracking. + + + Our framework has four main use cases: + + (1) automated detection of vulnerabilities, + + (2) automated detection of code optimization + opportunities, + + (3) improvement of the user's understanding of the + contracts, and + + (4) assistance with code review. +keywords: + - Ethereum + - Static Analysis + - Smart contracts + - EVM + - bug detection + - Software Engineering +license: AGPL-3.0-only +commit: 3d4f934d3228f072b7df2c5e7252c64df4601bc8 +version: 0.9.5 +date-released: '2023-06-28' diff --git a/README.md b/README.md index cb815561e..18c1c6226 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,40 @@ -# Slither, the Solidity source analyzer +Slither Static Analysis Framework Logo -Logo +# [Slither, the Solidity source analyzer](https://crytic.github.io/slither/slither.html) [![Build Status](https://img.shields.io/github/actions/workflow/status/crytic/slither/ci.yml?branch=master)](https://github.com/crytic/slither/actions?query=workflow%3ACI) -[![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com) -[![PyPI version](https://badge.fury.io/py/slither-analyzer.svg)](https://badge.fury.io/py/slither-analyzer) - -Slither is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. - -- [Features](#features) -- [Usage](#usage) -- [How to Install](#how-to-install) -- [Detectors](#detectors) -- [Printers](#printers) -- [Tools](#tools) -- [API Documentation](#api-documentation) -- [Getting Help](#getting-help) -- [FAQ](#faq) -- [Publications](#publications) +![PyPI](https://img.shields.io/pypi/v/slither-analyzer?logo=python&logoColor=white&label=slither-analyzer) +[![Slither - Read the Docs](https://img.shields.io/badge/Slither-Read_the_Docs-2ea44f)](https://crytic.github.io/slither/slither.html) +[![Slither - Wiki](https://img.shields.io/badge/Slither-Wiki-2ea44f)](https://github.com/crytic/slither/wiki/SlithIR) + +> Join the Empire Hacking Slack +> +> [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/) +> > - Discussions and Support + + +**Slither** is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. + + * [Features](#features) + * [Usage](#usage) + * [How to install](#how-to-install) + + [Using Pip](#using-pip) + + [Using Git](#using-git) + + [Using Docker](#using-docker) + + [Integration](#integration) + * [Detectors](#detectors) + * [Printers](#printers) + + [Quick Review Printers](#quick-review-printers) + + [In-Depth Review Printers](#in-depth-review-printers) + * [Tools](#tools) + * [API Documentation](#api-documentation) + * [Getting Help](#getting-help) + * [FAQ](#faq) + * [License](#license) + * [Publications](#publications) + + [Trail of Bits publication](#trail-of-bits-publication) + + [External publications](#external-publications) + ## Features @@ -36,7 +53,7 @@ Slither is a Solidity static analysis framework written in Python3. It runs a su Run Slither on a Hardhat/Foundry/Dapp/Brownie application: -```bash +```console slither . ``` @@ -44,18 +61,19 @@ This is the preferred option if your project has dependencies as Slither relies However, you can run Slither on a single file that does not import dependencies: -```bash +```console slither tests/uninitialized.sol ``` ## How to install -Slither requires Python 3.8+. +> **Note**
+> Slither requires Python 3.8+. If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile), you need [solc](https://github.com/ethereum/solidity/), the Solidity compiler; we recommend using [solc-select](https://github.com/crytic/solc-select) to conveniently switch between solc versions. ### Using Pip -```bash +```console pip3 install slither-analyzer ``` From e5f2a86f0906fd62c6c4eccb9dbfa5ab30671a78 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 6 Jul 2023 11:05:58 -0500 Subject: [PATCH 124/338] 0.9.6 (#2031) * 0.9.6 * lint readme --- README.md | 125 +++++++++++++++++++++++++++--------------------------- setup.py | 5 +-- 2 files changed, 64 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 18c1c6226..1a0d203c7 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,51 @@ -Slither Static Analysis Framework Logo - # [Slither, the Solidity source analyzer](https://crytic.github.io/slither/slither.html) +Slither Static Analysis Framework Logo + [![Build Status](https://img.shields.io/github/actions/workflow/status/crytic/slither/ci.yml?branch=master)](https://github.com/crytic/slither/actions?query=workflow%3ACI) ![PyPI](https://img.shields.io/pypi/v/slither-analyzer?logo=python&logoColor=white&label=slither-analyzer) [![Slither - Read the Docs](https://img.shields.io/badge/Slither-Read_the_Docs-2ea44f)](https://crytic.github.io/slither/slither.html) [![Slither - Wiki](https://img.shields.io/badge/Slither-Wiki-2ea44f)](https://github.com/crytic/slither/wiki/SlithIR) > Join the Empire Hacking Slack -> +> > [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/) > > - Discussions and Support - **Slither** is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. - * [Features](#features) - * [Usage](#usage) - * [How to install](#how-to-install) - + [Using Pip](#using-pip) - + [Using Git](#using-git) - + [Using Docker](#using-docker) - + [Integration](#integration) - * [Detectors](#detectors) - * [Printers](#printers) - + [Quick Review Printers](#quick-review-printers) - + [In-Depth Review Printers](#in-depth-review-printers) - * [Tools](#tools) - * [API Documentation](#api-documentation) - * [Getting Help](#getting-help) - * [FAQ](#faq) - * [License](#license) - * [Publications](#publications) - + [Trail of Bits publication](#trail-of-bits-publication) - + [External publications](#external-publications) - +* [Features](#features) +* [Usage](#usage) +* [How to install](#how-to-install) + * [Using Pip](#using-pip) + * [Using Git](#using-git) + * [Using Docker](#using-docker) + * [Integration](#integration) +* [Detectors](#detectors) +* [Printers](#printers) + * [Quick Review Printers](#quick-review-printers) + * [In-Depth Review Printers](#in-depth-review-printers) +* [Tools](#tools) +* [API Documentation](#api-documentation) +* [Getting Help](#getting-help) +* [FAQ](#faq) +* [License](#license) +* [Publications](#publications) + * [Trail of Bits publication](#trail-of-bits-publication) + * [External publications](#external-publications) ## Features -- Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md)) -- Identifies where the error condition occurs in the source code -- Easily integrates into continuous integration and Hardhat/Foundry builds -- Built-in 'printers' quickly report crucial contract information -- Detector API to write custom analyses in Python -- Ability to analyze contracts written with Solidity >= 0.4 -- Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses -- Correctly parses 99.9% of all public Solidity code -- Average execution time of less than 1 second per contract -- Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) +* Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md)) +* Identifies where the error condition occurs in the source code +* Easily integrates into continuous integration and Hardhat/Foundry builds +* Built-in 'printers' quickly report crucial contract information +* Detector API to write custom analyses in Python +* Ability to analyze contracts written with Solidity >= 0.4 +* Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses +* Correctly parses 99.9% of all public Solidity code +* Average execution time of less than 1 second per contract +* Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) ## Usage @@ -102,9 +100,9 @@ docker run -it -v /home/share:/share trailofbits/eth-security-toolbox ### Integration -- For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action). -- To generate a Markdown report, use `slither [target] --checklist`. -- To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`) +* For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action). +* To generate a Markdown report, use `slither [target] --checklist`. +* To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`) ## Detectors @@ -200,23 +198,24 @@ Num | Detector | What it Detects | Impact | Confidence For more information, see -- The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector -- The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run. -- The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results +* The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector +* The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run. +* The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results ## Printers + ### Quick Review Printers -- `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary) -- `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) -- `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary) -- `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) +* `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary) +* `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) +* `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary) +* `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) ### In-Depth Review Printers -- `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph) -- `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg) -- `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) -- `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization) -- `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused). +* `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph) +* `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg) +* `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) +* `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization) +* `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused). To run a printer, use `--print` and a comma-separated list of printers. @@ -224,13 +223,13 @@ See the [Printer documentation](https://github.com/crytic/slither/wiki/Printer-d ## Tools -- `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](https://github.com/crytic/slither/wiki/Upgradeability-Checks) -- `slither-prop`: [Automatic unit test and property generation](https://github.com/crytic/slither/wiki/Property-generation) -- `slither-flat`: [Flatten a codebase](https://github.com/crytic/slither/wiki/Contract-Flattening) -- `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance) -- `slither-format`: [Automatic patch generation](https://github.com/crytic/slither/wiki/Slither-format) -- `slither-read-storage`: [Read storage values from contracts](./slither/tools/read_storage/README.md) -- `slither-interface`: [Generate an interface for a contract](./slither/tools/interface/README.md) +* `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](https://github.com/crytic/slither/wiki/Upgradeability-Checks) +* `slither-prop`: [Automatic unit test and property generation](https://github.com/crytic/slither/wiki/Property-generation) +* `slither-flat`: [Flatten a codebase](https://github.com/crytic/slither/wiki/Contract-Flattening) +* `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance) +* `slither-format`: [Automatic patch generation](https://github.com/crytic/slither/wiki/Slither-format) +* `slither-read-storage`: [Read storage values from contracts](./slither/tools/read_storage/README.md) +* `slither-interface`: [Generate an interface for a contract](./slither/tools/interface/README.md) See the [Tool documentation](https://github.com/crytic/slither/wiki/Tool-Documentation) for additional tools. @@ -244,23 +243,23 @@ Documentation on Slither's internals is available [here](https://crytic.github.i Feel free to stop by our [Slack channel](https://empireslacking.herokuapp.com) (#ethereum) for help using or extending Slither. -- The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract. +* The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract. -- The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses. +* The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses. -- The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses. +* The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses. -- The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation. +* The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation. ## FAQ How do I exclude mocks or tests? -- View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering). +* View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering). How do I fix "unknown file" or compilation issues? -- Because slither requires the solc AST, it must have all dependencies available. +* Because slither requires the solc AST, it must have all dependencies available. If a contract has dependencies, `slither contract.sol` will fail. Instead, use `slither .` in the parent directory of `contracts/` (you should see `contracts/` when you run `ls`). If you have a `node_modules/` folder, it must be in the same directory as `contracts/`. To verify that this issue is related to slither, @@ -275,7 +274,7 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt ### Trail of Bits publication -- [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19 +* [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19 ### External publications diff --git a/setup.py b/setup.py index e7019b1aa..182b91d35 100644 --- a/setup.py +++ b/setup.py @@ -8,14 +8,14 @@ setup( description="Slither is a Solidity static analysis framework written in Python 3.", url="https://github.com/crytic/slither", author="Trail of Bits", - version="0.9.5", + version="0.9.6", packages=find_packages(), python_requires=">=3.8", install_requires=[ "packaging", "prettytable>=3.3.0", "pycryptodome>=3.4.6", - "crytic-compile>=0.3.2,<0.4.0", + "crytic-compile>=0.3.3,<0.4.0", # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile", "web3>=6.0.0", "eth-abi>=4.0.0", @@ -36,7 +36,6 @@ setup( "coverage[toml]", "filelock", "pytest-insta", - "solc-select>=1.0.4", ], "doc": [ "pdoc", From 06e218c822adcf83f96c7996b1c1683dd6a4d27d Mon Sep 17 00:00:00 2001 From: devtooligan Date: Wed, 5 Jul 2023 18:00:13 -0700 Subject: [PATCH 125/338] refactor: prefer custom classes to dicts --- slither/printers/summary/halstead.py | 177 ++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 4 deletions(-) diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index 12e422fb0..5741db123 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -25,19 +25,182 @@ """ import math +from dataclasses import dataclass, field +from typing import Tuple, List, Dict from collections import OrderedDict +from slither.core.declarations import ( + Contract, + Pragma, + Import, + Function, + Modifier, +) from slither.printers.abstract_printer import AbstractPrinter from slither.slithir.variables.temporary import TemporaryVariable -from slither.utils.myprettytable import make_pretty_table -from slither.utils.upgradeability import encode_ir_for_halstead +from slither.utils.myprettytable import make_pretty_table, MyPrettyTable +from slither.utils.upgradeability import encode_ir_for_halstead # TODO: Add to slither/utils/halstead -def compute_halstead(contracts: list) -> tuple: +@dataclass +class HalsteadContractMetrics: + """Class to hold the Halstead metrics for a single contract.""" + # TODO: Add to slither/utils/halstead + contract: Contract + all_operators: List[str] = field(default_factory=list) + all_operands: List[str] = field(default_factory=list) + n1: int = 0 + n2: int = 0 + N1: int = 0 + N2: int = 0 + n: int = 0 + N: int = 0 + S: float = 0 + V: float = 0 + D: float = 0 + E: float = 0 + T: float = 0 + B: float = 0 + + def __post_init__(self): + if (len(self.all_operators) == 0): + self.populate_operators_and_operands() + self.compute_metrics() + + def to_dict(self) -> Dict[str, float]: + """Return the metrics as a dictionary.""" + return OrderedDict({ + "Total Operators": self.N1, + "Unique Operators": self.n1, + "Total Operands": self.N2, + "Unique Operands": self.n2, + "Vocabulary": str(self.n1 + self.n2), + "Program Length": str(self.N1 + self.N2), + "Estimated Length": f"{self.S:.0f}", + "Volume": f"{self.V:.0f}", + "Difficulty": f"{self.D:.0f}", + "Effort": f"{self.E:.0f}", + "Time": f"{self.T:.0f}", + "Estimated Bugs": f"{self.B:.3f}", + }) + + def populate_operators_and_operands(self): + """Populate the operators and operands lists.""" + operators = [] + operands = [] + for func in self.contract.functions: + for node in func.nodes: + for operation in node.irs: + # use operation.expression.type to get the unique operator type + encoded_operator = encode_ir_for_halstead(operation) + operators.append(encoded_operator) + + # use operation.used to get the operands of the operation ignoring the temporary variables + operands.extend([ + op for op in operation.used if not isinstance(op, TemporaryVariable) + ]) + # import pdb; pdb.set_trace() + self.all_operators.extend(operators) + self.all_operands.extend(operands) + + def compute_metrics(self, all_operators=[], all_operands=[]): + """Compute the Halstead metrics.""" + if len(all_operators) == 0: + all_operators = self.all_operators + all_operands = self.all_operands + + self.n1 = len(set(all_operators)) + self.n2 = len(set(all_operands)) + self.N1 = len(all_operators) + self.N2 = len(all_operands) + if any(number <= 0 for number in [self.n1, self.n2, self.N1, self.N2]): + raise ValueError("n1 and n2 must be greater than 0") + + self.n = self.n1 + self.n2 + self.N = self.N1 + self.N2 + self.S = self.n1 * math.log2(self.n1) + self.n2 * math.log2(self.n2) + self.V = self.N * math.log2(self.n) + self.D = (self.n1 / 2) * (self.N2 / self.n2) + self.E = self.D * self.V + self.T = self.E / 18 + self.B = (self.E ** (2 / 3)) / 3000 + + +@dataclass +class SectionInfo: + title: str + pretty_table: MyPrettyTable + txt: str + + +@dataclass +class HalsteadMetrics: + """Class to hold the Halstead metrics for all contracts and methods for reporting.""" + contracts: List[Contract] = field(default_factory=list) + contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field(default_factory=OrderedDict) + title: str = "Halstead complexity metrics" + full_txt: str = "" + core: SectionInfo = field(default=SectionInfo) + extended1: SectionInfo = field(default=SectionInfo) + extended2: SectionInfo = field(default=SectionInfo) + CORE_KEYS = ( + "Total Operators", + "Unique Operators", + "Total Operands", + "Unique Operands", + ) + EXTENDED1_KEYS = ( + "Vocabulary", + "Program Length", + "Estimated Length", + "Volume", + ) + EXTENDED2_KEYS = ( + "Difficulty", + "Effort", + "Time", + "Estimated Bugs", + ) + SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( + ("Core", CORE_KEYS), + ("Extended1", EXTENDED1_KEYS), + ("Extended2", EXTENDED2_KEYS), + ) + + + def __post_init__(self): + for contract in self.contracts: + self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) + + if len(self.contracts) > 1: + all_operators = [ + operator for contract in self.contracts + for operator in self.contract_metrics[contract.name].all_operators + ] + + all_operands = [ + operand for contract in self.contracts + for operand in self.contract_metrics[contract.name].all_operands + ] + + self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics(all_operators=all_operators, all_operands=all_operands) + + data = { + contract.name: self.contract_metrics[contract.name].to_dict() + for contract in self.contracts + } + for (title, keys) in self.SECTIONS: + pretty_table = make_pretty_table(["Contract", *keys], data, False) + section_title = f"{self.title} - {title}" + txt = f"\n\n{section_title}:\n{pretty_table}\n" + self.full_txt += txt + setattr(self, title.lower(), SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt)) + +def compute_halstead(contracts: list) -> Tuple[Dict, Dict, Dict]: """Used to compute the Halstead complexity metrics for a list of contracts. Args: contracts: list of contracts. Returns: - Halstead metrics as a tuple of two OrderedDicts (core_metrics, extended_metrics) + Halstead metrics as a tuple of three OrderedDicts (core_metrics, extended_metrics1, extended_metrics2) which each contain one key per contract. The value of each key is a dict of metrics. In addition to one key per contract, there is a key for "ALL CONTRACTS" that contains @@ -162,6 +325,8 @@ class Halstead(AbstractPrinter): core, extended1, extended2 = compute_halstead(self.contracts) + halstead = HalsteadMetrics(self.contracts) + # Core metrics: operations and operands txt = "\n\nHalstead complexity core metrics:\n" keys = list(core[self.contracts[0].name].keys()) @@ -185,5 +350,9 @@ class Halstead(AbstractPrinter): res.add_pretty_table(table_extended1, "Halstead extended metrics1") res.add_pretty_table(table_extended2, "Halstead extended metrics2") self.info(txt) + self.info("*****************************************************************") + self.info("new one") + self.info("*****************************************************************") + self.info(halstead.full_txt) return res From db5ec712de134cef84c9bde4e2a57125a2336a13 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 12:06:58 -0700 Subject: [PATCH 126/338] chore: move halstead utilities to utils folder --- slither/printers/summary/halstead.py | 321 +-------------------------- slither/utils/halstead.py | 203 +++++++++++++++++ 2 files changed, 208 insertions(+), 316 deletions(-) create mode 100644 slither/utils/halstead.py diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index 5741db123..ef446e389 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -22,296 +22,9 @@ T = E / 18 seconds # Time required to program B = (E^(2/3)) / 3000 # Number of delivered bugs - """ -import math -from dataclasses import dataclass, field -from typing import Tuple, List, Dict -from collections import OrderedDict -from slither.core.declarations import ( - Contract, - Pragma, - Import, - Function, - Modifier, -) from slither.printers.abstract_printer import AbstractPrinter -from slither.slithir.variables.temporary import TemporaryVariable -from slither.utils.myprettytable import make_pretty_table, MyPrettyTable -from slither.utils.upgradeability import encode_ir_for_halstead # TODO: Add to slither/utils/halstead - - -@dataclass -class HalsteadContractMetrics: - """Class to hold the Halstead metrics for a single contract.""" - # TODO: Add to slither/utils/halstead - contract: Contract - all_operators: List[str] = field(default_factory=list) - all_operands: List[str] = field(default_factory=list) - n1: int = 0 - n2: int = 0 - N1: int = 0 - N2: int = 0 - n: int = 0 - N: int = 0 - S: float = 0 - V: float = 0 - D: float = 0 - E: float = 0 - T: float = 0 - B: float = 0 - - def __post_init__(self): - if (len(self.all_operators) == 0): - self.populate_operators_and_operands() - self.compute_metrics() - - def to_dict(self) -> Dict[str, float]: - """Return the metrics as a dictionary.""" - return OrderedDict({ - "Total Operators": self.N1, - "Unique Operators": self.n1, - "Total Operands": self.N2, - "Unique Operands": self.n2, - "Vocabulary": str(self.n1 + self.n2), - "Program Length": str(self.N1 + self.N2), - "Estimated Length": f"{self.S:.0f}", - "Volume": f"{self.V:.0f}", - "Difficulty": f"{self.D:.0f}", - "Effort": f"{self.E:.0f}", - "Time": f"{self.T:.0f}", - "Estimated Bugs": f"{self.B:.3f}", - }) - - def populate_operators_and_operands(self): - """Populate the operators and operands lists.""" - operators = [] - operands = [] - for func in self.contract.functions: - for node in func.nodes: - for operation in node.irs: - # use operation.expression.type to get the unique operator type - encoded_operator = encode_ir_for_halstead(operation) - operators.append(encoded_operator) - - # use operation.used to get the operands of the operation ignoring the temporary variables - operands.extend([ - op for op in operation.used if not isinstance(op, TemporaryVariable) - ]) - # import pdb; pdb.set_trace() - self.all_operators.extend(operators) - self.all_operands.extend(operands) - - def compute_metrics(self, all_operators=[], all_operands=[]): - """Compute the Halstead metrics.""" - if len(all_operators) == 0: - all_operators = self.all_operators - all_operands = self.all_operands - - self.n1 = len(set(all_operators)) - self.n2 = len(set(all_operands)) - self.N1 = len(all_operators) - self.N2 = len(all_operands) - if any(number <= 0 for number in [self.n1, self.n2, self.N1, self.N2]): - raise ValueError("n1 and n2 must be greater than 0") - - self.n = self.n1 + self.n2 - self.N = self.N1 + self.N2 - self.S = self.n1 * math.log2(self.n1) + self.n2 * math.log2(self.n2) - self.V = self.N * math.log2(self.n) - self.D = (self.n1 / 2) * (self.N2 / self.n2) - self.E = self.D * self.V - self.T = self.E / 18 - self.B = (self.E ** (2 / 3)) / 3000 - - -@dataclass -class SectionInfo: - title: str - pretty_table: MyPrettyTable - txt: str - - -@dataclass -class HalsteadMetrics: - """Class to hold the Halstead metrics for all contracts and methods for reporting.""" - contracts: List[Contract] = field(default_factory=list) - contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field(default_factory=OrderedDict) - title: str = "Halstead complexity metrics" - full_txt: str = "" - core: SectionInfo = field(default=SectionInfo) - extended1: SectionInfo = field(default=SectionInfo) - extended2: SectionInfo = field(default=SectionInfo) - CORE_KEYS = ( - "Total Operators", - "Unique Operators", - "Total Operands", - "Unique Operands", - ) - EXTENDED1_KEYS = ( - "Vocabulary", - "Program Length", - "Estimated Length", - "Volume", - ) - EXTENDED2_KEYS = ( - "Difficulty", - "Effort", - "Time", - "Estimated Bugs", - ) - SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( - ("Core", CORE_KEYS), - ("Extended1", EXTENDED1_KEYS), - ("Extended2", EXTENDED2_KEYS), - ) - - - def __post_init__(self): - for contract in self.contracts: - self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) - - if len(self.contracts) > 1: - all_operators = [ - operator for contract in self.contracts - for operator in self.contract_metrics[contract.name].all_operators - ] - - all_operands = [ - operand for contract in self.contracts - for operand in self.contract_metrics[contract.name].all_operands - ] - - self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics(all_operators=all_operators, all_operands=all_operands) - - data = { - contract.name: self.contract_metrics[contract.name].to_dict() - for contract in self.contracts - } - for (title, keys) in self.SECTIONS: - pretty_table = make_pretty_table(["Contract", *keys], data, False) - section_title = f"{self.title} - {title}" - txt = f"\n\n{section_title}:\n{pretty_table}\n" - self.full_txt += txt - setattr(self, title.lower(), SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt)) - -def compute_halstead(contracts: list) -> Tuple[Dict, Dict, Dict]: - """Used to compute the Halstead complexity metrics for a list of contracts. - Args: - contracts: list of contracts. - Returns: - Halstead metrics as a tuple of three OrderedDicts (core_metrics, extended_metrics1, extended_metrics2) - which each contain one key per contract. The value of each key is a dict of metrics. - - In addition to one key per contract, there is a key for "ALL CONTRACTS" that contains - the metrics for ALL CONTRACTS combined. (Not the sums of the individual contracts!) - - core_metrics: - {"contract1 name": { - "N1_total_operators": N1, - "n1_unique_operators": n1, - "N2_total_operands": N2, - "n2_unique_operands": n1, - }} - - extended_metrics1: - {"contract1 name": { - "n_vocabulary": n1 + n2, - "N_prog_length": N1 + N2, - "S_est_length": S, - "V_volume": V, - }} - extended_metrics2: - {"contract1 name": { - "D_difficulty": D, - "E_effort": E, - "T_time": T, - "B_bugs": B, - }} - - """ - core = OrderedDict() - extended1 = OrderedDict() - extended2 = OrderedDict() - all_operators = [] - all_operands = [] - for contract in contracts: - operators = [] - operands = [] - for func in contract.functions: - for node in func.nodes: - for operation in node.irs: - # use operation.expression.type to get the unique operator type - encoded_operator = encode_ir_for_halstead(operation) - operators.append(encoded_operator) - all_operators.append(encoded_operator) - - # use operation.used to get the operands of the operation ignoring the temporary variables - new_operands = [ - op for op in operation.used if not isinstance(op, TemporaryVariable) - ] - operands.extend(new_operands) - all_operands.extend(new_operands) - ( - core[contract.name], - extended1[contract.name], - extended2[contract.name], - ) = _calculate_metrics(operators, operands) - if len(contracts) > 1: - core["ALL CONTRACTS"] = OrderedDict() - extended1["ALL CONTRACTS"] = OrderedDict() - extended2["ALL CONTRACTS"] = OrderedDict() - ( - core["ALL CONTRACTS"], - extended1["ALL CONTRACTS"], - extended2["ALL CONTRACTS"], - ) = _calculate_metrics(all_operators, all_operands) - return (core, extended1, extended2) - - -# pylint: disable=too-many-locals -def _calculate_metrics(operators, operands): - """Used to compute the Halstead complexity metrics for a list of operators and operands. - Args: - operators: list of operators. - operands: list of operands. - Returns: - Halstead metrics as a tuple of two OrderedDicts (core_metrics, extended_metrics) - which each contain one key per contract. The value of each key is a dict of metrics. - NOTE: The metric values are ints and floats that have been converted to formatted strings - """ - n1 = len(set(operators)) - n2 = len(set(operands)) - N1 = len(operators) - N2 = len(operands) - n = n1 + n2 - N = N1 + N2 - S = 0 if (n1 == 0 or n2 == 0) else n1 * math.log2(n1) + n2 * math.log2(n2) - V = N * math.log2(n) if n > 0 else 0 - D = (n1 / 2) * (N2 / n2) if n2 > 0 else 0 - E = D * V - T = E / 18 - B = (E ** (2 / 3)) / 3000 - core_metrics = { - "Total Operators": N1, - "Unique Operators": n1, - "Total Operands": N2, - "Unique Operands": n2, - } - extended_metrics1 = { - "Vocabulary": str(n1 + n2), - "Program Length": str(N1 + N2), - "Estimated Length": f"{S:.0f}", - "Volume": f"{V:.0f}", - } - extended_metrics2 = { - "Difficulty": f"{D:.0f}", - "Effort": f"{E:.0f}", - "Time": f"{T:.0f}", - "Estimated Bugs": f"{B:.3f}", - } - return (core_metrics, extended_metrics1, extended_metrics2) - +from slither.utils.halstead import HalsteadMetrics class Halstead(AbstractPrinter): ARGUMENT = "halstead" @@ -323,36 +36,12 @@ class Halstead(AbstractPrinter): if len(self.contracts) == 0: return self.generate_output("No contract found") - core, extended1, extended2 = compute_halstead(self.contracts) - halstead = HalsteadMetrics(self.contracts) - # Core metrics: operations and operands - txt = "\n\nHalstead complexity core metrics:\n" - keys = list(core[self.contracts[0].name].keys()) - table_core = make_pretty_table(["Contract", *keys], core, False) - txt += str(table_core) + "\n" - - # Extended metrics1: vocabulary, program length, estimated length, volume - txt += "\nHalstead complexity extended metrics1:\n" - keys = list(extended1[self.contracts[0].name].keys()) - table_extended1 = make_pretty_table(["Contract", *keys], extended1, False) - txt += str(table_extended1) + "\n" - - # Extended metrics2: difficulty, effort, time, bugs - txt += "\nHalstead complexity extended metrics2:\n" - keys = list(extended2[self.contracts[0].name].keys()) - table_extended2 = make_pretty_table(["Contract", *keys], extended2, False) - txt += str(table_extended2) + "\n" - - res = self.generate_output(txt) - res.add_pretty_table(table_core, "Halstead core metrics") - res.add_pretty_table(table_extended1, "Halstead extended metrics1") - res.add_pretty_table(table_extended2, "Halstead extended metrics2") - self.info(txt) - self.info("*****************************************************************") - self.info("new one") - self.info("*****************************************************************") + res = self.generate_output(halstead.full_txt) + res.add_pretty_table(halstead.core.pretty_table, halstead.core.title) + res.add_pretty_table(halstead.extended1.pretty_table, halstead.extended1.title) + res.add_pretty_table(halstead.extended2.pretty_table, halstead.extended2.title) self.info(halstead.full_txt) return res diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py new file mode 100644 index 000000000..7417fb4e1 --- /dev/null +++ b/slither/utils/halstead.py @@ -0,0 +1,203 @@ +""" + Halstead complexity metrics + https://en.wikipedia.org/wiki/Halstead_complexity_measures + + 12 metrics based on the number of unique operators and operands: + + Core metrics: + n1 = the number of distinct operators + n2 = the number of distinct operands + N1 = the total number of operators + N2 = the total number of operands + + Extended metrics1: + n = n1 + n2 # Program vocabulary + N = N1 + N2 # Program length + S = n1 * log2(n1) + n2 * log2(n2) # Estimated program length + V = N * log2(n) # Volume + + Extended metrics2: + D = (n1 / 2) * (N2 / n2) # Difficulty + E = D * V # Effort + T = E / 18 seconds # Time required to program + B = (E^(2/3)) / 3000 # Number of delivered bugs + + +""" +import math +from dataclasses import dataclass, field +from typing import Tuple, List, Dict +from collections import OrderedDict +from slither.core.declarations import Contract +from slither.slithir.variables.temporary import TemporaryVariable +from slither.utils.myprettytable import make_pretty_table, MyPrettyTable +from slither.utils.upgradeability import encode_ir_for_halstead + + +@dataclass +class HalsteadContractMetrics: + """Class to hold the Halstead metrics for a single contract.""" + contract: Contract + all_operators: List[str] = field(default_factory=list) + all_operands: List[str] = field(default_factory=list) + n1: int = 0 + n2: int = 0 + N1: int = 0 + N2: int = 0 + n: int = 0 + N: int = 0 + S: float = 0 + V: float = 0 + D: float = 0 + E: float = 0 + T: float = 0 + B: float = 0 + + def __post_init__(self): + """ Operators and operands can be passed in as constructor args to avoid computing + them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" + if (len(self.all_operators) == 0): + self.populate_operators_and_operands() + if (len(self.all_operators) > 0): + self.compute_metrics() + + def to_dict(self) -> Dict[str, float]: + """Return the metrics as a dictionary.""" + return OrderedDict({ + "Total Operators": self.N1, + "Unique Operators": self.n1, + "Total Operands": self.N2, + "Unique Operands": self.n2, + "Vocabulary": str(self.n1 + self.n2), + "Program Length": str(self.N1 + self.N2), + "Estimated Length": f"{self.S:.0f}", + "Volume": f"{self.V:.0f}", + "Difficulty": f"{self.D:.0f}", + "Effort": f"{self.E:.0f}", + "Time": f"{self.T:.0f}", + "Estimated Bugs": f"{self.B:.3f}", + }) + + def populate_operators_and_operands(self): + """Populate the operators and operands lists.""" + operators = [] + operands = [] + for func in self.contract.functions: + for node in func.nodes: + for operation in node.irs: + # use operation.expression.type to get the unique operator type + encoded_operator = encode_ir_for_halstead(operation) + operators.append(encoded_operator) + + # use operation.used to get the operands of the operation ignoring the temporary variables + operands.extend([ + op for op in operation.used if not isinstance(op, TemporaryVariable) + ]) + self.all_operators.extend(operators) + self.all_operands.extend(operands) + + def compute_metrics(self, all_operators=[], all_operands=[]): + """Compute the Halstead metrics.""" + if len(all_operators) == 0: + all_operators = self.all_operators + all_operands = self.all_operands + + # core metrics + self.n1 = len(set(all_operators)) + self.n2 = len(set(all_operands)) + self.N1 = len(all_operators) + self.N2 = len(all_operands) + if any(number <= 0 for number in [self.n1, self.n2, self.N1, self.N2]): + raise ValueError("n1 and n2 must be greater than 0") + + # extended metrics 1 + self.n = self.n1 + self.n2 + self.N = self.N1 + self.N2 + self.S = self.n1 * math.log2(self.n1) + self.n2 * math.log2(self.n2) + self.V = self.N * math.log2(self.n) + + # extended metrics 2 + self.D = (self.n1 / 2) * (self.N2 / self.n2) + self.E = self.D * self.V + self.T = self.E / 18 + self.B = (self.E ** (2 / 3)) / 3000 + + +@dataclass +class SectionInfo: + """Class to hold the information for a section of the report.""" + title: str + pretty_table: MyPrettyTable + txt: str + + +@dataclass +class HalsteadMetrics: + """Class to hold the Halstead metrics for all contracts. Contains methods useful for reporting. + + There are 3 sections in the report: + 1. Core metrics (n1, n2, N1, N2) + 2. Extended metrics 1 (n, N, S, V) + 3. Extended metrics 2 (D, E, T, B) + + """ + contracts: List[Contract] = field(default_factory=list) + contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field(default_factory=OrderedDict) + title: str = "Halstead complexity metrics" + full_txt: str = "" + core: SectionInfo = field(default=SectionInfo) + extended1: SectionInfo = field(default=SectionInfo) + extended2: SectionInfo = field(default=SectionInfo) + CORE_KEYS = ( + "Total Operators", + "Unique Operators", + "Total Operands", + "Unique Operands", + ) + EXTENDED1_KEYS = ( + "Vocabulary", + "Program Length", + "Estimated Length", + "Volume", + ) + EXTENDED2_KEYS = ( + "Difficulty", + "Effort", + "Time", + "Estimated Bugs", + ) + SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( + ("Core", CORE_KEYS), + ("Extended1", EXTENDED1_KEYS), + ("Extended2", EXTENDED2_KEYS), + ) + + + def __post_init__(self): + # Compute the metrics for each contract and for all contracts. + for contract in self.contracts: + self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) + + # If there are more than 1 contract, compute the metrics for all contracts. + if len(self.contracts) > 1: + all_operators = [ + operator for contract in self.contracts + for operator in self.contract_metrics[contract.name].all_operators + ] + all_operands = [ + operand for contract in self.contracts + for operand in self.contract_metrics[contract.name].all_operands + ] + self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics(all_operators=all_operators, all_operands=all_operands) + + # Create the table and text for each section. + data = { + contract.name: self.contract_metrics[contract.name].to_dict() + for contract in self.contracts + } + for (title, keys) in self.SECTIONS: + pretty_table = make_pretty_table(["Contract", *keys], data, False) + section_title = f"{self.title} ({title})" + txt = f"\n\n{section_title}:\n{pretty_table}\n" + self.full_txt += txt + setattr(self, title.lower(), SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt)) From 0fb6e42a9d97833387dc23624f4763b33e9fb8ab Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 12:12:40 -0700 Subject: [PATCH 127/338] chore: lint --- slither/printers/summary/halstead.py | 1 + slither/utils/halstead.py | 72 +++++++++++++++++----------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index ef446e389..f5e4f0a90 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -26,6 +26,7 @@ from slither.printers.abstract_printer import AbstractPrinter from slither.utils.halstead import HalsteadMetrics + class Halstead(AbstractPrinter): ARGUMENT = "halstead" HELP = "Computes the Halstead complexity metrics for each contract" diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index 7417fb4e1..d9835b6be 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -35,8 +35,10 @@ from slither.utils.upgradeability import encode_ir_for_halstead @dataclass +# pylint: disable=too-many-instance-attributes class HalsteadContractMetrics: """Class to hold the Halstead metrics for a single contract.""" + contract: Contract all_operators: List[str] = field(default_factory=list) all_operands: List[str] = field(default_factory=list) @@ -54,29 +56,31 @@ class HalsteadContractMetrics: B: float = 0 def __post_init__(self): - """ Operators and operands can be passed in as constructor args to avoid computing + """Operators and operands can be passed in as constructor args to avoid computing them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" - if (len(self.all_operators) == 0): + if len(self.all_operators) == 0: self.populate_operators_and_operands() - if (len(self.all_operators) > 0): + if len(self.all_operators) > 0: self.compute_metrics() def to_dict(self) -> Dict[str, float]: """Return the metrics as a dictionary.""" - return OrderedDict({ - "Total Operators": self.N1, - "Unique Operators": self.n1, - "Total Operands": self.N2, - "Unique Operands": self.n2, - "Vocabulary": str(self.n1 + self.n2), - "Program Length": str(self.N1 + self.N2), - "Estimated Length": f"{self.S:.0f}", - "Volume": f"{self.V:.0f}", - "Difficulty": f"{self.D:.0f}", - "Effort": f"{self.E:.0f}", - "Time": f"{self.T:.0f}", - "Estimated Bugs": f"{self.B:.3f}", - }) + return OrderedDict( + { + "Total Operators": self.N1, + "Unique Operators": self.n1, + "Total Operands": self.N2, + "Unique Operands": self.n2, + "Vocabulary": str(self.n1 + self.n2), + "Program Length": str(self.N1 + self.N2), + "Estimated Length": f"{self.S:.0f}", + "Volume": f"{self.V:.0f}", + "Difficulty": f"{self.D:.0f}", + "Effort": f"{self.E:.0f}", + "Time": f"{self.T:.0f}", + "Estimated Bugs": f"{self.B:.3f}", + } + ) def populate_operators_and_operands(self): """Populate the operators and operands lists.""" @@ -90,15 +94,15 @@ class HalsteadContractMetrics: operators.append(encoded_operator) # use operation.used to get the operands of the operation ignoring the temporary variables - operands.extend([ - op for op in operation.used if not isinstance(op, TemporaryVariable) - ]) + operands.extend( + [op for op in operation.used if not isinstance(op, TemporaryVariable)] + ) self.all_operators.extend(operators) self.all_operands.extend(operands) - def compute_metrics(self, all_operators=[], all_operands=[]): + def compute_metrics(self, all_operators=None, all_operands=None): """Compute the Halstead metrics.""" - if len(all_operators) == 0: + if all_operators is None: all_operators = self.all_operators all_operands = self.all_operands @@ -126,12 +130,14 @@ class HalsteadContractMetrics: @dataclass class SectionInfo: """Class to hold the information for a section of the report.""" + title: str pretty_table: MyPrettyTable txt: str @dataclass +# pylint: disable=too-many-instance-attributes class HalsteadMetrics: """Class to hold the Halstead metrics for all contracts. Contains methods useful for reporting. @@ -141,8 +147,11 @@ class HalsteadMetrics: 3. Extended metrics 2 (D, E, T, B) """ + contracts: List[Contract] = field(default_factory=list) - contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field(default_factory=OrderedDict) + contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field( + default_factory=OrderedDict + ) title: str = "Halstead complexity metrics" full_txt: str = "" core: SectionInfo = field(default=SectionInfo) @@ -172,7 +181,6 @@ class HalsteadMetrics: ("Extended2", EXTENDED2_KEYS), ) - def __post_init__(self): # Compute the metrics for each contract and for all contracts. for contract in self.contracts: @@ -181,14 +189,18 @@ class HalsteadMetrics: # If there are more than 1 contract, compute the metrics for all contracts. if len(self.contracts) > 1: all_operators = [ - operator for contract in self.contracts + operator + for contract in self.contracts for operator in self.contract_metrics[contract.name].all_operators ] all_operands = [ - operand for contract in self.contracts + operand + for contract in self.contracts for operand in self.contract_metrics[contract.name].all_operands ] - self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics(all_operators=all_operators, all_operands=all_operands) + self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics( + None, all_operators=all_operators, all_operands=all_operands + ) # Create the table and text for each section. data = { @@ -200,4 +212,8 @@ class HalsteadMetrics: section_title = f"{self.title} ({title})" txt = f"\n\n{section_title}:\n{pretty_table}\n" self.full_txt += txt - setattr(self, title.lower(), SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt)) + setattr( + self, + title.lower(), + SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), + ) From 8f831ada952e8af8c084712282d6f73ec08afa1d Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 15:00:09 -0700 Subject: [PATCH 128/338] fix: 'type' object is not subscriptable --- slither/utils/halstead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index d9835b6be..d781e3c39 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -149,7 +149,7 @@ class HalsteadMetrics: """ contracts: List[Contract] = field(default_factory=list) - contract_metrics: OrderedDict[Contract, HalsteadContractMetrics] = field( + contract_metrics: OrderedDict = field( default_factory=OrderedDict ) title: str = "Halstead complexity metrics" From 61e3076647bce3dbd2940986fce9863abe63eb38 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 15:15:59 -0700 Subject: [PATCH 129/338] chore: lint --- slither/utils/halstead.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index d781e3c39..f4426f60a 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -149,9 +149,7 @@ class HalsteadMetrics: """ contracts: List[Contract] = field(default_factory=list) - contract_metrics: OrderedDict = field( - default_factory=OrderedDict - ) + contract_metrics: OrderedDict = field(default_factory=OrderedDict) title: str = "Halstead complexity metrics" full_txt: str = "" core: SectionInfo = field(default=SectionInfo) From fb25cbb26e4460305b5498ffe0bbfad9d8bb3044 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 15:40:51 -0700 Subject: [PATCH 130/338] refactor: initial --- slither/printers/summary/ck.py | 1 + slither/utils/ck.py | 166 +++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 slither/utils/ck.py diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index a9f80b354..fc199dc87 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -19,6 +19,7 @@ from slither.utils.myprettytable import make_pretty_table from slither.slithir.operations.high_level_call import HighLevelCall from slither.printers.abstract_printer import AbstractPrinter from slither.printers.summary.martin import compute_coupling +from slither.utils.ck import CKMetrics def compute_dit(contract, depth=0): diff --git a/slither/utils/ck.py b/slither/utils/ck.py new file mode 100644 index 000000000..d3c573521 --- /dev/null +++ b/slither/utils/ck.py @@ -0,0 +1,166 @@ +""" +Description + +""" +import math +from dataclasses import dataclass, field +from typing import Tuple, List, Dict +from collections import OrderedDict +from slither.core.declarations import Contract +from slither.slithir.variables.temporary import TemporaryVariable +from slither.utils.myprettytable import make_pretty_table, MyPrettyTable +from slither.utils.upgradeability import encode_ir_for_halstead + + +@dataclass +# pylint: disable=too-many-instance-attributes +class TEMPLATEContractMetrics: + """Class to hold the TEMPLATE metrics for a single contract.""" + + contract: Contract + + def __post_init__(self): + # """Operators and operands can be passed in as constructor args to avoid computing + # them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" + # if len(self.all_operators) == 0: + # self.populate_operators_and_operands() + # if len(self.all_operators) > 0: + # self.compute_metrics() + pass + + def to_dict(self) -> Dict[str, float]: + """Return the metrics as a dictionary.""" + return OrderedDict( + # { + # "Total Operators": self.N1, + # "Unique Operators": self.n1, + # "Total Operands": self.N2, + # "Unique Operands": self.n2, + # "Vocabulary": str(self.n1 + self.n2), + # "Program Length": str(self.N1 + self.N2), + # "Estimated Length": f"{self.S:.0f}", + # "Volume": f"{self.V:.0f}", + # "Difficulty": f"{self.D:.0f}", + # "Effort": f"{self.E:.0f}", + # "Time": f"{self.T:.0f}", + # "Estimated Bugs": f"{self.B:.3f}", + # } + ) + + def compute_metrics(self): + # """Compute the Halstead metrics.""" + # if all_operators is None: + # all_operators = self.all_operators + # all_operands = self.all_operands + + # # core metrics + # self.n1 = len(set(all_operators)) + # self.n2 = len(set(all_operands)) + # self.N1 = len(all_operators) + # self.N2 = len(all_operands) + # if any(number <= 0 for number in [self.n1, self.n2, self.N1, self.N2]): + # raise ValueError("n1 and n2 must be greater than 0") + + # # extended metrics 1 + # self.n = self.n1 + self.n2 + # self.N = self.N1 + self.N2 + # self.S = self.n1 * math.log2(self.n1) + self.n2 * math.log2(self.n2) + # self.V = self.N * math.log2(self.n) + + # # extended metrics 2 + # self.D = (self.n1 / 2) * (self.N2 / self.n2) + # self.E = self.D * self.V + # self.T = self.E / 18 + # self.B = (self.E ** (2 / 3)) / 3000 + pass + + +@dataclass +class SectionInfo: + """Class to hold the information for a section of the report.""" + + title: str + pretty_table: MyPrettyTable + txt: str + + +@dataclass +# pylint: disable=too-many-instance-attributes +class TEMPLATEMetrics: + """Class to hold the TEMPLATE metrics for all contracts. Contains methods useful for reporting. + + There are 3 sections in the report: + 1. Core metrics (n1, n2, N1, N2) + 2. Extended metrics 1 (n, N, S, V) + 3. Extended metrics 2 (D, E, T, B) + + """ + + contracts: List[Contract] = field(default_factory=list) + contract_metrics: OrderedDict = field(default_factory=OrderedDict) + title: str = "Halstead complexity metrics" + full_txt: str = "" + # core: SectionInfo = field(default=SectionInfo) + # extended1: SectionInfo = field(default=SectionInfo) + # extended2: SectionInfo = field(default=SectionInfo) + # CORE_KEYS = ( + # "Total Operators", + # "Unique Operators", + # "Total Operands", + # "Unique Operands", + # ) + # EXTENDED1_KEYS = ( + # "Vocabulary", + # "Program Length", + # "Estimated Length", + # "Volume", + # ) + # EXTENDED2_KEYS = ( + # "Difficulty", + # "Effort", + # "Time", + # "Estimated Bugs", + # ) + # SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( + # ("Core", CORE_KEYS), + # ("Extended1", EXTENDED1_KEYS), + # ("Extended2", EXTENDED2_KEYS), + # ) + + def __post_init__(self): + # # Compute the metrics for each contract and for all contracts. + # for contract in self.contracts: + # self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) + + # # If there are more than 1 contract, compute the metrics for all contracts. + # if len(self.contracts) > 1: + # all_operators = [ + # operator + # for contract in self.contracts + # for operator in self.contract_metrics[contract.name].all_operators + # ] + # all_operands = [ + # operand + # for contract in self.contracts + # for operand in self.contract_metrics[contract.name].all_operands + # ] + # self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics( + # None, all_operators=all_operators, all_operands=all_operands + # ) + pass + + # Create the table and text for each section. + data = { + contract.name: self.contract_metrics[contract.name].to_dict() + for contract in self.contracts + } + for (title, keys) in self.SECTIONS: + pretty_table = make_pretty_table(["Contract", *keys], data, False) + section_title = f"{self.title} ({title})" + txt = f"\n\n{section_title}:\n{pretty_table}\n" + self.full_txt += txt + setattr( + self, + title.lower(), + SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), + ) From 8d2e7c40ee58a4f46e8cb69d659cbef4a388bd6f Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 16:51:38 -0700 Subject: [PATCH 131/338] refactor: prefer custom classes to dicts --- slither/printers/summary/martin.py | 128 ++++++++++++++++++++++++++++- slither/utils/halstead.py | 41 +++++---- 2 files changed, 151 insertions(+), 18 deletions(-) diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index 693ec1575..56a04f341 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -9,9 +9,12 @@ Distance from the Main Sequence (D): abs(A + I - 1) """ -from typing import Tuple +from typing import Tuple, List, Dict +from dataclasses import dataclass, field +from collections import OrderedDict from slither.slithir.operations.high_level_call import HighLevelCall -from slither.utils.myprettytable import make_pretty_table +from slither.core.declarations import Contract +from slither.utils.myprettytable import make_pretty_table, MyPrettyTable from slither.printers.abstract_printer import AbstractPrinter @@ -86,6 +89,117 @@ def compute_coupling(contracts: list, abstractness: float) -> dict: } return coupling_dict +@dataclass +class MartinContractMetrics: + contract: Contract + ca: int + ce: int + abstractness: float + i: float = 0.0 + d: float = 0.0 + + def __post_init__(self): + if self.ce + self.ca > 0: + self.i = float(self.ce / (self.ce + self.ca)) + self.d = float(abs(self.i - self.abstractness)) + + def to_dict(self): + return { + "Dependents": self.ca, + "Dependencies": self.ce, + "Instability": f"{self.i:.2f}", + "Distance from main sequence": f"{self.d:.2f}", + } + +@dataclass +class SectionInfo: + """Class to hold the information for a section of the report.""" + + title: str + pretty_table: MyPrettyTable + txt: str + + +@dataclass +class MartinMetrics: + contracts: List[Contract] = field(default_factory=list) + abstractness: float = 0.0 + contract_metrics: OrderedDict = field(default_factory=OrderedDict) + title: str = "Martin complexity metrics" + full_text: str = "" + core: SectionInfo = field(default=SectionInfo) + CORE_KEYS = ( + "Dependents", + "Dependencies", + "Instability", + "Distance from main sequence", + ) + SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( + ("Core", CORE_KEYS), + ) + + def __post_init__(self): + self.update_abstractness() + self.update_coupling() + self.update_reporting_sections() + + def update_reporting_sections(self): + # Create the table and text for each section. + data = { + contract.name: self.contract_metrics[contract.name].to_dict() + for contract in self.contracts + } + for (title, keys) in self.SECTIONS: + pretty_table = make_pretty_table(["Contract", *keys], data, False) + section_title = f"{self.title} ({title})" + txt = f"\n\n{section_title}:\n" + txt = "Martin agile software metrics\n" + txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" + txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" + txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" + txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" + txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" + txt += "\n" + txt += f"Abstractness (overall): {round(self.abstractness, 2)}\n" + txt += f"{pretty_table}\n" + self.full_text += txt + setattr( + self, + title.lower(), + SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), + ) + + def update_abstractness(self) -> float: + abstract_contract_count = 0 + for c in self.contracts: + if not c.is_fully_implemented: + abstract_contract_count += 1 + self.abstractness = float(abstract_contract_count / len(self.contracts)) + + + def update_coupling(self) -> Dict: + dependencies = {} + for contract in self.contracts: + for func in contract.functions: + high_level_calls = [ + ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ] + # convert irs to string with target function and contract name + external_calls = [h.destination.type.type.name for h in high_level_calls] + dependencies[contract.name] = set(external_calls) + dependents = {} + for contract, deps in dependencies.items(): + for dep in deps: + if dep not in dependents: + dependents[dep] = set() + dependents[dep].add(contract) + + coupling_dict = {} + for contract in self.contracts: + ce = len(dependencies.get(contract.name, [])) + ca = len(dependents.get(contract.name, [])) + self.contract_metrics[contract.name] = MartinContractMetrics(contract, ca, ce, self.abstractness) + class Martin(AbstractPrinter): ARGUMENT = "martin" @@ -94,6 +208,16 @@ class Martin(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#martin" def output(self, _filename): + if len(self.contracts) == 0: + return self.generate_output("No contract found") + + martin = MartinMetrics(self.contracts) + + res = self.generate_output(martin.full_text) + res.add_pretty_table(martin.core.pretty_table, martin.core.title) + self.info(martin.full_text) + + (abstract_contract_count, total_contract_count) = count_abstracts(self.contracts) abstractness = float(abstract_contract_count / total_contract_count) coupling_dict = compute_coupling(self.contracts, abstractness) diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index f4426f60a..a152474d0 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -151,7 +151,7 @@ class HalsteadMetrics: contracts: List[Contract] = field(default_factory=list) contract_metrics: OrderedDict = field(default_factory=OrderedDict) title: str = "Halstead complexity metrics" - full_txt: str = "" + full_text: str = "" core: SectionInfo = field(default=SectionInfo) extended1: SectionInfo = field(default=SectionInfo) extended2: SectionInfo = field(default=SectionInfo) @@ -181,25 +181,34 @@ class HalsteadMetrics: def __post_init__(self): # Compute the metrics for each contract and for all contracts. + self.update_contract_metrics() + self.add_all_contracts_metrics() + self.update_reporting_sections() + + def update_contract_metrics(self): for contract in self.contracts: self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) + def add_all_contracts_metrics(self): # If there are more than 1 contract, compute the metrics for all contracts. - if len(self.contracts) > 1: - all_operators = [ - operator - for contract in self.contracts - for operator in self.contract_metrics[contract.name].all_operators - ] - all_operands = [ - operand - for contract in self.contracts - for operand in self.contract_metrics[contract.name].all_operands - ] - self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics( - None, all_operators=all_operators, all_operands=all_operands - ) + if len(self.contracts) <= 1: + return + all_operators = [ + operator + for contract in self.contracts + for operator in self.contract_metrics[contract.name].all_operators + ] + all_operands = [ + operand + for contract in self.contracts + for operand in self.contract_metrics[contract.name].all_operands + ] + self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics( + None, all_operators=all_operators, all_operands=all_operands + ) + + def update_reporting_sections(self): # Create the table and text for each section. data = { contract.name: self.contract_metrics[contract.name].to_dict() @@ -209,7 +218,7 @@ class HalsteadMetrics: pretty_table = make_pretty_table(["Contract", *keys], data, False) section_title = f"{self.title} ({title})" txt = f"\n\n{section_title}:\n{pretty_table}\n" - self.full_txt += txt + self.full_text += txt setattr( self, title.lower(), From c787fb4fbeef2296e1329f01ac32493fbaaac523 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 16:55:37 -0700 Subject: [PATCH 132/338] chore: move Martin logic to utils --- slither/printers/summary/halstead.py | 4 +- slither/printers/summary/martin.py | 211 +-------------------------- slither/utils/martin.py | 130 +++++++++++++++++ 3 files changed, 133 insertions(+), 212 deletions(-) create mode 100644 slither/utils/martin.py diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index f5e4f0a90..8144e467f 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -39,10 +39,10 @@ class Halstead(AbstractPrinter): halstead = HalsteadMetrics(self.contracts) - res = self.generate_output(halstead.full_txt) + res = self.generate_output(halstead.full_text) res.add_pretty_table(halstead.core.pretty_table, halstead.core.title) res.add_pretty_table(halstead.extended1.pretty_table, halstead.extended1.title) res.add_pretty_table(halstead.extended2.pretty_table, halstead.extended2.title) - self.info(halstead.full_txt) + self.info(halstead.full_text) return res diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index 56a04f341..66b14fb90 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -9,197 +9,8 @@ Distance from the Main Sequence (D): abs(A + I - 1) """ -from typing import Tuple, List, Dict -from dataclasses import dataclass, field -from collections import OrderedDict -from slither.slithir.operations.high_level_call import HighLevelCall -from slither.core.declarations import Contract -from slither.utils.myprettytable import make_pretty_table, MyPrettyTable from slither.printers.abstract_printer import AbstractPrinter - - -def count_abstracts(contracts) -> Tuple[int, int]: - """ - Count the number of abstract contracts - Args: - contracts(list): list of contracts - Returns: - a tuple of (abstract_contract_count, total_contract_count) - """ - abstract_contract_count = 0 - for c in contracts: - if not c.is_fully_implemented: - abstract_contract_count += 1 - return (abstract_contract_count, len(contracts)) - - -def compute_coupling(contracts: list, abstractness: float) -> dict: - """ - Used to compute the coupling between contracts external calls made to internal contracts - Args: - contracts: list of contracts - Returns: - dict of contract names with dicts of the coupling metrics: - { - "contract_name1": { - "Dependents": 0, - "Dependencies": 3 - "Instability": 1.0, - "Abstractness": 0.0, - "Distance from main sequence": 1.0, - }, - "contract_name2": { - "Dependents": 1, - "Dependencies": 0 - "Instability": 0.0, - "Abstractness": 1.0, - "Distance from main sequence": 0.0, - } - """ - dependencies = {} - for contract in contracts: - for func in contract.functions: - high_level_calls = [ - ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) - ] - # convert irs to string with target function and contract name - external_calls = [h.destination.type.type.name for h in high_level_calls] - dependencies[contract.name] = set(external_calls) - dependents = {} - for contract, deps in dependencies.items(): - for dep in deps: - if dep not in dependents: - dependents[dep] = set() - dependents[dep].add(contract) - - coupling_dict = {} - for contract in contracts: - ce = len(dependencies.get(contract.name, [])) - ca = len(dependents.get(contract.name, [])) - i = 0.0 - d = 0.0 - if ce + ca > 0: - i = float(ce / (ce + ca)) - d = float(abs(i - abstractness)) - coupling_dict[contract.name] = { - "Dependents": ca, - "Dependencies": ce, - "Instability": f"{i:.2f}", - "Distance from main sequence": f"{d:.2f}", - } - return coupling_dict - -@dataclass -class MartinContractMetrics: - contract: Contract - ca: int - ce: int - abstractness: float - i: float = 0.0 - d: float = 0.0 - - def __post_init__(self): - if self.ce + self.ca > 0: - self.i = float(self.ce / (self.ce + self.ca)) - self.d = float(abs(self.i - self.abstractness)) - - def to_dict(self): - return { - "Dependents": self.ca, - "Dependencies": self.ce, - "Instability": f"{self.i:.2f}", - "Distance from main sequence": f"{self.d:.2f}", - } - -@dataclass -class SectionInfo: - """Class to hold the information for a section of the report.""" - - title: str - pretty_table: MyPrettyTable - txt: str - - -@dataclass -class MartinMetrics: - contracts: List[Contract] = field(default_factory=list) - abstractness: float = 0.0 - contract_metrics: OrderedDict = field(default_factory=OrderedDict) - title: str = "Martin complexity metrics" - full_text: str = "" - core: SectionInfo = field(default=SectionInfo) - CORE_KEYS = ( - "Dependents", - "Dependencies", - "Instability", - "Distance from main sequence", - ) - SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( - ("Core", CORE_KEYS), - ) - - def __post_init__(self): - self.update_abstractness() - self.update_coupling() - self.update_reporting_sections() - - def update_reporting_sections(self): - # Create the table and text for each section. - data = { - contract.name: self.contract_metrics[contract.name].to_dict() - for contract in self.contracts - } - for (title, keys) in self.SECTIONS: - pretty_table = make_pretty_table(["Contract", *keys], data, False) - section_title = f"{self.title} ({title})" - txt = f"\n\n{section_title}:\n" - txt = "Martin agile software metrics\n" - txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" - txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" - txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" - txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" - txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" - txt += "\n" - txt += f"Abstractness (overall): {round(self.abstractness, 2)}\n" - txt += f"{pretty_table}\n" - self.full_text += txt - setattr( - self, - title.lower(), - SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), - ) - - def update_abstractness(self) -> float: - abstract_contract_count = 0 - for c in self.contracts: - if not c.is_fully_implemented: - abstract_contract_count += 1 - self.abstractness = float(abstract_contract_count / len(self.contracts)) - - - def update_coupling(self) -> Dict: - dependencies = {} - for contract in self.contracts: - for func in contract.functions: - high_level_calls = [ - ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) - ] - # convert irs to string with target function and contract name - external_calls = [h.destination.type.type.name for h in high_level_calls] - dependencies[contract.name] = set(external_calls) - dependents = {} - for contract, deps in dependencies.items(): - for dep in deps: - if dep not in dependents: - dependents[dep] = set() - dependents[dep].add(contract) - - coupling_dict = {} - for contract in self.contracts: - ce = len(dependencies.get(contract.name, [])) - ca = len(dependents.get(contract.name, [])) - self.contract_metrics[contract.name] = MartinContractMetrics(contract, ca, ce, self.abstractness) - +from slither.utils.martin import MartinMetrics class Martin(AbstractPrinter): ARGUMENT = "martin" @@ -216,24 +27,4 @@ class Martin(AbstractPrinter): res = self.generate_output(martin.full_text) res.add_pretty_table(martin.core.pretty_table, martin.core.title) self.info(martin.full_text) - - - (abstract_contract_count, total_contract_count) = count_abstracts(self.contracts) - abstractness = float(abstract_contract_count / total_contract_count) - coupling_dict = compute_coupling(self.contracts, abstractness) - - table = make_pretty_table( - ["Contract", *list(coupling_dict[self.contracts[0].name].keys())], coupling_dict - ) - txt = "Martin agile software metrics\n" - txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" - txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" - txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" - txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" - txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" - txt += "\n" - txt += f"Abstractness (overall): {round(abstractness, 2)}\n" + str(table) - self.info(txt) - res = self.generate_output(txt) - res.add_pretty_table(table, "Code Lines") return res diff --git a/slither/utils/martin.py b/slither/utils/martin.py new file mode 100644 index 000000000..2ca38473d --- /dev/null +++ b/slither/utils/martin.py @@ -0,0 +1,130 @@ +""" + Robert "Uncle Bob" Martin - Agile software metrics + https://en.wikipedia.org/wiki/Software_package_metrics + + Efferent Coupling (Ce): Number of contracts that the contract depends on + Afferent Coupling (Ca): Number of contracts that depend on a contract + Instability (I): Ratio of efferent coupling to total coupling (Ce / (Ce + Ca)) + Abstractness (A): Number of abstract contracts / total number of contracts + Distance from the Main Sequence (D): abs(A + I - 1) + +""" +from typing import Tuple, List, Dict +from dataclasses import dataclass, field +from collections import OrderedDict +from slither.slithir.operations.high_level_call import HighLevelCall +from slither.core.declarations import Contract +from slither.utils.myprettytable import make_pretty_table, MyPrettyTable + + +@dataclass +class MartinContractMetrics: + contract: Contract + ca: int + ce: int + abstractness: float + i: float = 0.0 + d: float = 0.0 + + def __post_init__(self): + if self.ce + self.ca > 0: + self.i = float(self.ce / (self.ce + self.ca)) + self.d = float(abs(self.i - self.abstractness)) + + def to_dict(self): + return { + "Dependents": self.ca, + "Dependencies": self.ce, + "Instability": f"{self.i:.2f}", + "Distance from main sequence": f"{self.d:.2f}", + } + +@dataclass +class SectionInfo: + """Class to hold the information for a section of the report.""" + + title: str + pretty_table: MyPrettyTable + txt: str + + +@dataclass +class MartinMetrics: + contracts: List[Contract] = field(default_factory=list) + abstractness: float = 0.0 + contract_metrics: OrderedDict = field(default_factory=OrderedDict) + title: str = "Martin complexity metrics" + full_text: str = "" + core: SectionInfo = field(default=SectionInfo) + CORE_KEYS = ( + "Dependents", + "Dependencies", + "Instability", + "Distance from main sequence", + ) + SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( + ("Core", CORE_KEYS), + ) + + def __post_init__(self): + self.update_abstractness() + self.update_coupling() + self.update_reporting_sections() + + def update_reporting_sections(self): + # Create the table and text for each section. + data = { + contract.name: self.contract_metrics[contract.name].to_dict() + for contract in self.contracts + } + for (title, keys) in self.SECTIONS: + pretty_table = make_pretty_table(["Contract", *keys], data, False) + section_title = f"{self.title} ({title})" + txt = f"\n\n{section_title}:\n" + txt = "Martin agile software metrics\n" + txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" + txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" + txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" + txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" + txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" + txt += "\n" + txt += f"Abstractness (overall): {round(self.abstractness, 2)}\n" + txt += f"{pretty_table}\n" + self.full_text += txt + setattr( + self, + title.lower(), + SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), + ) + + def update_abstractness(self) -> float: + abstract_contract_count = 0 + for c in self.contracts: + if not c.is_fully_implemented: + abstract_contract_count += 1 + self.abstractness = float(abstract_contract_count / len(self.contracts)) + + + def update_coupling(self) -> Dict: + dependencies = {} + for contract in self.contracts: + for func in contract.functions: + high_level_calls = [ + ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ] + # convert irs to string with target function and contract name + external_calls = [h.destination.type.type.name for h in high_level_calls] + dependencies[contract.name] = set(external_calls) + dependents = {} + for contract, deps in dependencies.items(): + for dep in deps: + if dep not in dependents: + dependents[dep] = set() + dependents[dep].add(contract) + + coupling_dict = {} + for contract in self.contracts: + ce = len(dependencies.get(contract.name, [])) + ca = len(dependents.get(contract.name, [])) + self.contract_metrics[contract.name] = MartinContractMetrics(contract, ca, ce, self.abstractness) + From 2e99e498f0d82d01de92ad38e763773d7e365beb Mon Sep 17 00:00:00 2001 From: devtooligan Date: Thu, 6 Jul 2023 16:59:57 -0700 Subject: [PATCH 133/338] chore: lint --- slither/printers/summary/martin.py | 1 + slither/utils/halstead.py | 1 - slither/utils/martin.py | 21 ++++++++++++--------- slither/utils/myprettytable.py | 1 + 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index 66b14fb90..c49e63fcb 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -12,6 +12,7 @@ from slither.printers.abstract_printer import AbstractPrinter from slither.utils.martin import MartinMetrics + class Martin(AbstractPrinter): ARGUMENT = "martin" HELP = "Martin agile software metrics (Ca, Ce, I, A, D)" diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index a152474d0..93552c9cd 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -207,7 +207,6 @@ class HalsteadMetrics: None, all_operators=all_operators, all_operands=all_operands ) - def update_reporting_sections(self): # Create the table and text for each section. data = { diff --git a/slither/utils/martin.py b/slither/utils/martin.py index 2ca38473d..ded8c0efa 100644 --- a/slither/utils/martin.py +++ b/slither/utils/martin.py @@ -39,6 +39,7 @@ class MartinContractMetrics: "Distance from main sequence": f"{self.d:.2f}", } + @dataclass class SectionInfo: """Class to hold the information for a section of the report.""" @@ -62,9 +63,7 @@ class MartinMetrics: "Instability", "Distance from main sequence", ) - SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( - ("Core", CORE_KEYS), - ) + SECTIONS: Tuple[Tuple[str, Tuple[str]]] = (("Core", CORE_KEYS),) def __post_init__(self): self.update_abstractness() @@ -84,7 +83,9 @@ class MartinMetrics: txt = "Martin agile software metrics\n" txt += "Efferent Coupling (Ce) - Number of contracts that a contract depends on\n" txt += "Afferent Coupling (Ca) - Number of contracts that depend on the contract\n" - txt += "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" + txt += ( + "Instability (I) - Ratio of efferent coupling to total coupling (Ce / (Ce + Ca))\n" + ) txt += "Abstractness (A) - Number of abstract contracts / total number of contracts\n" txt += "Distance from the Main Sequence (D) - abs(A + I - 1)\n" txt += "\n" @@ -104,13 +105,15 @@ class MartinMetrics: abstract_contract_count += 1 self.abstractness = float(abstract_contract_count / len(self.contracts)) - def update_coupling(self) -> Dict: dependencies = {} for contract in self.contracts: for func in contract.functions: high_level_calls = [ - ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ir + for node in func.nodes + for ir in node.irs_ssa + if isinstance(ir, HighLevelCall) ] # convert irs to string with target function and contract name external_calls = [h.destination.type.type.name for h in high_level_calls] @@ -122,9 +125,9 @@ class MartinMetrics: dependents[dep] = set() dependents[dep].add(contract) - coupling_dict = {} for contract in self.contracts: ce = len(dependencies.get(contract.name, [])) ca = len(dependents.get(contract.name, [])) - self.contract_metrics[contract.name] = MartinContractMetrics(contract, ca, ce, self.abstractness) - + self.contract_metrics[contract.name] = MartinContractMetrics( + contract, ca, ce, self.abstractness + ) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index b33164894..e45edeaf1 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -26,6 +26,7 @@ class MyPrettyTable: # **Dict to MyPrettyTable utility functions** + def make_pretty_table(headers: list, body: dict, totals: bool = False) -> MyPrettyTable: """ Converts a dict to a MyPrettyTable. Dict keys are the row headers. From 8c51e47a42d25d00379d3c883f4a876c62122315 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 11:25:51 -0700 Subject: [PATCH 134/338] Update scripts/ci_test_printers.sh Co-authored-by: alpharush <0xalpharush@protonmail.com> --- scripts/ci_test_printers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index 90d1b0e03..329c415c6 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,7 +5,7 @@ cd tests/e2e/solc_parsing/test_data/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,halstead,human-summary,inheritance,inheritance-graph,loc, slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,halstead,human-summary,inheritance,inheritance-graph,loc,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 From 56993490dd1de85a2fa1bde1d97cd17989beb1c5 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 11:29:22 -0700 Subject: [PATCH 135/338] fix: typo --- scripts/ci_test_printers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index 90d1b0e03..329c415c6 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,7 +5,7 @@ cd tests/e2e/solc_parsing/test_data/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,halstead,human-summary,inheritance,inheritance-graph,loc, slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,halstead,human-summary,inheritance,inheritance-graph,loc,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 From 4a3ab0a6538e0ecd6f562449a095722fe95a91c8 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 11:30:39 -0700 Subject: [PATCH 136/338] fix: add martin printer to testing printer list --- scripts/ci_test_printers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index 329c415c6..e7310700e 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,7 +5,7 @@ cd tests/e2e/solc_parsing/test_data/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,halstead,human-summary,inheritance,inheritance-graph,loc,slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,halstead,human-summary,inheritance,inheritance-graph,loc,martin,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 From 42cd6e0ecfae92f31d57ae1316b62925e3007ede Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 12:13:22 -0700 Subject: [PATCH 137/338] fix: account for case w no functions --- slither/utils/halstead.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index f4426f60a..829dc8035 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -86,6 +86,8 @@ class HalsteadContractMetrics: """Populate the operators and operands lists.""" operators = [] operands = [] + if not hasattr(self.contract, "functions"): + return for func in self.contract.functions: for node in func.nodes: for operation in node.irs: From 8d483ed471a7c630f8a4c0b694a2d7e2d196f4c2 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 12:37:07 -0700 Subject: [PATCH 138/338] fix: external calls --- slither/utils/martin.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/slither/utils/martin.py b/slither/utils/martin.py index ded8c0efa..16e3e13e8 100644 --- a/slither/utils/martin.py +++ b/slither/utils/martin.py @@ -105,9 +105,11 @@ class MartinMetrics: abstract_contract_count += 1 self.abstractness = float(abstract_contract_count / len(self.contracts)) + # pylint: disable=too-many-branches def update_coupling(self) -> Dict: dependencies = {} for contract in self.contracts: + external_calls = [] for func in contract.functions: high_level_calls = [ ir @@ -116,7 +118,27 @@ class MartinMetrics: if isinstance(ir, HighLevelCall) ] # convert irs to string with target function and contract name - external_calls = [h.destination.type.type.name for h in high_level_calls] + # Get the target contract name for each high level call + new_external_calls = [] + for high_level_call in high_level_calls: + if isinstance(high_level_call.destination, Contract): + new_external_call = high_level_call.destination.name + elif isinstance(high_level_call.destination, str): + new_external_call = high_level_call.destination + elif not hasattr(high_level_call.destination, "type"): + continue + elif isinstance(high_level_call.destination.type, Contract): + new_external_call = high_level_call.destination.type.name + elif isinstance(high_level_call.destination.type, str): + new_external_call = high_level_call.destination.type + elif not hasattr(high_level_call.destination.type, "type"): + continue + if isinstance(high_level_call.destination.type.type, Contract): + new_external_call = high_level_call.destination.type.type.name + if isinstance(high_level_call.destination.type.type, str): + new_external_call = high_level_call.destination.type.type + new_external_calls.append(new_external_call) + external_calls.extend(new_external_calls) dependencies[contract.name] = set(external_calls) dependents = {} for contract, deps in dependencies.items(): From 6843d03da43a984698ad493efe3de262246520e4 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 12:37:07 -0700 Subject: [PATCH 139/338] fix: external calls --- slither/utils/martin.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/slither/utils/martin.py b/slither/utils/martin.py index ded8c0efa..7d39b2c14 100644 --- a/slither/utils/martin.py +++ b/slither/utils/martin.py @@ -105,9 +105,11 @@ class MartinMetrics: abstract_contract_count += 1 self.abstractness = float(abstract_contract_count / len(self.contracts)) + # pylint: disable=too-many-branches def update_coupling(self) -> Dict: dependencies = {} for contract in self.contracts: + external_calls = [] for func in contract.functions: high_level_calls = [ ir @@ -116,7 +118,29 @@ class MartinMetrics: if isinstance(ir, HighLevelCall) ] # convert irs to string with target function and contract name - external_calls = [h.destination.type.type.name for h in high_level_calls] + # Get the target contract name for each high level call + new_external_calls = [] + for high_level_call in high_level_calls: + if isinstance(high_level_call.destination, Contract): + new_external_call = high_level_call.destination.name + elif isinstance(high_level_call.destination, str): + new_external_call = high_level_call.destination + elif not hasattr(high_level_call.destination, "type"): + continue + elif isinstance(high_level_call.destination.type, Contract): + new_external_call = high_level_call.destination.type.name + elif isinstance(high_level_call.destination.type, str): + new_external_call = high_level_call.destination.type + elif not hasattr(high_level_call.destination.type, "type"): + continue + elif isinstance(high_level_call.destination.type.type, Contract): + new_external_call = high_level_call.destination.type.type.name + elif isinstance(high_level_call.destination.type.type, str): + new_external_call = high_level_call.destination.type.type + else: + continue + new_external_calls.append(new_external_call) + external_calls.extend(new_external_calls) dependencies[contract.name] = set(external_calls) dependents = {} for contract, deps in dependencies.items(): From a35dff3a15b47ca75391029838aeddf5a6175ce2 Mon Sep 17 00:00:00 2001 From: devtooligan Date: Fri, 7 Jul 2023 16:31:36 -0700 Subject: [PATCH 140/338] refactor: ck --- slither/printers/summary/ck.py | 269 ++------------------- slither/utils/ck.py | 413 ++++++++++++++++++++++++--------- slither/utils/halstead.py | 18 +- slither/utils/martin.py | 6 +- slither/utils/myprettytable.py | 1 + 5 files changed, 334 insertions(+), 373 deletions(-) diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index 27f6dd06d..f7a851039 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -14,214 +14,24 @@ During the calculation of the metrics above, there are a number of other intermediate metrics that are calculated. These are also included in the output: - TODO!!! + - State variables: total number of state variables + - Constants: total number of constants + - Immutables: total number of immutables + - Public: total number of public functions + - External: total number of external functions + - Internal: total number of internal functions + - Private: total number of private functions + - Mutating: total number of state mutating functions + - View: total number of view functions + - Pure: total number of pure functions + - External mutating: total number of external mutating functions + - No auth or onlyOwner: total number of functions without auth or onlyOwner modifiers + - No modifiers: total number of functions without modifiers + - Ext calls: total number of external calls """ -from typing import Tuple -from slither.utils.colors import bold -from slither.utils.myprettytable import make_pretty_table -from slither.slithir.operations.high_level_call import HighLevelCall from slither.printers.abstract_printer import AbstractPrinter -from slither.utils.martin import MartinMetrics - - -def compute_dit(contract, depth=0): - """ - Recursively compute the depth of inheritance tree (DIT) of a contract - Args: - contract: Contract - the contract to compute the DIT for - depth: int - the depth of the contract in the inheritance tree - Returns: - the depth of the contract in the inheritance tree - """ - if not contract.inheritance: - return depth - max_dit = depth - for inherited_contract in contract.inheritance: - dit = compute_dit(inherited_contract, depth + 1) - max_dit = max(max_dit, dit) - return max_dit - - -# pylint: disable=too-many-locals -def compute_metrics(contracts): - """ - Compute CK metrics of a contract - Args: - contracts(list): list of contracts - Returns: - a tuple of (metrics1, metrics2, metrics3, metrics4, metrics5) - # Visbility - metrics1["contract name"] = { - "State variables":int, - "Constants":int, - "Immutables":int, - } - metrics2["contract name"] = { - "Public": int, - "External":int, - "Internal":int, - "Private":int, - } - # Mutability - metrics3["contract name"] = { - "Mutating":int, - "View":int, - "Pure":int, - } - # External facing, mutating: total / no auth / no modifiers - metrics4["contract name"] = { - "External mutating":int, - "No auth or onlyOwner":int, - "No modifiers":int, - } - metrics5["contract name"] = { - "Ext calls":int, - "Response For a Class":int, - "NOC":int, - "DIT":int, - } - - RFC is counted as follows: - +1 for each public or external fn - +1 for each public getter - +1 for each UNIQUE external call - - """ - metrics1 = {} - metrics2 = {} - metrics3 = {} - metrics4 = {} - metrics5 = {} - dependents = { - inherited.name: { - contract.name for contract in contracts if inherited.name in contract.inheritance - } - for inherited in contracts - } - - # Use MartinMetrics to compute Ca and Ce - martin = MartinMetrics(contracts) - - for contract in contracts: - (state_variables, constants, immutables, public_getters) = count_variables(contract) - rfc = public_getters # add 1 for each public getter - metrics1[contract.name] = { - "State variables": state_variables, - "Constants": constants, - "Immutables": immutables, - } - metrics2[contract.name] = { - "Public": 0, - "External": 0, - "Internal": 0, - "Private": 0, - } - metrics3[contract.name] = { - "Mutating": 0, - "View": 0, - "Pure": 0, - } - metrics4[contract.name] = { - "External mutating": 0, - "No auth or onlyOwner": 0, - "No modifiers": 0, - } - metrics5[contract.name] = { - "Ext calls": 0, - "RFC": 0, - "NOC": len(dependents[contract.name]), - "DIT": compute_dit(contract), - "CBO": coupling[contract.name]["Dependents"] + coupling[contract.name]["Dependencies"], - } - for func in contract.functions: - if func.name == "constructor": - continue - pure = func.pure - view = not pure and func.view - mutating = not pure and not view - external = func.visibility == "external" - public = func.visibility == "public" - internal = func.visibility == "internal" - private = func.visibility == "private" - external_public_mutating = external or public and mutating - external_no_auth = external_public_mutating and no_auth(func) - external_no_modifiers = external_public_mutating and len(func.modifiers) == 0 - if external or public: - rfc += 1 - - high_level_calls = [ - ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) - ] - - # convert irs to string with target function and contract name - external_calls = [] - for high_level_call in high_level_calls: - if hasattr(high_level_call.destination, "name"): - external_calls.append( - f"{high_level_call.function_name}{high_level_call.destination.name}" - ) - else: - external_calls.append( - f"{high_level_call.function_name}{high_level_call.destination.type.type.name}" - ) - - rfc += len(set(external_calls)) - - metrics2[contract.name]["Public"] += 1 if public else 0 - metrics2[contract.name]["External"] += 1 if external else 0 - metrics2[contract.name]["Internal"] += 1 if internal else 0 - metrics2[contract.name]["Private"] += 1 if private else 0 - - metrics3[contract.name]["Mutating"] += 1 if mutating else 0 - metrics3[contract.name]["View"] += 1 if view else 0 - metrics3[contract.name]["Pure"] += 1 if pure else 0 - - metrics4[contract.name]["External mutating"] += 1 if external_public_mutating else 0 - metrics4[contract.name]["No auth or onlyOwner"] += 1 if external_no_auth else 0 - metrics4[contract.name]["No modifiers"] += 1 if external_no_modifiers else 0 - - metrics5[contract.name]["Ext calls"] += len(external_calls) - metrics5[contract.name]["RFC"] = rfc - - return metrics1, metrics2, metrics3, metrics4, metrics5 - - -def count_variables(contract) -> Tuple[int, int, int, int]: - """Count the number of variables in a contract - Args: - contract(core.declarations.contract.Contract): contract to count variables - Returns: - Tuple of (state_variable_count, constant_count, immutable_count, public_getter) - """ - state_variable_count = 0 - constant_count = 0 - immutable_count = 0 - public_getter = 0 - for var in contract.variables: - if var.is_constant: - constant_count += 1 - elif var.is_immutable: - immutable_count += 1 - else: - state_variable_count += 1 - if var.visibility == "Public": - public_getter += 1 - return (state_variable_count, constant_count, immutable_count, public_getter) - - -def no_auth(func) -> bool: - """ - Check if a function has no auth or only_owner modifiers - Args: - func(core.declarations.function.Function): function to check - Returns: - bool - """ - for modifier in func.modifiers: - if "auth" in modifier.name or "only_owner" in modifier.name: - return False - return True +from slither.utils.ck import CKMetrics class CK(AbstractPrinter): @@ -233,48 +43,15 @@ class CK(AbstractPrinter): def output(self, _filename): if len(self.contracts) == 0: return self.generate_output("No contract found") - metrics1, metrics2, metrics3, metrics4, metrics5 = compute_metrics(self.contracts) - txt = bold("\nCK complexity metrics\n") - # metrics2: variable counts - txt += bold("\nVariables\n") - keys = list(metrics1[self.contracts[0].name].keys()) - table0 = make_pretty_table(["Contract", *keys], metrics1, True) - txt += str(table0) + "\n" - - # metrics3: function visibility - txt += bold("\nFunction visibility\n") - keys = list(metrics2[self.contracts[0].name].keys()) - table1 = make_pretty_table(["Contract", *keys], metrics2, True) - txt += str(table1) + "\n" - - # metrics4: function mutability counts - txt += bold("\nState mutability\n") - keys = list(metrics3[self.contracts[0].name].keys()) - table2 = make_pretty_table(["Contract", *keys], metrics3, True) - txt += str(table2) + "\n" - - # metrics5: external facing mutating functions - txt += bold("\nExternal/Public functions with modifiers\n") - keys = list(metrics4[self.contracts[0].name].keys()) - table3 = make_pretty_table(["Contract", *keys], metrics4, True) - txt += str(table3) + "\n" - # metrics5: ext calls and ck metrics - txt += bold("\nExternal calls and CK Metrics:\n") - txt += bold("Response For a Class (RFC)\n") - txt += bold("Number of Children (NOC)\n") - txt += bold("Depth of Inheritance Tree (DIT)\n") - txt += bold("Coupling Between Object Classes (CBO)\n") - keys = list(metrics5[self.contracts[0].name].keys()) - table4 = make_pretty_table(["Contract", *keys], metrics5, False) - txt += str(table4) + "\n" + ck = CKMetrics(self.contracts) - res = self.generate_output(txt) - res.add_pretty_table(table0, "CK complexity core metrics 1/5") - res.add_pretty_table(table1, "CK complexity core metrics 2/5") - res.add_pretty_table(table2, "CK complexity core metrics 3/5") - res.add_pretty_table(table3, "CK complexity core metrics 4/5") - res.add_pretty_table(table4, "CK complexity core metrics 5/5") - self.info(txt) + res = self.generate_output(ck.full_text) + res.add_pretty_table(ck.auxiliary1.pretty_table, ck.auxiliary1.title) + res.add_pretty_table(ck.auxiliary2.pretty_table, ck.auxiliary2.title) + res.add_pretty_table(ck.auxiliary3.pretty_table, ck.auxiliary3.title) + res.add_pretty_table(ck.auxiliary4.pretty_table, ck.auxiliary4.title) + res.add_pretty_table(ck.core.pretty_table, ck.core.title) + self.info(ck.full_text) return res diff --git a/slither/utils/ck.py b/slither/utils/ck.py index d3c573521..7b0d1afd9 100644 --- a/slither/utils/ck.py +++ b/slither/utils/ck.py @@ -1,79 +1,239 @@ """ -Description + CK Metrics are a suite of six software metrics proposed by Chidamber and Kemerer in 1994. + These metrics are used to measure the complexity of a class. + https://en.wikipedia.org/wiki/Programming_complexity + + - Response For a Class (RFC) is a metric that measures the number of unique method calls within a class. + - Number of Children (NOC) is a metric that measures the number of children a class has. + - Depth of Inheritance Tree (DIT) is a metric that measures the number of parent classes a class has. + - Coupling Between Object Classes (CBO) is a metric that measures the number of classes a class is coupled to. + + Not implemented: + - Lack of Cohesion of Methods (LCOM) is a metric that measures the lack of cohesion in methods. + - Weighted Methods per Class (WMC) is a metric that measures the complexity of a class. + + During the calculation of the metrics above, there are a number of other intermediate metrics that are calculated. + These are also included in the output: + - State variables: total number of state variables + - Constants: total number of constants + - Immutables: total number of immutables + - Public: total number of public functions + - External: total number of external functions + - Internal: total number of internal functions + - Private: total number of private functions + - Mutating: total number of state mutating functions + - View: total number of view functions + - Pure: total number of pure functions + - External mutating: total number of external mutating functions + - No auth or onlyOwner: total number of functions without auth or onlyOwner modifiers + - No modifiers: total number of functions without modifiers + - Ext calls: total number of external calls """ -import math -from dataclasses import dataclass, field -from typing import Tuple, List, Dict from collections import OrderedDict +from typing import Tuple, List, Dict +from dataclasses import dataclass, field +from slither.utils.colors import bold from slither.core.declarations import Contract -from slither.slithir.variables.temporary import TemporaryVariable from slither.utils.myprettytable import make_pretty_table, MyPrettyTable -from slither.utils.upgradeability import encode_ir_for_halstead +from slither.utils.martin import MartinMetrics +from slither.slithir.operations.high_level_call import HighLevelCall + + +# Utility functions + + +def compute_dit(contract: Contract, depth: int = 0) -> int: + """ + Recursively compute the depth of inheritance tree (DIT) of a contract + Args: + contract(core.declarations.contract.Contract): contract to compute DIT for + depth(int): current depth of the contract + Returns: + int: depth of the contract + """ + if not contract.inheritance: + return depth + max_dit = depth + for inherited_contract in contract.inheritance: + dit = compute_dit(inherited_contract, depth + 1) + max_dit = max(max_dit, dit) + return max_dit + + +def has_auth(func) -> bool: + """ + Check if a function has no auth or only_owner modifiers + Args: + func(core.declarations.function.Function): function to check + Returns: + bool True if it does have auth or only_owner modifiers + """ + for modifier in func.modifiers: + if "auth" in modifier.name or "only_owner" in modifier.name: + return True + return False + + +# Utility classes for calculating CK metrics @dataclass # pylint: disable=too-many-instance-attributes -class TEMPLATEContractMetrics: - """Class to hold the TEMPLATE metrics for a single contract.""" +class CKContractMetrics: + """Class to hold the CK metrics for a single contract.""" contract: Contract + # Used to calculate CBO - should be passed in as a constructor arg + martin_metrics: Dict + + # Used to calculate NOC + dependents: Dict + + state_variables: int = 0 + constants: int = 0 + immutables: int = 0 + public: int = 0 + external: int = 0 + internal: int = 0 + private: int = 0 + mutating: int = 0 + view: int = 0 + pure: int = 0 + external_mutating: int = 0 + no_auth_or_only_owner: int = 0 + no_modifiers: int = 0 + ext_calls: int = 0 + rfc: int = 0 + noc: int = 0 + dit: int = 0 + cbo: int = 0 + def __post_init__(self): - # """Operators and operands can be passed in as constructor args to avoid computing - # them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" - # if len(self.all_operators) == 0: - # self.populate_operators_and_operands() - # if len(self.all_operators) > 0: - # self.compute_metrics() - pass + if not hasattr(self.contract, "functions"): + return + self.count_variables() + self.noc = len(self.dependents[self.contract.name]) + self.dit = compute_dit(self.contract) + self.cbo = ( + self.martin_metrics[self.contract.name].ca + self.martin_metrics[self.contract.name].ce + ) + self.calculate_metrics() + + # pylint: disable=too-many-locals + # pylint: disable=too-many-branches + def calculate_metrics(self): + """Calculate the metrics for a contract""" + rfc = self.public # initialize with public getter count + for func in self.contract.functions: + if func.name == "constructor": + continue + pure = func.pure + view = not pure and func.view + mutating = not pure and not view + external = func.visibility == "external" + public = func.visibility == "public" + internal = func.visibility == "internal" + private = func.visibility == "private" + external_public_mutating = external or public and mutating + external_no_auth = external_public_mutating and not has_auth(func) + external_no_modifiers = external_public_mutating and len(func.modifiers) == 0 + if external or public: + rfc += 1 + + high_level_calls = [ + ir for node in func.nodes for ir in node.irs_ssa if isinstance(ir, HighLevelCall) + ] + + # convert irs to string with target function and contract name + external_calls = [] + for high_level_call in high_level_calls: + if isinstance(high_level_call.destination, Contract): + destination_contract = high_level_call.destination.name + elif isinstance(high_level_call.destination, str): + destination_contract = high_level_call.destination + elif not hasattr(high_level_call.destination, "type"): + continue + elif isinstance(high_level_call.destination.type, Contract): + destination_contract = high_level_call.destination.type.name + elif isinstance(high_level_call.destination.type, str): + destination_contract = high_level_call.destination.type + elif not hasattr(high_level_call.destination.type, "type"): + continue + elif isinstance(high_level_call.destination.type.type, Contract): + destination_contract = high_level_call.destination.type.type.name + elif isinstance(high_level_call.destination.type.type, str): + destination_contract = high_level_call.destination.type.type + else: + continue + external_calls.append(f"{high_level_call.function_name}{destination_contract}") + rfc += len(set(external_calls)) + + self.public += public + self.external += external + self.internal += internal + self.private += private + + self.mutating += mutating + self.view += view + self.pure += pure + + self.external_mutating += external_public_mutating + self.no_auth_or_only_owner += external_no_auth + self.no_modifiers += external_no_modifiers + + self.ext_calls += len(external_calls) + self.rfc = rfc + + def count_variables(self): + """Count the number of variables in a contract""" + state_variable_count = 0 + constant_count = 0 + immutable_count = 0 + public_getter_count = 0 + for variable in self.contract.variables: + if variable.is_constant: + constant_count += 1 + elif variable.is_immutable: + immutable_count += 1 + else: + state_variable_count += 1 + if variable.visibility == "Public": + public_getter_count += 1 + self.state_variables = state_variable_count + self.constants = constant_count + self.immutables = immutable_count + + # initialize RFC with public getter count + # self.public is used count public functions not public variables + self.rfc = public_getter_count def to_dict(self) -> Dict[str, float]: """Return the metrics as a dictionary.""" return OrderedDict( - # { - # "Total Operators": self.N1, - # "Unique Operators": self.n1, - # "Total Operands": self.N2, - # "Unique Operands": self.n2, - # "Vocabulary": str(self.n1 + self.n2), - # "Program Length": str(self.N1 + self.N2), - # "Estimated Length": f"{self.S:.0f}", - # "Volume": f"{self.V:.0f}", - # "Difficulty": f"{self.D:.0f}", - # "Effort": f"{self.E:.0f}", - # "Time": f"{self.T:.0f}", - # "Estimated Bugs": f"{self.B:.3f}", - # } + { + "State variables": self.state_variables, + "Constants": self.constants, + "Immutables": self.immutables, + "Public": self.public, + "External": self.external, + "Internal": self.internal, + "Private": self.private, + "Mutating": self.mutating, + "View": self.view, + "Pure": self.pure, + "External mutating": self.external_mutating, + "No auth or onlyOwner": self.no_auth_or_only_owner, + "No modifiers": self.no_modifiers, + "Ext calls": self.ext_calls, + "RFC": self.rfc, + "NOC": self.noc, + "DIT": self.dit, + "CBO": self.cbo, + } ) - def compute_metrics(self): - # """Compute the Halstead metrics.""" - # if all_operators is None: - # all_operators = self.all_operators - # all_operands = self.all_operands - - # # core metrics - # self.n1 = len(set(all_operators)) - # self.n2 = len(set(all_operands)) - # self.N1 = len(all_operators) - # self.N2 = len(all_operands) - # if any(number <= 0 for number in [self.n1, self.n2, self.N1, self.N2]): - # raise ValueError("n1 and n2 must be greater than 0") - - # # extended metrics 1 - # self.n = self.n1 + self.n2 - # self.N = self.N1 + self.N2 - # self.S = self.n1 * math.log2(self.n1) + self.n2 * math.log2(self.n2) - # self.V = self.N * math.log2(self.n) - - # # extended metrics 2 - # self.D = (self.n1 / 2) * (self.N2 / self.n2) - # self.E = self.D * self.V - # self.T = self.E / 18 - # self.B = (self.E ** (2 / 3)) / 3000 - pass - @dataclass class SectionInfo: @@ -86,81 +246,102 @@ class SectionInfo: @dataclass # pylint: disable=too-many-instance-attributes -class TEMPLATEMetrics: - """Class to hold the TEMPLATE metrics for all contracts. Contains methods useful for reporting. - - There are 3 sections in the report: - 1. Core metrics (n1, n2, N1, N2) - 2. Extended metrics 1 (n, N, S, V) - 3. Extended metrics 2 (D, E, T, B) +class CKMetrics: + """Class to hold the CK metrics for all contracts. Contains methods useful for reporting. + There are 5 sections in the report: + 1. Variable count by type (state, constant, immutable) + 2. Function count by visibility (public, external, internal, private) + 3. Function count by mutability (mutating, view, pure) + 4. External mutating function count by modifier (external mutating, no auth or onlyOwner, no modifiers) + 5. CK metrics (RFC, NOC, DIT, CBO) """ contracts: List[Contract] = field(default_factory=list) contract_metrics: OrderedDict = field(default_factory=OrderedDict) - title: str = "Halstead complexity metrics" - full_txt: str = "" - # core: SectionInfo = field(default=SectionInfo) - # extended1: SectionInfo = field(default=SectionInfo) - # extended2: SectionInfo = field(default=SectionInfo) - # CORE_KEYS = ( - # "Total Operators", - # "Unique Operators", - # "Total Operands", - # "Unique Operands", - # ) - # EXTENDED1_KEYS = ( - # "Vocabulary", - # "Program Length", - # "Estimated Length", - # "Volume", - # ) - # EXTENDED2_KEYS = ( - # "Difficulty", - # "Effort", - # "Time", - # "Estimated Bugs", - # ) - # SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( - # ("Core", CORE_KEYS), - # ("Extended1", EXTENDED1_KEYS), - # ("Extended2", EXTENDED2_KEYS), - # ) + title: str = "CK complexity metrics" + full_text: str = "" + auxiliary1: SectionInfo = field(default=SectionInfo) + auxiliary2: SectionInfo = field(default=SectionInfo) + auxiliary3: SectionInfo = field(default=SectionInfo) + auxiliary4: SectionInfo = field(default=SectionInfo) + core: SectionInfo = field(default=SectionInfo) + AUXILIARY1_KEYS = ( + "State variables", + "Constants", + "Immutables", + ) + AUXILIARY2_KEYS = ( + "Public", + "External", + "Internal", + "Private", + ) + AUXILIARY3_KEYS = ( + "Mutating", + "View", + "Pure", + ) + AUXILIARY4_KEYS = ( + "External mutating", + "No auth or onlyOwner", + "No modifiers", + ) + CORE_KEYS = ( + "Ext calls", + "RFC", + "NOC", + "DIT", + "CBO", + ) + SECTIONS: Tuple[Tuple[str, str, Tuple[str]]] = ( + ("Variables", "auxiliary1", AUXILIARY1_KEYS), + ("Function visibility", "auxiliary2", AUXILIARY2_KEYS), + ("State mutability", "auxiliary3", AUXILIARY3_KEYS), + ("External mutating functions", "auxiliary4", AUXILIARY4_KEYS), + ("Core", "core", CORE_KEYS), + ) def __post_init__(self): - # # Compute the metrics for each contract and for all contracts. - # for contract in self.contracts: - # self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) - - # # If there are more than 1 contract, compute the metrics for all contracts. - # if len(self.contracts) > 1: - # all_operators = [ - # operator - # for contract in self.contracts - # for operator in self.contract_metrics[contract.name].all_operators - # ] - # all_operands = [ - # operand - # for contract in self.contracts - # for operand in self.contract_metrics[contract.name].all_operands - # ] - # self.contract_metrics["ALL CONTRACTS"] = HalsteadContractMetrics( - # None, all_operators=all_operators, all_operands=all_operands - # ) - pass + martin_metrics = MartinMetrics(self.contracts).contract_metrics + dependents = { + inherited.name: { + contract.name + for contract in self.contracts + if inherited.name in contract.inheritance + } + for inherited in self.contracts + } + for contract in self.contracts: + self.contract_metrics[contract.name] = CKContractMetrics( + contract=contract, martin_metrics=martin_metrics, dependents=dependents + ) # Create the table and text for each section. data = { contract.name: self.contract_metrics[contract.name].to_dict() for contract in self.contracts } - for (title, keys) in self.SECTIONS: - pretty_table = make_pretty_table(["Contract", *keys], data, False) + + # Update each section + for (title, attr, keys) in self.SECTIONS: + if attr == "core": + # Special handling for core section + totals_enabled = False + subtitle += bold("RFC: Response For a Class\n") + subtitle += bold("NOC: Number of Children\n") + subtitle += bold("DIT: Depth of Inheritance Tree\n") + subtitle += bold("CBO: Coupling Between Object Classes\n") + else: + totals_enabled = True + subtitle = "" + + pretty_table = make_pretty_table(["Contract", *keys], data, totals=totals_enabled) section_title = f"{self.title} ({title})" - txt = f"\n\n{section_title}:\n{pretty_table}\n" - self.full_txt += txt + txt = f"\n\n{section_title}:\n{subtitle}{pretty_table}\n" + self.full_text += txt setattr( self, - title.lower(), + attr, SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), ) diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index a5ab41cc9..64dd1f6a1 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -58,7 +58,10 @@ class HalsteadContractMetrics: def __post_init__(self): """Operators and operands can be passed in as constructor args to avoid computing them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" + if len(self.all_operators) == 0: + if not hasattr(self.contract, "functions"): + return self.populate_operators_and_operands() if len(self.all_operators) > 0: self.compute_metrics() @@ -86,8 +89,7 @@ class HalsteadContractMetrics: """Populate the operators and operands lists.""" operators = [] operands = [] - if not hasattr(self.contract, "functions"): - return + for func in self.contract.functions: for node in func.nodes: for operation in node.irs: @@ -175,10 +177,10 @@ class HalsteadMetrics: "Time", "Estimated Bugs", ) - SECTIONS: Tuple[Tuple[str, Tuple[str]]] = ( - ("Core", CORE_KEYS), - ("Extended1", EXTENDED1_KEYS), - ("Extended2", EXTENDED2_KEYS), + SECTIONS: Tuple[Tuple[str, str, Tuple[str]]] = ( + ("Core", "core", CORE_KEYS), + ("Extended 1/2", "extended1", EXTENDED1_KEYS), + ("Extended 2/2", "extended2", EXTENDED2_KEYS), ) def __post_init__(self): @@ -215,13 +217,13 @@ class HalsteadMetrics: contract.name: self.contract_metrics[contract.name].to_dict() for contract in self.contracts } - for (title, keys) in self.SECTIONS: + for (title, attr, keys) in self.SECTIONS: pretty_table = make_pretty_table(["Contract", *keys], data, False) section_title = f"{self.title} ({title})" txt = f"\n\n{section_title}:\n{pretty_table}\n" self.full_text += txt setattr( self, - title.lower(), + attr, SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), ) diff --git a/slither/utils/martin.py b/slither/utils/martin.py index 7d39b2c14..fb62a4c58 100644 --- a/slither/utils/martin.py +++ b/slither/utils/martin.py @@ -63,7 +63,7 @@ class MartinMetrics: "Instability", "Distance from main sequence", ) - SECTIONS: Tuple[Tuple[str, Tuple[str]]] = (("Core", CORE_KEYS),) + SECTIONS: Tuple[Tuple[str, str, Tuple[str]]] = (("Core", "core", CORE_KEYS),) def __post_init__(self): self.update_abstractness() @@ -76,7 +76,7 @@ class MartinMetrics: contract.name: self.contract_metrics[contract.name].to_dict() for contract in self.contracts } - for (title, keys) in self.SECTIONS: + for (title, attr, keys) in self.SECTIONS: pretty_table = make_pretty_table(["Contract", *keys], data, False) section_title = f"{self.title} ({title})" txt = f"\n\n{section_title}:\n" @@ -94,7 +94,7 @@ class MartinMetrics: self.full_text += txt setattr( self, - title.lower(), + attr, SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), ) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index 2763470c4..d67f570c0 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -37,6 +37,7 @@ class MyPrettyTable: # UTILITY FUNCTIONS + def make_pretty_table( headers: list, body: dict, totals: bool = False, total_header="TOTAL" ) -> MyPrettyTable: From 97f817712fbe35d5d118cf1caa54075f9d660528 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:35:07 +0000 Subject: [PATCH 141/338] Bump actions/upload-pages-artifact from 1 to 2 Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 1 to 2. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v1...v2) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f6d66aa0a..625cafe4f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -37,7 +37,7 @@ jobs: - run: pip install -e ".[doc]" - run: pdoc -o html/ slither '!slither.tools' #TODO fix import errors on pdoc run - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v2 with: # Upload the doc path: './html/' From ec309343a5e9c7dbf3ca5d4cc1dfb12b080da049 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 17 Jul 2023 15:42:10 +0200 Subject: [PATCH 142/338] Fix abi.decode tuple result with udt --- slither/slithir/convert.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index d40715c4f..df9400c6a 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1210,7 +1210,12 @@ def convert_to_solidity_func( and len(new_ir.arguments) == 2 and isinstance(new_ir.arguments[1], list) ): - types = list(new_ir.arguments[1]) + types = [] + for arg_type in new_ir.arguments[1]: + decode_type = arg_type + if isinstance(decode_type, (Structure, Enum, Contract)): + decode_type = UserDefinedType(decode_type) + types.append(decode_type) new_ir.lvalue.set_type(types) # abi.decode where the type to decode is a singleton # abi.decode(a, (uint)) From 65aaafa0c61f1b5dd8c8ce15e945bae3eebf12c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:38:31 +0000 Subject: [PATCH 143/338] Bump pypa/gh-action-pypi-publish from 1.8.7 to 1.8.8 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.7 to 1.8.8. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.7...v1.8.8) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f7d9ff9e7..24f04ee87 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: path: dist/ - name: publish - uses: pypa/gh-action-pypi-publish@v1.8.7 + uses: pypa/gh-action-pypi-publish@v1.8.8 - name: sign uses: sigstore/gh-action-sigstore-python@v1.2.3 From b4add6eb055d205b3ab3c040357ed918cf9e8359 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 18 Jul 2023 13:53:17 +0200 Subject: [PATCH 144/338] Fix enum.max/min when enum in other contract --- .../visitors/slithir/expression_to_slithir.py | 25 ++++++++++-- tests/e2e/solc_parsing/test_ast_parsing.py | 1 + .../enum-max-min.sol-0.8.19-compact.zip | Bin 0 -> 3319 bytes .../solc_parsing/test_data/enum-max-min.sol | 37 ++++++++++++++++++ .../enum-max-min.sol-0.8.19-compact.json | 12 ++++++ 5 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/compile/enum-max-min.sol-0.8.19-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/enum-max-min.sol create mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-max-min.sol-0.8.19-compact.json diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 005ad81a4..0e265f909 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -443,6 +443,7 @@ class ExpressionToSlithIR(ExpressionVisitor): # Look for type(X).max / min # Because we looked at the AST structure, we need to look into the nested expression # Hopefully this is always on a direct sub field, and there is no weird construction + # pylint: disable=too-many-nested-blocks if isinstance(expression.expression, CallExpression) and expression.member_name in [ "min", "max", @@ -462,10 +463,22 @@ class ExpressionToSlithIR(ExpressionVisitor): constant_type = type_found else: # type(enum).max/min - assert isinstance(type_expression_found, Identifier) - type_found_in_expression = type_expression_found.value - assert isinstance(type_found_in_expression, (EnumContract, EnumTopLevel)) - type_found = UserDefinedType(type_found_in_expression) + # Case when enum is in another contract e.g. type(C.E).max + if isinstance(type_expression_found, MemberAccess): + contract = type_expression_found.expression.value + assert isinstance(contract, Contract) + for enum in contract.enums: + if enum.name == type_expression_found.member_name: + type_found_in_expression = enum + type_found = UserDefinedType(enum) + break + else: + assert isinstance(type_expression_found, Identifier) + type_found_in_expression = type_expression_found.value + assert isinstance( + type_found_in_expression, (EnumContract, EnumTopLevel) + ) + type_found = UserDefinedType(type_found_in_expression) constant_type = None min_value = type_found_in_expression.min max_value = type_found_in_expression.max @@ -523,6 +536,10 @@ class ExpressionToSlithIR(ExpressionVisitor): if expression.member_name in expr.custom_errors_as_dict: set_val(expression, expr.custom_errors_as_dict[expression.member_name]) return + # Lookup enums when in a different contract e.g. C.E + if str(expression) in expr.enums_as_dict: + set_val(expression, expr.enums_as_dict[str(expression)]) + return val_ref = ReferenceVariable(self._node) member = Member(expr, Constant(expression.member_name), val_ref) diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index 307e6736f..d6cc1b8b4 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -459,6 +459,7 @@ ALL_TESTS = [ ["0.6.9", "0.7.6", "0.8.16"], ), Test("user_defined_operators-0.8.19.sol", ["0.8.19"]), + Test("enum-max-min.sol", ["0.8.19"]), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/compile/enum-max-min.sol-0.8.19-compact.zip b/tests/e2e/solc_parsing/test_data/compile/enum-max-min.sol-0.8.19-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..f29ad0bdb623661cfecebcc9e63e18e268196b83 GIT binary patch literal 3319 zcma)Q@U0XzVZ0aWde^=SIm$}~s-fF2J3fE@q;SUI@a^VwT? z^4Z%u@Vhv^H?#6YIXb(VSvVtYY~8K+?OYrkfOz--69B*;0FVj^u@<@!a>}0g(I82h z-s@ody!}Z~B#c3tW!9yYR^UutI%8>6lnAGx|)K;iT#XY(F_kx$x2al&e#Q z17X`pk5kb5oa)4KoH+*R082@SZJKemSUzUvxGCwa?EDeGUqxT=-X1M5i3*<;kWDtR zB_kW(BG(=zp>n$6r4&#E$lx|#vm|*7-%;_c>UM!q8Hoel2rFeb)S6sKU4KyF%BxU6zodzr2yq9U92)BE@rj zq2dOM2+pT^w~|N|n^ze1VUi1iebpR7Pa$Q1xV4XKOZGaY8W1V35t|y8Up2Pu+yH1g zH95U$KzCVRO`LDfzSgIEIN0@F4f9WyOyr<-;38MTcn}-M4Fyb_Tj#B4uP%GjDg849 zpIA6u6N&0UEvZ2;?`V@9V;rg>udc2b;@>Y)e%+x7T7yVrX5`M#yOn@#zm_ z{0Hi;sIJWclhy4wi|~?R$b^v7gsA;{xPp!*@DzTG5p1meN8-mGZP716y#|9p?^~-neGLC(8UvUVivBk}lBFufVI7 zzhIz?X16~3ZHD`8*k-)opAxF0-+WeXeS$&~oPjuihtAOlLvv5MH1wTQkS^J^3 z%MaY|DkKtp!%)^RswybgR#saIUqglpvCx#sv_8FD4aG?#oBX>Onwv+=JqOrpV%wbd zkKd1pjuHxO2*&+Ru z4`3W)8C&fx?PhGOREzp{4jwzG({rv3Wql-jR_B7$)UppQ3bly6BQnI@S31qyjg#LU z{Ge{#`l0<{M2Ay z=%)FmTBZ1F!-2;BvESFtj+gtvH|S6wIV?qc`|K zxkVI`i9^_fx)Jxsmq|>2hHnNrS-Rzb&1?yb!e^OS9mP2E|4P*_|?38785< zhxto?L@7GzX>ctvQx!dX5G4xQBoXr~G}grVmlQC`uz8waKynSC!+~UYosUp}Z>6*l z?RESg?o=5on+9nI=9b$AT}!1*F}k3yG#;Evke@4E4ErA=FnZ<~UrB&M&X#UWh#|)k z>x)G08}rbPk$zp(26t=QuFD{l%&|g5+Mzm@(37L=WV(7XERguHn( zdAAn?k(6Rw{^UOKxj~nrUSC7EmJ1hRjB=(&`j_|k%;csqwbbj(BgfOZm z2}jimjAt*J=MWT3^uk}ZWCQ5(8|+%Dhnr+MS{OJ<6v0;I>dP$y`8b=iaa%S4Bt8BmiwVyH!FVlMZ&W>H;-vggHYaUhz=6+>w)Ee^StoxAU z^G{dZGGDI4F5SflFb7^H=h7o$UK5OQ#WuA&Cgf|J(~MtkqBImNTRV8>omgGU%3ASn z6}SL>-d(1exjPtrwm8Cig(Z~`tQ78w!-(LQe{Kmeszrvgh8+6=(lhSv>_dC%+Z1~& zz^1{gNy74KZ3Jr({9cQ|>ojN?XQefE!A^~A6X2KHXmo-Stz|a+C?(7tVVBJX4Qeja zj8FGLwB)eRh1%``20*Hc&r`BHwr7Ov-MgZT+a{HE&UO{YbA~(t~}h7AB{@X!O}`Eqt1#HDysEsPRM+`!AablVq-`T$tHc%cR%AZd3k-Si-Ik*>v<&LG8uwRo*WhsrL zxh8RM=U>jz{KM)^Uf7)Rhgp8H9wBE$@XIz;?;LPgpZ$o+*U^N7hhP1t{wjR*7LC7{&)n9w@RXOOp=3UE9d6W=cjz!sd}^@K zpGC$KwCMhW@cTE6t;_ZW6YZGrw-(svTZIVxk0e9F8tY}O7P0iku}QvEYvkTo@uZpo zkqgWm5e{kEQ_cDd^a^Fa_<@~;&ug*lkUY$i-FTYE=1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "b()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "c()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "d()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "e()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file From 60a67680b06ec21311158a115f4d4a7d97a678cc Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 18 Jul 2023 14:07:51 +0200 Subject: [PATCH 145/338] Compile after the test was added --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5cf02136b..ae7951c7f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,8 +96,8 @@ For each new detector, at least one regression tests must be present. #### Adding parsing tests 1. Create a test in `tests/e2e/solc_parsing/` -2. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git. -3. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py`. +2. Update `ALL_TESTS` in `tests/e2e/solc_parsing/test_ast_parsing.py`. +3. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --compile`. This will compile the artifact in `tests/e2e/solc_parsing/compile`. Add the compiled artifact to git. 4. Run `python tests/e2e/solc_parsing/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/e2e/solc_parsing/expected_json`. Add the generated files to git. 5. Run `pytest tests/e2e/solc_parsing/test_ast_parsing.py` and check that everything worked. From 27f56466f2f9f52eb4ecaca5d5dc05b1e65e130b Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 25 Jul 2023 11:03:36 +0200 Subject: [PATCH 146/338] Use is_test_contract util --- slither/printers/guidance/echidna.py | 17 ++++++----------- slither/slither.py | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 60fcd6b0f..92d031fdd 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -1,5 +1,4 @@ import json -import re from collections import defaultdict from typing import Dict, List, Set, Tuple, NamedTuple, Union @@ -33,6 +32,7 @@ from slither.slithir.operations import ( from slither.slithir.operations.binary import Binary from slither.slithir.variables import Constant from slither.utils.output import Output +from slither.utils.tests_pattern import is_test_contract from slither.visitors.expression.constants_folding import ConstantFolding @@ -53,9 +53,7 @@ def _extract_payable(contracts) -> Dict[str, List[str]]: return ret -def _extract_solidity_variable_usage( - contracts, sol_var: SolidityVariable -) -> Dict[str, List[str]]: +def _extract_solidity_variable_usage(contracts, sol_var: SolidityVariable) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} for contract in contracts: functions_using_sol_var = [] @@ -391,8 +389,7 @@ class Echidna(AbstractPrinter): _filename(string) """ - filter = r"mock(s)?|test(s)?" - contracts = [c for c in self.slither.contracts if not re.search(filter, c.file_scope.filename.absolute, re.IGNORECASE)] + contracts = [c for c in self.slither.contracts if not is_test_contract(c)] payable = _extract_payable(contracts) timestamp = _extract_solidity_variable_usage( @@ -404,9 +401,7 @@ class Echidna(AbstractPrinter): msg_sender = _extract_solidity_variable_usage( contracts, SolidityVariableComposed("msg.sender") ) - msg_gas = _extract_solidity_variable_usage( - contracts, SolidityVariableComposed("msg.gas") - ) + msg_gas = _extract_solidity_variable_usage(contracts, SolidityVariableComposed("msg.gas")) assert_usage = _extract_assert(contracts) cst_functions = _extract_constant_functions(contracts) (cst_used, cst_used_in_binary) = _extract_constants(contracts) @@ -421,7 +416,7 @@ class Echidna(AbstractPrinter): external_calls = _have_external_calls(contracts) - #call_parameters = _call_a_parameter(self.slither, contracts) + # call_parameters = _call_a_parameter(self.slither, contracts) use_balance = _use_balance(contracts) @@ -442,7 +437,7 @@ class Echidna(AbstractPrinter): "functions_relations": functions_relations, "constructors": constructors, "have_external_calls": external_calls, - #"call_a_parameter": call_parameters, + # "call_a_parameter": call_parameters, "use_balance": use_balance, "solc_versions": [unit.solc_version for unit in self.slither.compilation_units], "with_fallback": with_fallback, diff --git a/slither/slither.py b/slither/slither.py index ca0df5f71..046fc54fa 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -137,7 +137,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes if printers_to_run == "echidna": self.skip_data_dependency = True - self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) + self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: From c23b8fe8318f5ec287545f6aad79fe18635be31f Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 25 Jul 2023 11:31:43 +0200 Subject: [PATCH 147/338] Lint --- slither/printers/guidance/echidna.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index ae89c2580..7255534ed 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -33,7 +33,7 @@ from slither.slithir.operations.binary import Binary from slither.slithir.variables import Constant from slither.utils.output import Output from slither.utils.tests_pattern import is_test_contract -from slither.visitors.expression.constants_folding import ConstantFolding +from slither.visitors.expression.constants_folding import ConstantFolding, NotConstant def _get_name(f: Union[Function, Variable]) -> str: From baa7fb5974ed7bbb99216481723e90d9015f36b6 Mon Sep 17 00:00:00 2001 From: webthethird Date: Wed, 26 Jul 2023 21:36:09 -0500 Subject: [PATCH 148/338] Better struct handling in code generation util --- slither/utils/code_generation.py | 112 +++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/slither/utils/code_generation.py b/slither/utils/code_generation.py index bb8344d8f..907100239 100644 --- a/slither/utils/code_generation.py +++ b/slither/utils/code_generation.py @@ -12,16 +12,18 @@ from slither.core.solidity_types import ( MappingType, ArrayType, ElementaryType, + TypeAlias ) -from slither.core.declarations import Structure, Enum, Contract +from slither.core.declarations import Structure, StructureContract, Enum, Contract if TYPE_CHECKING: from slither.core.declarations import FunctionContract, CustomErrorContract from slither.core.variables.state_variable import StateVariable from slither.core.variables.local_variable import LocalVariable + from slither.core.variables.structure_variable import StructureVariable -# pylint: disable=too-many-arguments +# pylint: disable=too-many-arguments,too-many-locals,too-many-branches def generate_interface( contract: "Contract", unroll_structs: bool = True, @@ -56,12 +58,47 @@ def generate_interface( for enum in contract.enums: interface += f" enum {enum.name} {{ {', '.join(enum.values)} }}\n" if include_structs: - for struct in contract.structures: + # Include structures defined in this contract and at the top level + structs = contract.structures + contract.compilation_unit.structures_top_level + # Function signatures may reference other structures as well + # Include structures defined in libraries used for them + for _for in contract.using_for.keys(): + if ( + isinstance(_for, UserDefinedType) + and isinstance(_for.type, StructureContract) + and _for.type not in structs + ): + structs.append(_for.type) + # Include any other structures used as function arguments/returns + for func in contract.functions_entry_points: + for arg in func.parameters + func.returns: + _type = arg.type + if isinstance(_type, ArrayType): + _type = _type.type + while isinstance(_type, MappingType): + _type = _type.type_to + if isinstance(_type, UserDefinedType): + _type = _type.type + if isinstance(_type, Structure) and _type not in structs: + structs.append(_type) + for struct in structs: interface += generate_struct_interface_str(struct, indent=4) + for elem in struct.elems_ordered: + if ( + isinstance(elem.type, UserDefinedType) + and isinstance(elem.type.type, StructureContract) + and elem.type.type not in structs + ): + structs.append(elem.type.type) for var in contract.state_variables_entry_points: - interface += f" function {generate_interface_variable_signature(var, unroll_structs)};\n" + # if any(func.name == var.name for func in contract.functions_entry_points): + # # ignore public variables that override a public function + # continue + var_sig = generate_interface_variable_signature(var, unroll_structs) + if var_sig is not None and var_sig != "": + interface += f" function {var_sig};\n" for func in contract.functions_entry_points: - if func.is_constructor or func.is_fallback or func.is_receive: + if func.is_constructor or func.is_fallback or func.is_receive or not func.is_implemented: continue interface += ( f" function {generate_interface_function_signature(func, unroll_structs)};\n" @@ -75,6 +112,10 @@ def generate_interface_variable_signature( ) -> Optional[str]: if var.visibility in ["private", "internal"]: return None + if isinstance(var.type, UserDefinedType) and isinstance(var.type.type, Structure): + for elem in var.type.type.elems_ordered: + if isinstance(elem.type, MappingType): + return "" if unroll_structs: params = [ convert_type_for_solidity_signature_to_string(x).replace("(", "").replace(")", "") @@ -93,6 +134,11 @@ def generate_interface_variable_signature( _type = _type.type_to while isinstance(_type, (ArrayType, UserDefinedType)): _type = _type.type + if isinstance(_type, TypeAlias): + _type = _type.type + if isinstance(_type, Structure): + if any(isinstance(elem.type, MappingType) for elem in _type.elems_ordered): + return "" ret = str(_type) if isinstance(_type, Structure) or (isinstance(_type, Type) and _type.is_dynamic): ret += " memory" @@ -125,6 +171,8 @@ def generate_interface_function_signature( .replace("(", "") .replace(")", "") ) + if var.type.is_dynamic: + return f"{_handle_dynamic_struct_elem(var.type)} {var.location}" if isinstance(var.type, ArrayType) and isinstance( var.type.type, (UserDefinedType, ElementaryType) ): @@ -135,12 +183,14 @@ def generate_interface_function_signature( + f" {var.location}" ) if isinstance(var.type, UserDefinedType): - if isinstance(var.type.type, (Structure, Enum)): + if isinstance(var.type.type, Structure): return f"{str(var.type.type)} memory" + if isinstance(var.type.type, Enum): + return str(var.type.type) if isinstance(var.type.type, Contract): return "address" - if var.type.is_dynamic: - return f"{var.type} {var.location}" + if isinstance(var.type, TypeAlias): + return str(var.type.type) return str(var.type) name, _, _ = func.signature @@ -154,6 +204,12 @@ def generate_interface_function_signature( view = " view" if func.view and not func.pure else "" pure = " pure" if func.pure else "" payable = " payable" if func.payable else "" + # Make sure the function doesn't return a struct with nested mappings + for ret in func.returns: + if isinstance(ret.type, UserDefinedType) and isinstance(ret.type.type, Structure): + for elem in ret.type.type.elems_ordered: + if isinstance(elem.type, MappingType): + return "" returns = [format_var(ret, unroll_structs) for ret in func.returns] parameters = [format_var(param, unroll_structs) for param in func.parameters] _interface_signature_str = ( @@ -184,17 +240,49 @@ def generate_struct_interface_str(struct: "Structure", indent: int = 0) -> str: spaces += " " definition = f"{spaces}struct {struct.name} {{\n" for elem in struct.elems_ordered: - if isinstance(elem.type, UserDefinedType): - if isinstance(elem.type.type, (Structure, Enum)): + if elem.type.is_dynamic: + definition += f"{spaces} {_handle_dynamic_struct_elem(elem.type)} {elem.name};\n" + elif isinstance(elem.type, UserDefinedType): + if isinstance(elem.type.type, Structure): definition += f"{spaces} {elem.type.type} {elem.name};\n" - elif isinstance(elem.type.type, Contract): - definition += f"{spaces} address {elem.name};\n" + else: + definition += f"{spaces} {convert_type_for_solidity_signature_to_string(elem.type)} {elem.name};\n" + elif isinstance(elem.type, TypeAlias): + definition += f"{spaces} {elem.type.type} {elem.name};\n" else: definition += f"{spaces} {elem.type} {elem.name};\n" definition += f"{spaces}}}\n" return definition +def _handle_dynamic_struct_elem(elem_type: Type) -> str: + assert elem_type.is_dynamic + if isinstance(elem_type, ElementaryType): + return f"{elem_type}" + if isinstance(elem_type, ArrayType): + base_type = elem_type.type + if isinstance(base_type, UserDefinedType): + if isinstance(base_type.type, Contract): + return "address[]" + if isinstance(base_type.type, Enum): + return convert_type_for_solidity_signature_to_string(elem_type) + return f"{base_type.type.name}[]" + return f"{base_type}[]" + if isinstance(elem_type, MappingType): + type_to = elem_type.type_to + type_from = elem_type.type_from + if isinstance(type_from, UserDefinedType) and isinstance(type_from.type, Contract): + type_from = ElementaryType("address") + if isinstance(type_to, MappingType): + return f"mapping({type_from} => {_handle_dynamic_struct_elem(type_to)})" + if isinstance(type_to, UserDefinedType): + if isinstance(type_to.type, Contract): + return f"mapping({type_from} => address)" + return f"mapping({type_from} => {type_to.type.name})" + return f"{elem_type}" + return "" + + def generate_custom_error_interface( error: "CustomErrorContract", unroll_structs: bool = True ) -> str: From c47fa62b712af745cecbb0f20329d567c24affff Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 28 Jul 2023 17:36:04 -0500 Subject: [PATCH 149/338] ci: add problem matchers for yamllint and pylint --- .github/workflows/linter.yml | 7 +++--- .github/workflows/matchers/pylint.json | 32 ++++++++++++++++++++++++ .github/workflows/matchers/yamllint.json | 22 ++++++++++++++++ .github/workflows/pylint.yml | 6 +++++ 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/matchers/pylint.json create mode 100644 .github/workflows/matchers/yamllint.json diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index b352a8301..0468b07f8 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -9,8 +9,6 @@ defaults: on: pull_request: branches: [master, dev] - paths: - - "**/*.py" schedule: # run CI every day even if no PRs/merges occur @@ -42,6 +40,10 @@ jobs: mkdir -p .github/linters cp pyproject.toml .github/linters + - name: Register yamllint problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/yamllint.json" + - name: Lint everything else uses: super-linter/super-linter/slim@v4.9.2 if: always() @@ -55,7 +57,6 @@ jobs: VALIDATE_PYTHON_PYLINT: false VALIDATE_PYTHON_BLACK: false VALIDATE_PYTHON_ISORT: false - # Always false VALIDATE_JSON: false VALIDATE_JAVASCRIPT_STANDARD: false VALIDATE_PYTHON_FLAKE8: false diff --git a/.github/workflows/matchers/pylint.json b/.github/workflows/matchers/pylint.json new file mode 100644 index 000000000..4d9e13fca --- /dev/null +++ b/.github/workflows/matchers/pylint.json @@ -0,0 +1,32 @@ +{ + "problemMatcher": [ + { + "owner": "pylint-error", + "severity": "error", + "pattern": [ + { + "regexp": "^(.+):(\\d+):(\\d+):\\s(([EF]\\d{4}):\\s.+)$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + }, + { + "owner": "pylint-warning", + "severity": "warning", + "pattern": [ + { + "regexp": "^(.+):(\\d+):(\\d+):\\s(([CRW]\\d{4}):\\s.+)$", + "file": 1, + "line": 2, + "column": 3, + "message": 4, + "code": 5 + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/workflows/matchers/yamllint.json b/.github/workflows/matchers/yamllint.json new file mode 100644 index 000000000..b0b2f125c --- /dev/null +++ b/.github/workflows/matchers/yamllint.json @@ -0,0 +1,22 @@ +{ + "problemMatcher": [ + { + "owner": "yamllint", + "pattern": [ + { + "regexp": "^(.*\\.ya?ml)$", + "file": 1 + }, + { + "regexp": "^\\s{2}(\\d+):(\\d+)\\s+(error|warning)\\s+(.*?)\\s+\\((.*)\\)$", + "line": 1, + "column": 2, + "severity": 3, + "message": 4, + "code": 5, + "loop": true + } + ] + } + ] + } \ No newline at end of file diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 207f98eac..8c7e7bce9 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -9,6 +9,8 @@ defaults: on: pull_request: branches: [master, dev] + paths: + - "**/*.py" concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -36,6 +38,10 @@ jobs: mkdir -p .github/linters cp pyproject.toml .github/linters + - name: Register pylint problem matcher + run: | + echo "::add-matcher::.github/workflows/matchers/pylint.json" + - name: Pylint uses: super-linter/super-linter/slim@v4.9.2 if: always() From d90505826f952526f5daccd107b4100ed44ab2cb Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 3 Aug 2023 16:51:49 -0500 Subject: [PATCH 150/338] fix ternary rewrite test and make assertion more strict (#2067) --- .../unit/slithir/test_ternary_expressions.py | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/tests/unit/slithir/test_ternary_expressions.py b/tests/unit/slithir/test_ternary_expressions.py index 0acd9345d..712c9582b 100644 --- a/tests/unit/slithir/test_ternary_expressions.py +++ b/tests/unit/slithir/test_ternary_expressions.py @@ -1,8 +1,13 @@ from pathlib import Path from slither import Slither from slither.core.cfg.node import NodeType -from slither.slithir.operations import Assignment -from slither.core.expressions import AssignmentOperation, TupleExpression +from slither.slithir.operations import Assignment, Unpack +from slither.core.expressions import ( + AssignmentOperation, + TupleExpression, + NewElementaryType, + CallExpression, +) TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" @@ -12,27 +17,29 @@ def test_ternary_conversions(solc_binary_path) -> None: solc_path = solc_binary_path("0.8.0") slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path) for contract in slither.contracts: - for function in contract.functions: - vars_declared = 0 - vars_assigned = 0 - for node in function.nodes: - if node.type in [NodeType.IF, NodeType.IFLOOP]: + if not contract.is_signature_only: + for function in contract.functions: + vars_declared = 0 + vars_assigned = 0 + for node in function.nodes: + if node.type in [NodeType.IF, NodeType.IFLOOP]: - # Iterate over true and false son - for inner_node in node.sons: - # Count all variables declared - expression = inner_node.expression - if isinstance(expression, AssignmentOperation): - var_expr = expression.expression_left - # Only tuples declare more than one var - if isinstance(var_expr, TupleExpression): - vars_declared += len(var_expr.expressions) - else: - vars_declared += 1 + # Iterate over true and false son + for inner_node in node.sons: + # Count all variables declared + expression = inner_node.expression + if isinstance( + expression, (AssignmentOperation, NewElementaryType, CallExpression) + ): + var_expr = expression.expression_left + # Only tuples declare more than one var + if isinstance(var_expr, TupleExpression): + vars_declared += len(var_expr.expressions) + else: + vars_declared += 1 - for ir in inner_node.irs: - # Count all variables defined - if isinstance(ir, Assignment): - vars_assigned += 1 - - assert vars_declared == vars_assigned + for ir in inner_node.irs: + # Count all variables defined + if isinstance(ir, (Assignment, Unpack)): + vars_assigned += 1 + assert vars_declared == vars_assigned and vars_assigned != 0 From e0098907c998fede544525f859f917074a752e63 Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:53:09 +0200 Subject: [PATCH 151/338] Add CustomError as printable output (#2063) --- slither/core/declarations/__init__.py | 2 ++ .../declarations/custom_error_contract.py | 4 +++ .../declarations/custom_error_top_level.py | 4 +++ slither/utils/output.py | 29 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/slither/core/declarations/__init__.py b/slither/core/declarations/__init__.py index 92e0b9eca..f34118751 100644 --- a/slither/core/declarations/__init__.py +++ b/slither/core/declarations/__init__.py @@ -18,3 +18,5 @@ from .structure_top_level import StructureTopLevel from .function_contract import FunctionContract from .function_top_level import FunctionTopLevel from .custom_error_contract import CustomErrorContract +from .custom_error_top_level import CustomErrorTopLevel +from .custom_error import CustomError diff --git a/slither/core/declarations/custom_error_contract.py b/slither/core/declarations/custom_error_contract.py index cd279a3a6..2c8bec9ef 100644 --- a/slither/core/declarations/custom_error_contract.py +++ b/slither/core/declarations/custom_error_contract.py @@ -16,3 +16,7 @@ class CustomErrorContract(CustomError, ContractLevel): :return: """ return self.contract == contract + + @property + def canonical_name(self) -> str: + return self.contract.name + "." + self.full_name diff --git a/slither/core/declarations/custom_error_top_level.py b/slither/core/declarations/custom_error_top_level.py index 64a6a8535..b80356b24 100644 --- a/slither/core/declarations/custom_error_top_level.py +++ b/slither/core/declarations/custom_error_top_level.py @@ -12,3 +12,7 @@ class CustomErrorTopLevel(CustomError, TopLevel): def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None: super().__init__(compilation_unit) self.file_scope: "FileScope" = scope + + @property + def canonical_name(self) -> str: + return self.full_name diff --git a/slither/utils/output.py b/slither/utils/output.py index 84c9ac65a..4a91ca9b9 100644 --- a/slither/utils/output.py +++ b/slither/utils/output.py @@ -18,6 +18,7 @@ from slither.core.declarations import ( Structure, Pragma, FunctionContract, + CustomError, ) from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables.local_variable import LocalVariable @@ -438,6 +439,8 @@ class Output: self.add_event(add, additional_fields=additional_fields) elif isinstance(add, Structure): self.add_struct(add, additional_fields=additional_fields) + elif isinstance(add, CustomError): + self.add_custom_error(add, additional_fields=additional_fields) elif isinstance(add, Pragma): self.add_pragma(add, additional_fields=additional_fields) elif isinstance(add, Node): @@ -585,6 +588,32 @@ class Output: self._data["elements"].append(element) + # endregion + ################################################################################### + ################################################################################### + # region CustomError + ################################################################################### + ################################################################################### + + def add_custom_error( + self, custom_error: CustomError, additional_fields: Optional[Dict] = None + ) -> None: + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + "parent": _create_parent_element(custom_error), + "signature": custom_error.full_name, + } + element = _create_base_element( + "custom_error", + custom_error.name, + custom_error.source_mapping.to_json(), + type_specific_fields, + additional_fields, + ) + + self._data["elements"].append(element) + # endregion ################################################################################### ################################################################################### From d86bd4109d69f7e99ea84e716f7d41d9ac29b1ea Mon Sep 17 00:00:00 2001 From: SheldonHolmgren <116484297+SheldonHolmgren@users.noreply.github.com> Date: Thu, 3 Aug 2023 22:54:15 +0100 Subject: [PATCH 152/338] UnaryOperation: -variable and +variable doesn't make variable an lvalue (#2027) --- slither/core/expressions/unary_operation.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/slither/core/expressions/unary_operation.py b/slither/core/expressions/unary_operation.py index 657224927..405132613 100644 --- a/slither/core/expressions/unary_operation.py +++ b/slither/core/expressions/unary_operation.py @@ -106,8 +106,6 @@ class UnaryOperation(Expression): UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST, - UnaryOperationType.PLUS_PRE, - UnaryOperationType.MINUS_PRE, ]: expression.set_lvalue() From 3f90e86badfa956b5cc692e0421c2b8065c31d43 Mon Sep 17 00:00:00 2001 From: yisun92 Date: Thu, 3 Aug 2023 17:56:04 -0400 Subject: [PATCH 153/338] fix: get_state_variable_from_canonical_name() filter by canonical_name (#1983) --- slither/core/declarations/contract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index fd2cdd468..9b1488db3 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -861,7 +861,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods Returns: StateVariable """ - return next((v for v in self.state_variables if v.name == canonical_name), None) + return next((v for v in self.state_variables if v.canonical_name == canonical_name), None) def get_structure_from_name(self, structure_name: str) -> Optional["StructureContract"]: """ From d9977c02ad22e9f6b5b99ec6f0ad2f12fa16fb33 Mon Sep 17 00:00:00 2001 From: Simone Date: Sun, 6 Aug 2023 11:17:16 +0200 Subject: [PATCH 154/338] Add end assembly node in the cfg --- slither/core/cfg/node.py | 1 + slither/solc_parsing/declarations/function.py | 4 ++- .../assembly-all.sol-0.6.0-compact.json | 4 +-- .../assembly-all.sol-0.6.1-compact.json | 4 +-- .../assembly-all.sol-0.6.10-compact.json | 4 +-- .../assembly-all.sol-0.6.11-compact.json | 4 +-- .../assembly-all.sol-0.6.12-compact.json | 4 +-- .../assembly-all.sol-0.6.2-compact.json | 4 +-- .../assembly-all.sol-0.6.3-compact.json | 4 +-- .../assembly-all.sol-0.6.4-compact.json | 4 +-- .../assembly-all.sol-0.6.5-compact.json | 4 +-- .../assembly-all.sol-0.6.6-compact.json | 4 +-- .../assembly-all.sol-0.6.7-compact.json | 4 +-- .../assembly-all.sol-0.6.8-compact.json | 4 +-- .../assembly-all.sol-0.6.9-compact.json | 4 +-- .../assembly-all.sol-0.7.0-compact.json | 4 +-- .../assembly-all.sol-0.7.1-compact.json | 4 +-- .../assembly-all.sol-0.7.2-compact.json | 4 +-- .../assembly-all.sol-0.7.3-compact.json | 4 +-- .../assembly-all.sol-0.7.4-compact.json | 4 +-- .../assembly-all.sol-0.7.5-compact.json | 4 +-- .../assembly-all.sol-0.7.6-compact.json | 4 +-- .../assembly-all.sol-0.8.0-compact.json | 4 +-- .../assembly-all.sol-0.8.1-compact.json | 4 +-- .../assembly-all.sol-0.8.10-compact.json | 4 +-- .../assembly-all.sol-0.8.11-compact.json | 4 +-- .../assembly-all.sol-0.8.12-compact.json | 4 +-- .../assembly-all.sol-0.8.13-compact.json | 4 +-- .../assembly-all.sol-0.8.14-compact.json | 4 +-- .../assembly-all.sol-0.8.15-compact.json | 4 +-- .../assembly-all.sol-0.8.2-compact.json | 4 +-- .../assembly-all.sol-0.8.3-compact.json | 4 +-- .../assembly-all.sol-0.8.4-compact.json | 4 +-- .../assembly-all.sol-0.8.5-compact.json | 4 +-- .../assembly-all.sol-0.8.6-compact.json | 4 +-- .../assembly-all.sol-0.8.7-compact.json | 4 +-- .../assembly-all.sol-0.8.8-compact.json | 4 +-- .../assembly-all.sol-0.8.9-compact.json | 4 +-- .../assembly-functions.sol-0.6.9-compact.json | 2 +- .../assembly-functions.sol-0.7.6-compact.json | 2 +- ...assembly-functions.sol-0.8.16-compact.json | 2 +- .../assignment-0.4.0.sol-0.4.0-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.1-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.10-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.11-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.2-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.3-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.4-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.5-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.6-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.7-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.8-compact.json | 5 ---- .../assignment-0.4.0.sol-0.4.9-compact.json | 5 ---- .../assignment-0.4.7.sol-0.4.7-compact.json | 5 ---- .../assignment-0.4.7.sol-0.4.8-compact.json | 5 ---- .../assignment-0.4.7.sol-0.4.9-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.0-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.1-compact.json | 5 ---- ...aryoperation-0.4.0.sol-0.4.10-compact.json | 5 ---- ...aryoperation-0.4.0.sol-0.4.11-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.2-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.3-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.4-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.5-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.6-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.7-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.8-compact.json | 5 ---- ...naryoperation-0.4.0.sol-0.4.9-compact.json | 5 ---- ...naryoperation-0.4.7.sol-0.4.7-compact.json | 5 ---- ...naryoperation-0.4.7.sol-0.4.8-compact.json | 5 ---- ...naryoperation-0.4.7.sol-0.4.9-compact.json | 5 ---- .../expected/break-all.sol-0.4.0-compact.json | 5 ---- .../expected/break-all.sol-0.4.1-compact.json | 5 ---- .../break-all.sol-0.4.10-compact.json | 5 ---- .../break-all.sol-0.4.11-compact.json | 5 ---- .../expected/break-all.sol-0.4.2-compact.json | 5 ---- .../expected/break-all.sol-0.4.3-compact.json | 5 ---- .../expected/break-all.sol-0.4.4-compact.json | 5 ---- .../expected/break-all.sol-0.4.5-compact.json | 5 ---- .../expected/break-all.sol-0.4.6-compact.json | 5 ---- .../expected/break-all.sol-0.4.7-compact.json | 5 ---- .../expected/break-all.sol-0.4.8-compact.json | 5 ---- .../expected/break-all.sol-0.4.9-compact.json | 5 ---- ...all_to_variable-all.sol-0.4.0-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.1-compact.json | 6 ---- ...ll_to_variable-all.sol-0.4.10-compact.json | 6 ---- ...ll_to_variable-all.sol-0.4.11-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.2-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.3-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.4-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.5-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.6-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.7-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.8-compact.json | 6 ---- ...all_to_variable-all.sol-0.4.9-compact.json | 6 ---- .../comment-all.sol-0.4.0-compact.json | 5 ---- .../comment-all.sol-0.4.1-compact.json | 5 ---- .../comment-all.sol-0.4.10-compact.json | 5 ---- .../comment-all.sol-0.4.11-compact.json | 5 ---- .../comment-all.sol-0.4.2-compact.json | 5 ---- .../comment-all.sol-0.4.3-compact.json | 5 ---- .../comment-all.sol-0.4.4-compact.json | 5 ---- .../comment-all.sol-0.4.5-compact.json | 5 ---- .../comment-all.sol-0.4.6-compact.json | 5 ---- .../comment-all.sol-0.4.7-compact.json | 5 ---- .../comment-all.sol-0.4.8-compact.json | 5 ---- .../comment-all.sol-0.4.9-compact.json | 5 ---- .../continue-all.sol-0.4.0-compact.json | 5 ---- .../continue-all.sol-0.4.1-compact.json | 5 ---- .../continue-all.sol-0.4.10-compact.json | 5 ---- .../continue-all.sol-0.4.11-compact.json | 5 ---- .../continue-all.sol-0.4.2-compact.json | 5 ---- .../continue-all.sol-0.4.3-compact.json | 5 ---- .../continue-all.sol-0.4.4-compact.json | 5 ---- .../continue-all.sol-0.4.5-compact.json | 5 ---- .../continue-all.sol-0.4.6-compact.json | 5 ---- .../continue-all.sol-0.4.7-compact.json | 5 ---- .../continue-all.sol-0.4.8-compact.json | 5 ---- .../continue-all.sol-0.4.9-compact.json | 5 ---- .../contract-0.4.0.sol-0.4.0-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.1-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.10-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.11-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.2-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.3-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.4-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.5-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.6-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.7-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.8-compact.json | 19 ------------ .../contract-0.4.0.sol-0.4.9-compact.json | 19 ------------ .../custom_error-0.4.0.sol-0.4.0-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.1-compact.json | 1 - ...custom_error-0.4.0.sol-0.4.10-compact.json | 1 - ...custom_error-0.4.0.sol-0.4.11-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.2-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.3-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.4-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.5-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.6-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.7-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.8-compact.json | 1 - .../custom_error-0.4.0.sol-0.4.9-compact.json | 1 - .../dowhile-0.4.0.sol-0.4.0-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.1-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.10-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.11-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.2-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.3-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.4-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.5-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.6-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.7-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.8-compact.json | 3 -- .../dowhile-0.4.0.sol-0.4.9-compact.json | 3 -- .../dowhile-0.4.5.sol-0.4.5-compact.json | 5 ---- .../dowhile-0.4.5.sol-0.4.6-compact.json | 5 ---- .../dowhile-0.4.5.sol-0.4.7-compact.json | 5 ---- .../dowhile-0.4.5.sol-0.4.8-compact.json | 5 ---- .../dowhile-0.4.5.sol-0.4.9-compact.json | 5 ---- .../emit-0.4.21.sol-0.4.21-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.21-legacy.json | 7 ----- .../emit-0.4.21.sol-0.4.22-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.22-legacy.json | 7 ----- .../emit-0.4.21.sol-0.4.23-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.23-legacy.json | 7 ----- .../emit-0.4.21.sol-0.4.24-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.24-legacy.json | 7 ----- .../emit-0.4.21.sol-0.4.25-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.25-legacy.json | 7 ----- .../emit-0.4.21.sol-0.4.26-compact.json | 7 ----- .../emit-0.4.21.sol-0.4.26-legacy.json | 7 ----- .../emit-0.4.8.sol-0.4.8-compact.json | 6 ---- .../expected/emit-0.4.8.sol-0.4.8-legacy.json | 6 ---- .../emit-0.4.8.sol-0.4.9-compact.json | 6 ---- .../expected/emit-0.4.8.sol-0.4.9-legacy.json | 6 ---- .../enum-0.4.0.sol-0.4.0-compact.json | 3 -- .../enum-0.4.0.sol-0.4.1-compact.json | 3 -- .../enum-0.4.0.sol-0.4.10-compact.json | 3 -- .../enum-0.4.0.sol-0.4.11-compact.json | 3 -- .../enum-0.4.0.sol-0.4.2-compact.json | 3 -- .../enum-0.4.0.sol-0.4.3-compact.json | 3 -- .../enum-0.4.0.sol-0.4.4-compact.json | 3 -- .../enum-0.4.0.sol-0.4.5-compact.json | 3 -- .../enum-0.4.0.sol-0.4.6-compact.json | 3 -- .../enum-0.4.0.sol-0.4.7-compact.json | 3 -- .../enum-0.4.0.sol-0.4.8-compact.json | 3 -- .../enum-0.4.0.sol-0.4.9-compact.json | 3 -- .../expected/event-all.sol-0.4.0-compact.json | 3 -- .../expected/event-all.sol-0.4.1-compact.json | 3 -- .../event-all.sol-0.4.10-compact.json | 3 -- .../event-all.sol-0.4.11-compact.json | 3 -- .../expected/event-all.sol-0.4.2-compact.json | 3 -- .../expected/event-all.sol-0.4.3-compact.json | 3 -- .../expected/event-all.sol-0.4.4-compact.json | 3 -- .../expected/event-all.sol-0.4.5-compact.json | 3 -- .../expected/event-all.sol-0.4.6-compact.json | 3 -- .../expected/event-all.sol-0.4.7-compact.json | 3 -- .../expected/event-all.sol-0.4.8-compact.json | 3 -- .../expected/event-all.sol-0.4.9-compact.json | 3 -- .../expected/for-all.sol-0.4.0-compact.json | 15 ---------- .../expected/for-all.sol-0.4.1-compact.json | 15 ---------- .../expected/for-all.sol-0.4.10-compact.json | 15 ---------- .../expected/for-all.sol-0.4.11-compact.json | 15 ---------- .../expected/for-all.sol-0.4.2-compact.json | 15 ---------- .../expected/for-all.sol-0.4.3-compact.json | 15 ---------- .../expected/for-all.sol-0.4.4-compact.json | 15 ---------- .../expected/for-all.sol-0.4.5-compact.json | 15 ---------- .../expected/for-all.sol-0.4.6-compact.json | 15 ---------- .../expected/for-all.sol-0.4.7-compact.json | 15 ---------- .../expected/for-all.sol-0.4.8-compact.json | 15 ---------- .../expected/for-all.sol-0.4.9-compact.json | 15 ---------- .../function-0.4.0.sol-0.4.0-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.1-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.10-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.11-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.2-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.3-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.4-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.5-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.6-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.7-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.8-compact.json | 30 ------------------- .../function-0.4.0.sol-0.4.9-compact.json | 30 ------------------- .../functioncall-0.4.0.sol-0.4.0-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.1-compact.json | 11 ------- ...functioncall-0.4.0.sol-0.4.10-compact.json | 11 ------- ...functioncall-0.4.0.sol-0.4.11-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.2-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.3-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.4-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.5-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.6-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.7-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.8-compact.json | 11 ------- .../functioncall-0.4.0.sol-0.4.9-compact.json | 11 ------- .../functioncall-0.4.5.sol-0.4.5-compact.json | 11 ------- .../functioncall-0.4.5.sol-0.4.6-compact.json | 11 ------- .../functioncall-0.4.5.sol-0.4.7-compact.json | 11 ------- .../functioncall-0.4.5.sol-0.4.8-compact.json | 11 ------- .../functioncall-0.4.5.sol-0.4.9-compact.json | 11 ------- ...l_variables-0.8.18.sol-0.8.18-compact.json | 2 +- .../expected/if-all.sol-0.4.0-compact.json | 8 ----- .../expected/if-all.sol-0.4.1-compact.json | 8 ----- .../expected/if-all.sol-0.4.10-compact.json | 8 ----- .../expected/if-all.sol-0.4.11-compact.json | 8 ----- .../expected/if-all.sol-0.4.2-compact.json | 8 ----- .../expected/if-all.sol-0.4.3-compact.json | 8 ----- .../expected/if-all.sol-0.4.4-compact.json | 8 ----- .../expected/if-all.sol-0.4.5-compact.json | 8 ----- .../expected/if-all.sol-0.4.6-compact.json | 8 ----- .../expected/if-all.sol-0.4.7-compact.json | 8 ----- .../expected/if-all.sol-0.4.8-compact.json | 8 ----- .../expected/if-all.sol-0.4.9-compact.json | 8 ----- ...rom_top_level-0.4.0.sol-0.4.0-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.1-compact.json | 1 - ...om_top_level-0.4.0.sol-0.4.10-compact.json | 1 - ...om_top_level-0.4.0.sol-0.4.11-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.2-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.3-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.4-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.5-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.6-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.7-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.8-compact.json | 1 - ...rom_top_level-0.4.0.sol-0.4.9-compact.json | 1 - .../indexaccess-all.sol-0.4.0-compact.json | 5 ---- .../indexaccess-all.sol-0.4.1-compact.json | 5 ---- .../indexaccess-all.sol-0.4.10-compact.json | 5 ---- .../indexaccess-all.sol-0.4.11-compact.json | 5 ---- .../indexaccess-all.sol-0.4.2-compact.json | 5 ---- .../indexaccess-all.sol-0.4.3-compact.json | 5 ---- .../indexaccess-all.sol-0.4.4-compact.json | 5 ---- .../indexaccess-all.sol-0.4.5-compact.json | 5 ---- .../indexaccess-all.sol-0.4.6-compact.json | 5 ---- .../indexaccess-all.sol-0.4.7-compact.json | 5 ---- .../indexaccess-all.sol-0.4.8-compact.json | 5 ---- .../indexaccess-all.sol-0.4.9-compact.json | 5 ---- ...exrangeaccess-0.4.0.sol-0.4.0-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.1-compact.json | 3 -- ...xrangeaccess-0.4.0.sol-0.4.10-compact.json | 3 -- ...xrangeaccess-0.4.0.sol-0.4.11-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.2-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.3-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.4-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.5-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.6-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.7-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.8-compact.json | 3 -- ...exrangeaccess-0.4.0.sol-0.4.9-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.0-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.1-compact.json | 3 -- ...t_conversion-0.4.0.sol-0.4.10-compact.json | 3 -- ...t_conversion-0.4.0.sol-0.4.11-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.2-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.3-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.4-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.5-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.6-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.7-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.8-compact.json | 3 -- ...it_conversion-0.4.0.sol-0.4.9-compact.json | 3 -- .../literal-0.4.0.sol-0.4.0-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.1-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.2-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.3-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.4-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.5-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.6-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.7-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.8-compact.json | 5 ---- .../literal-0.4.0.sol-0.4.9-compact.json | 5 ---- .../literal-0.4.10.sol-0.4.10-compact.json | 5 ---- .../literal-0.4.10.sol-0.4.11-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.0-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.1-compact.json | 5 ---- ...memberaccess-0.4.0.sol-0.4.10-compact.json | 5 ---- ...memberaccess-0.4.0.sol-0.4.11-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.2-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.3-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.4-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.5-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.6-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.7-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.8-compact.json | 5 ---- .../memberaccess-0.4.0.sol-0.4.9-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.0-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.1-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.10-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.11-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.2-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.3-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.4-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.5-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.6-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.7-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.8-compact.json | 5 ---- .../minmax-0.4.0.sol-0.4.9-compact.json | 5 ---- .../modifier-all.sol-0.4.0-compact.json | 8 ----- .../modifier-all.sol-0.4.1-compact.json | 8 ----- .../modifier-all.sol-0.4.10-compact.json | 8 ----- .../modifier-all.sol-0.4.11-compact.json | 8 ----- .../modifier-all.sol-0.4.2-compact.json | 8 ----- .../modifier-all.sol-0.4.3-compact.json | 8 ----- .../modifier-all.sol-0.4.4-compact.json | 8 ----- .../modifier-all.sol-0.4.5-compact.json | 8 ----- .../modifier-all.sol-0.4.6-compact.json | 8 ----- .../modifier-all.sol-0.4.7-compact.json | 8 ----- .../modifier-all.sol-0.4.8-compact.json | 8 ----- .../modifier-all.sol-0.4.9-compact.json | 8 ----- .../modifier-all.sol-0.7.0-compact.json | 8 ----- .../modifier-all.sol-0.7.0-legacy.json | 8 ----- .../modifier-all.sol-0.7.1-compact.json | 8 ----- .../modifier-all.sol-0.7.1-legacy.json | 8 ----- .../modifier-all.sol-0.7.2-compact.json | 8 ----- .../modifier-all.sol-0.7.2-legacy.json | 8 ----- .../modifier-all.sol-0.7.3-compact.json | 8 ----- .../modifier-all.sol-0.7.3-legacy.json | 8 ----- .../modifier-all.sol-0.7.4-compact.json | 8 ----- .../modifier-all.sol-0.7.4-legacy.json | 8 ----- .../modifier-all.sol-0.7.5-compact.json | 8 ----- .../modifier-all.sol-0.7.5-legacy.json | 8 ----- .../modifier-all.sol-0.7.6-compact.json | 8 ----- .../modifier-all.sol-0.7.6-legacy.json | 8 ----- .../modifier-all.sol-0.8.0-compact.json | 8 ----- .../modifier-all.sol-0.8.1-compact.json | 8 ----- .../modifier-all.sol-0.8.10-compact.json | 8 ----- .../modifier-all.sol-0.8.11-compact.json | 8 ----- .../modifier-all.sol-0.8.12-compact.json | 8 ----- .../modifier-all.sol-0.8.13-compact.json | 8 ----- .../modifier-all.sol-0.8.14-compact.json | 8 ----- .../modifier-all.sol-0.8.15-compact.json | 8 ----- .../modifier-all.sol-0.8.2-compact.json | 8 ----- .../modifier-all.sol-0.8.3-compact.json | 8 ----- .../modifier-all.sol-0.8.4-compact.json | 8 ----- .../modifier-all.sol-0.8.5-compact.json | 8 ----- .../modifier-all.sol-0.8.6-compact.json | 8 ----- .../modifier-all.sol-0.8.7-compact.json | 8 ----- .../modifier-all.sol-0.8.8-compact.json | 8 ----- .../modifier-all.sol-0.8.9-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.0-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.1-compact.json | 8 ----- ...ewexpression-0.4.0.sol-0.4.10-compact.json | 8 ----- ...ewexpression-0.4.0.sol-0.4.11-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.2-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.3-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.4-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.5-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.6-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.7-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.8-compact.json | 8 ----- ...newexpression-0.4.0.sol-0.4.9-compact.json | 8 ----- .../pragma-0.4.0.sol-0.4.0-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.1-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.10-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.11-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.2-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.3-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.4-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.5-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.6-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.7-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.8-compact.json | 3 -- .../pragma-0.4.0.sol-0.4.9-compact.json | 3 -- .../expected/push-all.sol-0.4.0-compact.json | 5 ---- .../expected/push-all.sol-0.4.1-compact.json | 5 ---- .../expected/push-all.sol-0.4.10-compact.json | 5 ---- .../expected/push-all.sol-0.4.11-compact.json | 5 ---- .../expected/push-all.sol-0.4.2-compact.json | 5 ---- .../expected/push-all.sol-0.4.3-compact.json | 5 ---- .../expected/push-all.sol-0.4.4-compact.json | 5 ---- .../expected/push-all.sol-0.4.5-compact.json | 5 ---- .../expected/push-all.sol-0.4.6-compact.json | 5 ---- .../expected/push-all.sol-0.4.7-compact.json | 5 ---- .../expected/push-all.sol-0.4.8-compact.json | 5 ---- .../expected/push-all.sol-0.4.9-compact.json | 5 ---- .../return-all.sol-0.4.0-compact.json | 9 ------ .../return-all.sol-0.4.1-compact.json | 9 ------ .../return-all.sol-0.4.10-compact.json | 9 ------ .../return-all.sol-0.4.11-compact.json | 9 ------ .../return-all.sol-0.4.2-compact.json | 9 ------ .../return-all.sol-0.4.3-compact.json | 9 ------ .../return-all.sol-0.4.4-compact.json | 9 ------ .../return-all.sol-0.4.5-compact.json | 9 ------ .../return-all.sol-0.4.6-compact.json | 9 ------ .../return-all.sol-0.4.7-compact.json | 9 ------ .../return-all.sol-0.4.8-compact.json | 9 ------ .../return-all.sol-0.4.9-compact.json | 9 ------ .../scope-0.4.0.sol-0.4.0-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.1-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.10-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.11-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.2-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.3-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.4-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.5-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.6-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.7-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.8-compact.json | 8 ----- .../scope-0.4.0.sol-0.4.9-compact.json | 8 ----- .../struct-0.4.0.sol-0.4.0-compact.json | 3 -- .../struct-0.4.0.sol-0.4.1-compact.json | 3 -- .../struct-0.4.0.sol-0.4.10-compact.json | 3 -- .../struct-0.4.0.sol-0.4.11-compact.json | 3 -- .../struct-0.4.0.sol-0.4.2-compact.json | 3 -- .../struct-0.4.0.sol-0.4.3-compact.json | 3 -- .../struct-0.4.0.sol-0.4.4-compact.json | 3 -- .../struct-0.4.0.sol-0.4.5-compact.json | 3 -- .../struct-0.4.0.sol-0.4.6-compact.json | 3 -- .../struct-0.4.0.sol-0.4.7-compact.json | 3 -- .../struct-0.4.0.sol-0.4.8-compact.json | 3 -- .../struct-0.4.0.sol-0.4.9-compact.json | 3 -- .../throw-0.4.0.sol-0.4.0-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.1-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.10-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.11-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.2-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.3-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.4-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.5-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.6-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.7-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.8-compact.json | 5 ---- .../throw-0.4.0.sol-0.4.9-compact.json | 5 ---- .../top-level-0.4.0.sol-0.4.0-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.1-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.10-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.11-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.2-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.3-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.4-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.5-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.6-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.7-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.8-compact.json | 3 -- .../top-level-0.4.0.sol-0.4.9-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.0-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.1-compact.json | 3 -- ...level-import-0.4.0.sol-0.4.10-compact.json | 3 -- ...level-import-0.4.0.sol-0.4.11-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.2-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.3-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.4-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.5-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.6-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.7-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.8-compact.json | 3 -- ...-level-import-0.4.0.sol-0.4.9-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.0-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.1-compact.json | 3 -- ...l-import-bis-0.4.0.sol-0.4.10-compact.json | 3 -- ...l-import-bis-0.4.0.sol-0.4.11-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.2-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.3-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.4-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.5-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.6-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.7-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.8-compact.json | 3 -- ...el-import-bis-0.4.0.sol-0.4.9-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.0-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.1-compact.json | 3 -- ...ested-import-0.4.0.sol-0.4.10-compact.json | 3 -- ...ested-import-0.4.0.sol-0.4.11-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.2-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.3-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.4-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.5-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.6-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.7-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.8-compact.json | 3 -- ...nested-import-0.4.0.sol-0.4.9-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.0-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.1-compact.json | 3 -- ...vel_variable-0.4.0.sol-0.4.10-compact.json | 3 -- ...vel_variable-0.4.0.sol-0.4.11-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.2-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.3-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.4-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.5-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.6-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.7-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.8-compact.json | 3 -- ...evel_variable-0.4.0.sol-0.4.9-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.0-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.1-compact.json | 3 -- ...el_variable2-0.4.0.sol-0.4.10-compact.json | 3 -- ...el_variable2-0.4.0.sol-0.4.11-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.2-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.3-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.4-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.5-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.6-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.7-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.8-compact.json | 3 -- ...vel_variable2-0.4.0.sol-0.4.9-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.0-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.1-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.10-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.11-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.2-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.3-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.4-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.5-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.6-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.7-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.8-compact.json | 3 -- .../trycatch-0.4.0.sol-0.4.9-compact.json | 3 -- ...pleexpression-0.4.0.sol-0.4.0-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.1-compact.json | 5 ---- ...leexpression-0.4.0.sol-0.4.10-compact.json | 5 ---- ...leexpression-0.4.0.sol-0.4.11-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.2-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.3-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.4-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.5-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.6-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.7-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.8-compact.json | 5 ---- ...pleexpression-0.4.0.sol-0.4.9-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.0-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.1-compact.json | 5 ---- ...ryexpression-0.4.0.sol-0.4.10-compact.json | 5 ---- ...ryexpression-0.4.0.sol-0.4.11-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.2-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.3-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.4-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.5-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.6-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.7-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.8-compact.json | 5 ---- ...aryexpression-0.4.0.sol-0.4.9-compact.json | 5 ---- .../unchecked-0.4.0.sol-0.4.0-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.1-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.10-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.11-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.2-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.3-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.4-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.5-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.6-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.7-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.8-compact.json | 3 -- .../unchecked-0.4.0.sol-0.4.9-compact.json | 3 -- ...bal_variables-0.4.0.sol-0.4.0-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.1-compact.json | 10 ------- ...al_variables-0.4.0.sol-0.4.10-compact.json | 10 ------- ...al_variables-0.4.0.sol-0.4.11-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.2-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.3-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.4-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.5-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.6-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.7-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.8-compact.json | 10 ------- ...bal_variables-0.4.0.sol-0.4.9-compact.json | 10 ------- ...user_defined_types.sol-0.8.10-compact.json | 10 ------- ...user_defined_types.sol-0.8.11-compact.json | 10 ------- ...user_defined_types.sol-0.8.12-compact.json | 10 ------- .../user_defined_types.sol-0.8.8-compact.json | 10 ------- .../top-level-0.8.8.sol-0.8.10-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.11-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.12-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.13-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.14-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.15-compact.json | 2 +- .../top-level-0.8.8.sol-0.8.8-compact.json | 2 +- .../using-for-0.4.0.sol-0.4.0-compact.json | 3 -- .../using-for-0.4.1.sol-0.4.1-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.10-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.11-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.2-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.3-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.4-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.5-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.6-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.7-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.8-compact.json | 9 ------ .../using-for-0.4.1.sol-0.4.9-compact.json | 9 ------ .../variable-0.4.0.sol-0.4.0-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.1-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.10-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.11-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.2-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.3-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.4-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.5-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.6-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.7-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.8-compact.json | 6 ---- .../variable-0.4.0.sol-0.4.9-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.10-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.11-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.5-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.6-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.7-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.8-compact.json | 6 ---- .../variable-0.4.5.sol-0.4.9-compact.json | 6 ---- .../expected/while-all.sol-0.4.0-compact.json | 5 ---- .../expected/while-all.sol-0.4.1-compact.json | 5 ---- .../while-all.sol-0.4.10-compact.json | 5 ---- .../while-all.sol-0.4.11-compact.json | 5 ---- .../expected/while-all.sol-0.4.2-compact.json | 5 ---- .../expected/while-all.sol-0.4.3-compact.json | 5 ---- .../expected/while-all.sol-0.4.4-compact.json | 5 ---- .../expected/while-all.sol-0.4.5-compact.json | 5 ---- .../expected/while-all.sol-0.4.6-compact.json | 5 ---- .../expected/while-all.sol-0.4.7-compact.json | 5 ---- .../expected/while-all.sol-0.4.8-compact.json | 5 ---- .../expected/while-all.sol-0.4.9-compact.json | 5 ---- .../expected/yul-0.4.0.sol-0.4.0-compact.json | 5 ---- .../expected/yul-0.4.1.sol-0.4.1-compact.json | 6 ---- .../yul-0.4.1.sol-0.4.10-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.2-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.3-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.4-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.5-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.6-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.7-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.8-compact.json | 6 ---- .../expected/yul-0.4.1.sol-0.4.9-compact.json | 6 ---- .../yul-0.4.11.sol-0.4.11-compact.json | 6 ---- .../yul-0.4.11.sol-0.6.0-compact.json | 2 +- .../yul-0.4.11.sol-0.6.1-compact.json | 2 +- .../yul-0.4.11.sol-0.6.10-compact.json | 2 +- .../yul-0.4.11.sol-0.6.11-compact.json | 2 +- .../yul-0.4.11.sol-0.6.12-compact.json | 2 +- .../yul-0.4.11.sol-0.6.2-compact.json | 2 +- .../yul-0.4.11.sol-0.6.3-compact.json | 2 +- .../yul-0.4.11.sol-0.6.4-compact.json | 2 +- .../yul-0.4.11.sol-0.6.5-compact.json | 2 +- .../yul-0.4.11.sol-0.6.6-compact.json | 2 +- .../yul-0.4.11.sol-0.6.7-compact.json | 2 +- .../yul-0.4.11.sol-0.6.8-compact.json | 2 +- .../yul-0.4.11.sol-0.6.9-compact.json | 2 +- .../expected/yul-0.7.0.sol-0.7.0-compact.json | 2 +- .../expected/yul-0.7.0.sol-0.7.1-compact.json | 2 +- .../expected/yul-0.7.0.sol-0.7.2-compact.json | 2 +- .../expected/yul-0.7.0.sol-0.7.3-compact.json | 2 +- .../expected/yul-0.7.0.sol-0.7.4-compact.json | 2 +- .../expected/yul-0.7.5.sol-0.7.5-compact.json | 2 +- .../expected/yul-0.7.5.sol-0.7.6-compact.json | 2 +- .../expected/yul-0.8.0.sol-0.8.0-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.1-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.10-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.11-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.12-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.13-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.14-compact.json | 4 +-- .../yul-0.8.0.sol-0.8.15-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.2-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.3-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.4-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.5-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.6-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.7-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.8-compact.json | 4 +-- .../expected/yul-0.8.0.sol-0.8.9-compact.json | 4 +-- ...te-constant-access.sol-0.8.16-compact.json | 4 +-- 699 files changed, 141 insertions(+), 3911 deletions(-) delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-legacy.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.12-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.13-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.14-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.15-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.12-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.11-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-compact.json delete mode 100644 tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-compact.json diff --git a/slither/core/cfg/node.py b/slither/core/cfg/node.py index 2a48bd235..596eb0e81 100644 --- a/slither/core/cfg/node.py +++ b/slither/core/cfg/node.py @@ -74,6 +74,7 @@ class NodeType(Enum): IF = "IF" VARIABLE = "NEW VARIABLE" # Variable declaration ASSEMBLY = "INLINE ASM" + ENDASSEMBLY = "END INLINE ASM" IFLOOP = "IF_LOOP" # Nodes where control flow merges diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 35ca51aeb..01a4d2238 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -983,7 +983,9 @@ class FunctionSolc(CallerContextExpression): # technically, entrypoint and exitpoint are YulNodes and we should be returning a NodeSolc here # but they both expose an underlying_node so oh well link_underlying_nodes(node, entrypoint) - node = exitpoint + end_assembly = self._new_node(NodeType.ENDASSEMBLY, statement["src"], scope) + link_underlying_nodes(exitpoint, end_assembly) + node = end_assembly else: asm_node = self._new_node(NodeType.ASSEMBLY, statement["src"], scope) self._function.contains_assembly = True diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.0-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.1-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.10-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.11-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.12-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.2-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.3-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.4-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.5-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.6-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.7-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.8-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.6.9-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.0-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.1-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.2-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.3-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.4-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.5-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.7.6-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.0-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.0-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.1-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.1-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.10-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.10-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.11-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.11-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.12-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.12-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.13-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.13-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.14-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.14-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.15-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.15-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.2-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.2-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.3-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.3-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.4-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.4-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.5-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.5-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.6-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.6-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.7-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.7-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.8-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.8-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.9-compact.json index 5bfb159c1..ff18e4e47 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-all.sol-0.8.9-compact.json @@ -1,6 +1,6 @@ { "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->7;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->1;\n}\n", - "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: _ 4\n\"];\n}\n" + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->9;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: INLINE ASM 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: END INLINE ASM 8\n\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->1;\n}\n", + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n4->5;\n5[label=\"Node Type: _ 5\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json index a48faa23d..0c50d020c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.6.9-compact.json @@ -1,6 +1,6 @@ { "A": { - "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n", "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json index a48faa23d..0c50d020c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.7.6-compact.json @@ -1,6 +1,6 @@ { "A": { - "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n", "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", diff --git a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json index a48faa23d..0c50d020c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/assembly-functions.sol-0.8.16-compact.json @@ -1,6 +1,6 @@ { "A": { - "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n", "foo.asm_0.f()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "foo.asm_0.f.z.x()": "digraph{\n0[label=\"Node Type: INLINE ASM 0\n\"];\n0->1;\n1[label=\"Node Type: ENTRY_POINT 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 8db75806e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.7-compact.json deleted file mode 100644 index 8f9f9857b..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.8-compact.json deleted file mode 100644 index 8f9f9857b..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.9-compact.json deleted file mode 100644 index 8f9f9857b..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/assignment-0.4.7.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index f7313f2eb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.7-compact.json deleted file mode 100644 index 8939b57f2..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.8-compact.json deleted file mode 100644 index 8939b57f2..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.9-compact.json deleted file mode 100644 index 8939b57f2..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/binaryoperation-0.4.7.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.0-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.1-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.10-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.11-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.2-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.3-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.4-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.5-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.6-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.7-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.8-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.9-compact.json deleted file mode 100644 index b9b7fc93e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/break-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: BREAK 7\n\"];\n7->3;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: BREAK 20\n\"];\n20->16;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.0-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.1-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.10-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.11-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.2-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.3-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.4-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.5-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.6-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.7-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.8-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.9-compact.json deleted file mode 100644 index 113bb5a14..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/call_to_variable-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": {}, - "D": { - "f(C)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.0-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.1-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.10-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.11-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.2-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.3-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.4-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.5-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.6-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.7-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.8-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.9-compact.json deleted file mode 100644 index a53745acd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/comment-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "A": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.0-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.1-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.10-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.11-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.2-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.3-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.4-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.5-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.6-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.7-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.8-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.9-compact.json deleted file mode 100644 index bba15d9bd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/continue-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n3->13;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: IF 6\n\"];\n6->7[label=\"True\"];\n6->8[label=\"False\"];\n7[label=\"Node Type: CONTINUE 7\n\"];\n7->2;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->5;\n11[label=\"Node Type: BEGIN_LOOP 11\n\"];\n11->14;\n12[label=\"Node Type: END_LOOP 12\n\"];\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->11;\n14[label=\"Node Type: IF_LOOP 14\n\"];\n14->17[label=\"True\"];\n14->12[label=\"False\"];\n15[label=\"Node Type: BEGIN_LOOP 15\n\"];\n15->18;\n16[label=\"Node Type: END_LOOP 16\n\"];\n16->24;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->15;\n18[label=\"Node Type: IF_LOOP 18\n\"];\n18->19[label=\"True\"];\n18->16[label=\"False\"];\n19[label=\"Node Type: IF 19\n\"];\n19->20[label=\"True\"];\n19->21[label=\"False\"];\n20[label=\"Node Type: CONTINUE 20\n\"];\n20->15;\n21[label=\"Node Type: END_IF 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->18;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->14;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 5c911c175..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/contract-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "A": {}, - "B": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "D": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "D()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - }, - "E": { - "B(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "F": {}, - "G": {}, - "H": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.5-compact.json deleted file mode 100644 index 1cf317575..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->4;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->9;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.6-compact.json deleted file mode 100644 index 1cf317575..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->4;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->9;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.7-compact.json deleted file mode 100644 index 1cf317575..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->4;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->9;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.8-compact.json deleted file mode 100644 index 1cf317575..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->4;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->9;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.9-compact.json deleted file mode 100644 index 1cf317575..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/dowhile-0.4.5.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->4;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->9;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.21-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.22-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.23-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.24-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.25-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-compact.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-compact.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-legacy.json deleted file mode 100644 index c940f7b41..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.21.sol-0.4.26-legacy.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "emitWithKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-compact.json deleted file mode 100644 index a4e54d0ee..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-legacy.json deleted file mode 100644 index a4e54d0ee..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.8-legacy.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-compact.json deleted file mode 100644 index a4e54d0ee..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-legacy.json b/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-legacy.json deleted file mode 100644 index a4e54d0ee..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/emit-0.4.8.sol-0.4.9-legacy.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "emitNoKeyword()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/enum-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/event-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.0-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.1-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.10-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.11-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.2-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.3-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.4-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.5-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.6-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.7-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.8-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.9-compact.json deleted file mode 100644 index fe24348d8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/for-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "C": { - "normalLoopBlockBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopExprBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "normalLoopNoBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->5;\n}\n", - "loopNoPre()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoPreCond()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPrePost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->4[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n", - "loopNoCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->3;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->2;\n}\n", - "loopNoPreCondPost()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: BEGIN_LOOP 3\n\"];\n3->5;\n4[label=\"Node Type: END_LOOP 4\n\"];\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: BREAK 6\n\"];\n6->4;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->3;\n}\n", - "loopNoPreCondPostBody()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: BEGIN_LOOP 1\n\"];\n1->1;\n1->2;\n2[label=\"Node Type: END_LOOP 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 5406c6dd0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/function-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "C1": { - "C1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C2": { - "C2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "fallback()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C3": { - "C3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", - "modifierNoArgs()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "modifierWithArgs(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - }, - "C4": { - "hasArgs(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasReturns()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "hasArgsAndReturns(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C5": { - "constantFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "payableFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "externalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "publicFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "privateFunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "abstractFunc()": "digraph{\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 771efb110..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.5-compact.json deleted file mode 100644 index b36758ed7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.5-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.6-compact.json deleted file mode 100644 index b36758ed7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.6-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.7-compact.json deleted file mode 100644 index b36758ed7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.7-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.8-compact.json deleted file mode 100644 index b36758ed7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.8-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.9-compact.json deleted file mode 100644 index b36758ed7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/functioncall-0.4.5.sol-0.4.9-compact.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "I": { - "I()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n", - "publicTarget()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "internalTarget(uint256,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "cursed()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/global_variables-0.8.18.sol-0.8.18-compact.json b/tests/e2e/solc_parsing/test_data/expected/global_variables-0.8.18.sol-0.8.18-compact.json index b74cf7115..5f42b943e 100644 --- a/tests/e2e/solc_parsing/test_data/expected/global_variables-0.8.18.sol-0.8.18-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/global_variables-0.8.18.sol-0.8.18-compact.json @@ -1,6 +1,6 @@ { "C": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "g()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.0-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.1-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.10-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.11-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.2-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.3-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.4-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.5-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.6-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.7-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.8-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.9-compact.json deleted file mode 100644 index c0c884b4e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/if-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "ifWithoutElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END_IF 3\n\"];\n}\n", - "ifWithElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->4;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "ifWithElseIf()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->9;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->8;\n5[label=\"Node Type: IF 5\n\"];\n5->6[label=\"True\"];\n5->7[label=\"False\"];\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n7->8;\n8[label=\"Node Type: END_IF 8\n\"];\n8->9;\n9[label=\"Node Type: END_IF 9\n\"];\n}\n", - "ifWithElseIfElse()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->7;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->6;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: END_IF 6\n\"];\n6->7;\n7[label=\"Node Type: END_IF 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/import_interface_with_struct_from_top_level-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.0-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.1-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.10-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.11-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.2-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.3-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.4-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.5-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.6-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.7-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.8-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.9-compact.json deleted file mode 100644 index 43190fcd6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexaccess-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/indexrangeaccess-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/library_implicit_conversion-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 141d16af3..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.10-compact.json deleted file mode 100644 index b29327c65..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.11-compact.json deleted file mode 100644 index b29327c65..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/literal-0.4.10.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 2772fda53..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/memberaccess-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 228af371a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/minmax-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.0-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.1-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.10-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.11-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.2-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.3-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.4-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.5-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.6-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.7-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.8-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.9-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.0-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.1-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.2-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.3-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.4-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.5-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-legacy.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-legacy.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.7.6-legacy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.0-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.1-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.10-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.10-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.11-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.11-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.12-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.12-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.13-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.13-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.14-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.14-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.15-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.15-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.2-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.3-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.4-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.5-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.6-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.7-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.7-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.8-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.8-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.9-compact.json deleted file mode 100644 index 34aad8ef1..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/modifier-all.sol-0.8.9-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "C": { - "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", - "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", - "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index cf3c4f4ea..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/newexpression-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "B": { - "B()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" - }, - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/pragma-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.0-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.1-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.10-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.11-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.2-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.3-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.4-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.5-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.6-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.7-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.8-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.9-compact.json deleted file mode 100644 index a1a35e654..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/push-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.0-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.1-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.10-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.11-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.2-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.3-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.4-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.5-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.6-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.7-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.8-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.9-compact.json deleted file mode 100644 index 7eddd38f6..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/return-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "C": { - "returnConstant()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "returnVariable()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n", - "returnTuple()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: RETURN 3\n\"];\n}\n", - "returnTernary()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->3;\n3[label=\"Node Type: IF 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: RETURN 4\n\"];\n5[label=\"Node Type: RETURN 5\n\"];\n}\n", - "returnDelete()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 00c3dbb1a..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/scope-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Scope": { - "nested_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n}\n", - "if_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->4;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: END_IF 4\n\"];\n}\n", - "while_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n}\n", - "for_scope()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->4;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->5;\n3[label=\"Node Type: END_LOOP 3\n\"];\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->2;\n5[label=\"Node Type: IF_LOOP 5\n\"];\n5->6[label=\"True\"];\n5->3[label=\"False\"];\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->5;\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/struct-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index a444e777e..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/throw-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: IF 1\n\"];\n1->2[label=\"True\"];\n1->3[label=\"False\"];\n2[label=\"Node Type: THROW 2\n\"];\n3[label=\"Node Type: END_IF 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-import-bis-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top-level-nested-import-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 7caa60cf7..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/top_level_variable2-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "A": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/trycatch-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index b5912e6b8..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/tupleexpression-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index b4c60f249..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unaryexpression-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/unchecked-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index 94dd85fe0..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/units_and_global_variables-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Test": { - "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n}\n", - "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n}\n", - "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n}\n", - "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", - "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", - "contract_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.10-compact.json deleted file mode 100644 index 06367c7cd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.10-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "B": { - "u()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - }, - "D": {}, - "C": { - "f(Left[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.11-compact.json deleted file mode 100644 index 06367c7cd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.11-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "B": { - "u()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - }, - "D": {}, - "C": { - "f(Left[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.12-compact.json deleted file mode 100644 index 06367c7cd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.12-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "B": { - "u()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - }, - "D": {}, - "C": { - "f(Left[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.8-compact.json deleted file mode 100644 index 06367c7cd..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_types.sol-0.8.8-compact.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "B": { - "u()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" - }, - "D": {}, - "C": { - "f(Left[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.10-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.10-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.11-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.11-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.12-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.12-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.13-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.13-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.14-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.14-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.15-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.15-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.8-compact.json index c8211c636..6a50f34f7 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/top-level-0.8.8.sol-0.8.8-compact.json @@ -1,5 +1,5 @@ { "Test": { - "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "set(StackTop,uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 0008a4469..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.1-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.1-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.10-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.10-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.11-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.11-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.2-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.2-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.3-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.3-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.4-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.4-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.5-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.5-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.6-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.6-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.7-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.7-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.8-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.8-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.9-compact.json deleted file mode 100644 index 27fa7c323..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/using-for-0.4.1.sol-0.4.9-compact.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "L1": { - "f(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "L2": { - "f(bytes32)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" - }, - "C": {} -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.1-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.1-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.10-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.10-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.11-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.11-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.2-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.2-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.3-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.3-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.4-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.4-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.5-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.5-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.6-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.6-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.7-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.7-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.8-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.8-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.9-compact.json deleted file mode 100644 index cddfa6dae..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.0.sol-0.4.9-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.10-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.10-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.11-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.11-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.5-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.5-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.6-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.6-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.7-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.7-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.8-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.8-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.9-compact.json deleted file mode 100644 index 439c5ec12..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/variable-0.4.5.sol-0.4.9-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "C": { - "basic()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: NEW VARIABLE 11\n\"];\n11->12;\n12[label=\"Node Type: NEW VARIABLE 12\n\"];\n12->13;\n13[label=\"Node Type: NEW VARIABLE 13\n\"];\n13->14;\n14[label=\"Node Type: NEW VARIABLE 14\n\"];\n14->15;\n15[label=\"Node Type: NEW VARIABLE 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n}\n", - "complex()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: NEW VARIABLE 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.0-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.1-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.1-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.10-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.10-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.11-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.11-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.2-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.2-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.3-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.3-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.4-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.4-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.5-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.5-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.6-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.6-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.7-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.7-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.8-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.8-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.9-compact.json deleted file mode 100644 index 4d9657391..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/while-all.sol-0.4.9-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: BEGIN_LOOP 2\n\"];\n2->3;\n3[label=\"Node Type: IF_LOOP 3\n\"];\n3->4[label=\"True\"];\n3->5[label=\"False\"];\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->3;\n5[label=\"Node Type: END_LOOP 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: BEGIN_LOOP 7\n\"];\n7->8;\n8[label=\"Node Type: IF_LOOP 8\n\"];\n8->9[label=\"True\"];\n8->10[label=\"False\"];\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->8;\n10[label=\"Node Type: END_LOOP 10\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-compact.json deleted file mode 100644 index 8f6ef922b..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.0.sol-0.4.0-compact.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.1-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.10-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.2-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.3-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.4-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.5-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.6-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.7-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.8-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.1.sol-0.4.9-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-compact.json deleted file mode 100644 index a9569a2fb..000000000 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.4.11-compact.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "L": {}, - "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n}\n" - } -} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.0-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.1-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.10-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.11-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.12-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.2-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.3-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.4-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.5-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.6-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.7-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.8-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.4.11.sol-0.6.9-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.0-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.1-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.2-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.3-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-compact.json index 04cb49aa8..bb6d4d562 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.0.sol-0.7.4-compact.json @@ -1,6 +1,6 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: END INLINE ASM 30\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-compact.json index c180eeda7..55d59666c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.5-compact.json @@ -1,5 +1,5 @@ { "C": { - "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" + "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-compact.json index c180eeda7..55d59666c 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.7.5.sol-0.7.6-compact.json @@ -1,5 +1,5 @@ { "C": { - "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n" + "f(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.0-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.0-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.0-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.0-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.1-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.1-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.1-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.1-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.10-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.10-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.11-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.11-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.12-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.12-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.13-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.13-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.14-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.14-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.15-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.15-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.2-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.2-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.2-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.2-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.3-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.3-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.3-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.3-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.4-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.4-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.5-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.5-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.6-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.6-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.7-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.7-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.8-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.8-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.9-compact.json index b58e03af7..6d58794c9 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-0.8.0.sol-0.8.9-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", - "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n31->32;\n32[label=\"Node Type: END INLINE ASM 32\n\"];\n}\n", + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: END INLINE ASM 3\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/yul-state-constant-access.sol-0.8.16-compact.json b/tests/e2e/solc_parsing/test_data/expected/yul-state-constant-access.sol-0.8.16-compact.json index 6c6bc9377..62a5f1a90 100644 --- a/tests/e2e/solc_parsing/test_data/expected/yul-state-constant-access.sol-0.8.16-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/yul-state-constant-access.sol-0.8.16-compact.json @@ -1,12 +1,12 @@ { "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", + "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n", "f3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" }, "B": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n", - "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n", + "f2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: INLINE ASM 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: END INLINE ASM 4\n\"];\n}\n", "f3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file From 47800850cc70bca405687c4ba184fb5321a66a9b Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 7 Aug 2023 16:59:13 -0500 Subject: [PATCH 155/338] Black --- slither/utils/code_generation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/utils/code_generation.py b/slither/utils/code_generation.py index 907100239..215757010 100644 --- a/slither/utils/code_generation.py +++ b/slither/utils/code_generation.py @@ -12,7 +12,7 @@ from slither.core.solidity_types import ( MappingType, ArrayType, ElementaryType, - TypeAlias + TypeAlias, ) from slither.core.declarations import Structure, StructureContract, Enum, Contract From 73d8b7f2f2357c47cf42436b586d84314984a43b Mon Sep 17 00:00:00 2001 From: webthethird Date: Mon, 7 Aug 2023 17:12:31 -0500 Subject: [PATCH 156/338] Add regression test for handling external structs --- .../test_data/code_generation/CodeGeneration.sol | 13 +++++++++++-- tests/unit/utils/test_data/code_generation/IFee.sol | 5 +++++ .../code_generation/TEST_generated_code.sol | 4 ++++ .../TEST_generated_code_not_unrolled.sol | 4 ++++ 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/unit/utils/test_data/code_generation/IFee.sol diff --git a/tests/unit/utils/test_data/code_generation/CodeGeneration.sol b/tests/unit/utils/test_data/code_generation/CodeGeneration.sol index 6f1f63c72..292a4b43f 100644 --- a/tests/unit/utils/test_data/code_generation/CodeGeneration.sol +++ b/tests/unit/utils/test_data/code_generation/CodeGeneration.sol @@ -1,7 +1,10 @@ pragma solidity ^0.8.4; + +import "./IFee.sol"; + interface I { - enum SomeEnum { ONE, TWO, THREE } - error ErrorWithEnum(SomeEnum e); + enum SomeEnum { ONE, TWO, THREE } + error ErrorWithEnum(SomeEnum e); } contract TestContract is I { @@ -62,4 +65,10 @@ contract TestContract is I { function setOtherI(I _i) public { otherI = _i; } + + function newFee(uint128 fee) public returns (IFee.Fee memory) { + IFee.Fee memory _fee; + _fee.fee = fee; + return _fee; + } } \ No newline at end of file diff --git a/tests/unit/utils/test_data/code_generation/IFee.sol b/tests/unit/utils/test_data/code_generation/IFee.sol new file mode 100644 index 000000000..17560f60c --- /dev/null +++ b/tests/unit/utils/test_data/code_generation/IFee.sol @@ -0,0 +1,5 @@ +interface IFee { + struct Fee { + uint128 fee; + } +} diff --git a/tests/unit/utils/test_data/code_generation/TEST_generated_code.sol b/tests/unit/utils/test_data/code_generation/TEST_generated_code.sol index 373fba9ca..5240e1063 100644 --- a/tests/unit/utils/test_data/code_generation/TEST_generated_code.sol +++ b/tests/unit/utils/test_data/code_generation/TEST_generated_code.sol @@ -14,6 +14,9 @@ interface ITestContract { struct Nested { St st; } + struct Fee { + uint128 fee; + } function stateA() external returns (uint256); function owner() external returns (address); function structsMap(address,uint256) external returns (uint256); @@ -26,5 +29,6 @@ interface ITestContract { function getSt(uint256) external view returns (uint256); function removeSt(uint256) external; function setOtherI(address) external; + function newFee(uint128) external returns (uint128); } diff --git a/tests/unit/utils/test_data/code_generation/TEST_generated_code_not_unrolled.sol b/tests/unit/utils/test_data/code_generation/TEST_generated_code_not_unrolled.sol index 0cc4dc040..1154ec4cc 100644 --- a/tests/unit/utils/test_data/code_generation/TEST_generated_code_not_unrolled.sol +++ b/tests/unit/utils/test_data/code_generation/TEST_generated_code_not_unrolled.sol @@ -14,6 +14,9 @@ interface ITestContract { struct Nested { St st; } + struct Fee { + uint128 fee; + } function stateA() external returns (uint256); function owner() external returns (address); function structsMap(address,uint256) external returns (St memory); @@ -26,5 +29,6 @@ interface ITestContract { function getSt(uint256) external view returns (St memory); function removeSt(St memory) external; function setOtherI(address) external; + function newFee(uint128) external returns (Fee memory); } From 4b0482014dbf911f886a5f1221260ccb71a7cd22 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 8 Aug 2023 10:01:12 -0500 Subject: [PATCH 157/338] chore: bump sigstore to 2.0.0 (#2081) --- .github/workflows/publish.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 24f04ee87..977a92ab2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,8 +47,7 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.8.8 - name: sign - uses: sigstore/gh-action-sigstore-python@v1.2.3 + uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true - bundle-only: true From 2bc6a0f1a4349e2cb6a45bf7a078f65e050d7e28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:22:08 +0000 Subject: [PATCH 158/338] Bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.10 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.8 to 1.8.10. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.8...v1.8.10) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 977a92ab2..ed11178e3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: path: dist/ - name: publish - uses: pypa/gh-action-pypi-publish@v1.8.8 + uses: pypa/gh-action-pypi-publish@v1.8.10 - name: sign uses: sigstore/gh-action-sigstore-python@v2.0.0 From 81c0c8cd88a437f39fa6aece06470f7e8c1b1a31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:22:13 +0000 Subject: [PATCH 159/338] Bump sigstore/gh-action-sigstore-python from 2.0.0 to 2.0.1 Bumps [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases) - [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: sigstore/gh-action-sigstore-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 977a92ab2..cd6feacce 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,7 +47,7 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.8.8 - name: sign - uses: sigstore/gh-action-sigstore-python@v2.0.0 + uses: sigstore/gh-action-sigstore-python@v2.0.1 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true From 7b3e0645e33185c3081b26c8cfc9ff159808284f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 17 Aug 2023 22:22:48 -0500 Subject: [PATCH 160/338] WIP --- slither/__main__.py | 10 +- slither/core/compilation_unit.py | 24 ++ slither/core/declarations/contract.py | 2 +- slither/core/declarations/function.py | 6 +- slither/core/expressions/binary_operation.py | 2 +- slither/core/expressions/identifier.py | 2 +- slither/slither.py | 35 +- .../slither_compilation_unit_solc.py | 18 +- .../visitors/slithir/expression_to_slithir.py | 1 + slither/vyper_parsing/__init__.py | 0 slither/vyper_parsing/ast/__init__.py | 0 slither/vyper_parsing/ast/ast.py | 373 ++++++++++++++++++ slither/vyper_parsing/ast/types.py | 270 +++++++++++++ slither/vyper_parsing/cfg/__init__.py | 0 slither/vyper_parsing/cfg/node.py | 66 ++++ .../vyper_parsing/declarations/__init__.py | 0 .../vyper_parsing/declarations/contract.py | 176 +++++++++ slither/vyper_parsing/declarations/event.py | 43 ++ .../vyper_parsing/declarations/function.py | 340 ++++++++++++++++ .../vyper_parsing/declarations/modifier.py | 107 +++++ slither/vyper_parsing/declarations/struct.py | 35 ++ slither/vyper_parsing/expressions/__init__.py | 0 .../expressions/expression_parsing.py | 308 +++++++++++++++ .../expressions/find_variable.py | 240 +++++++++++ slither/vyper_parsing/type_parsing.py | 55 +++ slither/vyper_parsing/variables/__init__.py | 0 .../vyper_parsing/variables/event_variable.py | 21 + .../variables/function_type_variable.py | 13 + .../vyper_parsing/variables/local_variable.py | 32 ++ .../vyper_parsing/variables/state_variable.py | 30 ++ .../variables/structure_variable.py | 20 + .../variables/variable_declaration.py | 150 +++++++ .../vyper_parsing/vyper_compilation_unit.py | 94 +++++ 33 files changed, 2438 insertions(+), 35 deletions(-) create mode 100644 slither/vyper_parsing/__init__.py create mode 100644 slither/vyper_parsing/ast/__init__.py create mode 100644 slither/vyper_parsing/ast/ast.py create mode 100644 slither/vyper_parsing/ast/types.py create mode 100644 slither/vyper_parsing/cfg/__init__.py create mode 100644 slither/vyper_parsing/cfg/node.py create mode 100644 slither/vyper_parsing/declarations/__init__.py create mode 100644 slither/vyper_parsing/declarations/contract.py create mode 100644 slither/vyper_parsing/declarations/event.py create mode 100644 slither/vyper_parsing/declarations/function.py create mode 100644 slither/vyper_parsing/declarations/modifier.py create mode 100644 slither/vyper_parsing/declarations/struct.py create mode 100644 slither/vyper_parsing/expressions/__init__.py create mode 100644 slither/vyper_parsing/expressions/expression_parsing.py create mode 100644 slither/vyper_parsing/expressions/find_variable.py create mode 100644 slither/vyper_parsing/type_parsing.py create mode 100644 slither/vyper_parsing/variables/__init__.py create mode 100644 slither/vyper_parsing/variables/event_variable.py create mode 100644 slither/vyper_parsing/variables/function_type_variable.py create mode 100644 slither/vyper_parsing/variables/local_variable.py create mode 100644 slither/vyper_parsing/variables/state_variable.py create mode 100644 slither/vyper_parsing/variables/structure_variable.py create mode 100644 slither/vyper_parsing/variables/variable_declaration.py create mode 100644 slither/vyper_parsing/vyper_compilation_unit.py diff --git a/slither/__main__.py b/slither/__main__.py index d9201a90d..e68f0b67f 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -870,11 +870,11 @@ def main_impl( logging.error(red(output_error)) logging.error("Please report an issue to https://github.com/crytic/slither/issues") - except Exception: # pylint: disable=broad-except - output_error = traceback.format_exc() - traceback.print_exc() - logging.error(f"Error in {args.filename}") # pylint: disable=logging-fstring-interpolation - logging.error(output_error) + # except Exception: # pylint: disable=broad-except + # output_error = traceback.format_exc() + # traceback.print_exc() + # logging.error(f"Error in {args.filename}") # pylint: disable=logging-fstring-interpolation + # logging.error(output_error) # If we are outputting JSON, capture the redirected output and disable the redirect to output the final JSON. if outputting_json: diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 6d24786eb..8e801ea95 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -1,4 +1,5 @@ import math +from enum import Enum from typing import Optional, Dict, List, Set, Union, TYPE_CHECKING, Tuple from crytic_compile import CompilationUnit, CryticCompile @@ -29,6 +30,20 @@ if TYPE_CHECKING: from slither.core.slither_core import SlitherCore +class Language(Enum): + SOLIDITY = "solidity" + VYPER = "vyper" + + @staticmethod + def from_str(label: str): + if label == "solc": + return Language.SOLIDITY + elif label == "vyper": + return Language.VYPER + else: + raise ValueError(f"Unknown language: {label}") + + # pylint: disable=too-many-instance-attributes,too-many-public-methods class SlitherCompilationUnit(Context): def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit) -> None: @@ -36,6 +51,7 @@ class SlitherCompilationUnit(Context): self._core = core self._crytic_compile_compilation_unit = crytic_compilation_unit + self._language = Language.from_str(crytic_compilation_unit.compiler_version.compiler) # Top level object self.contracts: List[Contract] = [] @@ -81,6 +97,13 @@ class SlitherCompilationUnit(Context): # region Compiler ################################################################################### ################################################################################### + @property + def is_vyper(self) -> bool: + return self._language == Language.VYPER + + @property + def is_solidity(self) -> bool: + return self._language == Language.SOLIDITY @property def compiler_version(self) -> CompilerVersion: @@ -259,6 +282,7 @@ class SlitherCompilationUnit(Context): ################################################################################### def compute_storage_layout(self) -> None: + assert self.is_solidity for contract in self.contracts_derived: self._storage_layouts[contract.name] = {} diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 9b1488db3..5e3ab4571 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -136,7 +136,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods @property def id(self) -> int: """Unique id.""" - assert self._id + assert self._id is not None return self._id @id.setter diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index e77801961..d549c9615 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -106,7 +106,7 @@ def _filter_state_variables_written(expressions: List["Expression"]): ret.append(expression.expression_left) return ret - +#TODO replace class FunctionLanguage(Enum): Solidity = 0 Yul = 1 @@ -1521,6 +1521,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu def _analyze_read_write(self) -> None: """Compute variables read/written/...""" write_var = [x.variables_written_as_expression for x in self.nodes] + print(write_var) write_var = [x for x in write_var if x] write_var = [item for sublist in write_var for item in sublist] write_var = list(set(write_var)) @@ -1756,6 +1757,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu node.irs_ssa = [ir for ir in node.irs_ssa if not self._unchange_phi(ir)] def generate_slithir_and_analyze(self) -> None: + print("generate_slithir_and_analyze") + print(self.nodes) + for node in self.nodes: node.slithir_generation() diff --git a/slither/core/expressions/binary_operation.py b/slither/core/expressions/binary_operation.py index a395d07cf..271975e77 100644 --- a/slither/core/expressions/binary_operation.py +++ b/slither/core/expressions/binary_operation.py @@ -42,7 +42,7 @@ class BinaryOperationType(Enum): # pylint: disable=too-many-branches @staticmethod def get_type( - operation_type: "BinaryOperation", + operation_type: "str", ) -> "BinaryOperationType": if operation_type == "**": return BinaryOperationType.POWER diff --git a/slither/core/expressions/identifier.py b/slither/core/expressions/identifier.py index 8ffabad89..d4c426100 100644 --- a/slither/core/expressions/identifier.py +++ b/slither/core/expressions/identifier.py @@ -26,7 +26,7 @@ class Identifier(Expression): ], ) -> None: super().__init__() - + assert value # pylint: disable=import-outside-toplevel from slither.core.declarations import Contract, SolidityVariable, SolidityFunction from slither.solc_parsing.yul.evm_functions import YulBuiltin diff --git a/slither/slither.py b/slither/slither.py index 85f852e1d..07444c72f 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -11,6 +11,7 @@ from slither.detectors.abstract_detector import AbstractDetector, DetectorClassi from slither.exceptions import SlitherError from slither.printers.abstract_printer import AbstractPrinter from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc +from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit from slither.utils.output import Output logger = logging.getLogger("Slither") @@ -62,16 +63,6 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes triage_mode (bool): if true, switch to triage mode (default false) exclude_dependencies (bool): if true, exclude results that are only related to dependencies generate_patches (bool): if true, patches are generated (json output only) - - truffle_ignore (bool): ignore truffle.js presence (default false) - truffle_build_directory (str): build truffle directory (default 'build/contracts') - truffle_ignore_compile (bool): do not run truffle compile (default False) - truffle_version (str): use a specific truffle version (default None) - - embark_ignore (bool): ignore embark.js presence (default false) - embark_ignore_compile (bool): do not run embark build (default False) - embark_overwrite_config (bool): overwrite original config file (default false) - change_line_prefix (str): Change the line prefix (default #) for the displayed source codes (i.e. file.sol#1). @@ -108,13 +99,25 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes for compilation_unit in crytic_compile.compilation_units.values(): compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) self._compilation_units.append(compilation_unit_slither) - parser = SlitherCompilationUnitSolc(compilation_unit_slither) - self._parsers.append(parser) - for path, ast in compilation_unit.asts.items(): - parser.parse_top_level_from_loaded_json(ast, path) - self.add_source_code(path) - _update_file_scopes(compilation_unit_slither.scopes.values()) + if compilation_unit_slither.is_vyper: + vyper_parser = VyperCompilationUnit(compilation_unit_slither) + for path, ast in compilation_unit.asts.items(): + from slither.vyper_parsing.ast.ast import parse + + ast_nodes = parse(ast["ast"]) + vyper_parser.parse_module(ast_nodes, path) + self._parsers.append(vyper_parser) + else: + # Solidity specific + assert compilation_unit_slither.is_solidity + sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) + self._parsers.append(sol_parser) + for path, ast in compilation_unit.asts.items(): + sol_parser.parse_top_level_items(ast, path) + self.add_source_code(path) + + _update_file_scopes(compilation_unit_slither.scopes.values()) if kwargs.get("generate_patches", False): self.generate_patches = True diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 00ac3a519..cc61deb1f 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -75,9 +75,12 @@ class SlitherCompilationUnitSolc(CallerContextExpression): def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: super().__init__() + self._compilation_unit: SlitherCompilationUnit = compilation_unit + self._contracts_by_id: Dict[int, ContractSolc] = {} self._parsed = False self._analyzed = False + self._is_compact_ast = False self._underlying_contract_to_parser: Dict[Contract, ContractSolc] = {} self._structures_top_level_parser: List[StructureTopLevelSolc] = [] @@ -85,11 +88,6 @@ class SlitherCompilationUnitSolc(CallerContextExpression): self._variables_top_level_parser: List[TopLevelVariableSolc] = [] self._functions_top_level_parser: List[FunctionSolc] = [] self._using_for_top_level_parser: List[UsingForTopLevelSolc] = [] - - self._is_compact_ast = False - # self._core: SlitherCore = core - self._compilation_unit = compilation_unit - self._all_functions_and_modifier_parser: List[FunctionSolc] = [] self._top_level_contracts_counter = 0 @@ -145,14 +143,14 @@ class SlitherCompilationUnitSolc(CallerContextExpression): data_loaded = json.loads(json_data) # Truffle AST if "ast" in data_loaded: - self.parse_top_level_from_loaded_json(data_loaded["ast"], data_loaded["sourcePath"]) + self.parse_top_level_items(data_loaded["ast"], data_loaded["sourcePath"]) return True # solc AST, where the non-json text was removed if "attributes" in data_loaded: filename = data_loaded["attributes"]["absolutePath"] else: filename = data_loaded["absolutePath"] - self.parse_top_level_from_loaded_json(data_loaded, filename) + self.parse_top_level_items(data_loaded, filename) return True except ValueError: @@ -163,7 +161,7 @@ class SlitherCompilationUnitSolc(CallerContextExpression): json_data = json_data[first:last] data_loaded = json.loads(json_data) - self.parse_top_level_from_loaded_json(data_loaded, filename) + self.parse_top_level_items(data_loaded, filename) return True return False @@ -197,7 +195,7 @@ class SlitherCompilationUnitSolc(CallerContextExpression): self._compilation_unit.enums_top_level.append(enum) # pylint: disable=too-many-branches,too-many-statements,too-many-locals - def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) -> None: + def parse_top_level_items(self, data_loaded: Dict, filename: str) -> None: if not data_loaded or data_loaded is None: logger.error( "crytic-compile returned an empty AST. " @@ -405,7 +403,7 @@ class SlitherCompilationUnitSolc(CallerContextExpression): def parse_contracts(self) -> None: # pylint: disable=too-many-statements,too-many-branches if not self._underlying_contract_to_parser: logger.info( - f"No contract were found in {self._compilation_unit.core.filename}, check the correct compilation" + f"No contracts were found in {self._compilation_unit.core.filename}, check the correct compilation" ) if self._parsed: raise Exception("Contract analysis can be run only once!") diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 005ad81a4..a99a6af86 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -434,6 +434,7 @@ class ExpressionToSlithIR(ExpressionVisitor): def _post_literal(self, expression: Literal) -> None: expression_type = expression.type assert isinstance(expression_type, ElementaryType) + print(expression.value) cst = Constant(expression.value, expression_type, expression.subdenomination) set_val(expression, cst) diff --git a/slither/vyper_parsing/__init__.py b/slither/vyper_parsing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/ast/__init__.py b/slither/vyper_parsing/ast/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py new file mode 100644 index 000000000..b0a687528 --- /dev/null +++ b/slither/vyper_parsing/ast/ast.py @@ -0,0 +1,373 @@ +from typing import Dict, Callable, List +from slither.vyper_parsing.ast.types import ASTNode +from slither.vyper_parsing.ast.types import * + + +class ParsingError(Exception): + pass + + +def _extract_base_props(raw: Dict) -> Dict: + return { + "src": raw["src"], + "node_id": raw["node_id"], + } + + +def _extract_decl_props(raw: Dict) -> Dict: + return { + "doc_string": parse_doc_str(raw["doc_string"]) if raw["doc_string"] else None, + **_extract_base_props(raw), + } + + +def parse_module(raw: Dict) -> Module: + nodes_parsed: List[ASTNode] = [] + + for node in raw["body"]: + nodes_parsed.append(parse(node)) + + return Module(name=raw["name"], body=nodes_parsed, **_extract_decl_props(raw)) + + +def parse_import_from(raw: Dict) -> ImportFrom: + return ImportFrom( + module=raw["module"], + name=raw["name"], + alias=raw["alias"], + **_extract_base_props(raw), + ) + + +def parse_event_def(raw: Dict) -> EventDef: + body_parsed: List[ASTNode] = [] + for node in raw["body"]: + body_parsed.append(parse(node)) + + return EventDef( + name=raw["name"], + body=body_parsed, + *_extract_base_props(raw), + ) + + +def parse_ann_assign(raw: Dict) -> AnnAssign: + return AnnAssign( + target=parse(raw["target"]), + annotation=parse(raw["annotation"]), + value=parse(raw["value"]) if raw["value"] else None, + **_extract_base_props(raw), + ) + + +def parse_name(raw: Dict) -> Name: + return Name( + id=raw["id"], + **_extract_base_props(raw), + ) + + +def parse_call(raw: Dict) -> Call: + return Call( + func=parse(raw["func"]), + args=[parse(arg) for arg in raw["args"]], + keyword=parse(raw["keyword"]) if raw["keyword"] else None, + keywords=[parse(keyword) for keyword in raw["keywords"]], + **_extract_base_props(raw), + ) + + +def parse_struct_def(raw: Dict) -> StructDef: + body_parsed: List[ASTNode] = [] + for node in raw["body"]: + body_parsed.append(parse(node)) + + return StructDef( + name=raw["name"], + body=body_parsed, + **_extract_base_props(raw), + ) + + +def parse_variable_decl(raw: Dict) -> VariableDecl: + return VariableDecl( + annotation=parse(raw["annotation"]), + value=parse(raw["value"]) if raw["value"] else None, + target=parse(raw["target"]), + is_constant=raw["is_constant"], + is_immutable=raw["is_immutable"], + is_public=raw["is_public"], + **_extract_base_props(raw), + ) + + +def parse_subscript(raw: Dict) -> Subscript: + return Subscript( + value=parse(raw["value"]), + slice=parse(raw["slice"]), + **_extract_base_props(raw), + ) + + +def parse_index(raw: Dict) -> Index: + return Index(value=parse(raw["value"]), **_extract_base_props(raw)) + + +def parse_bytes(raw: Dict) -> Bytes: + return Bytes(value=raw["value"], **_extract_base_props(raw)) + + +def parse_hex(raw: Dict) -> Hex: + return Hex(value=raw["value"], **_extract_base_props(raw)) + + +def parse_int(raw: Dict) -> Int: + return Int(value=raw["value"], **_extract_base_props(raw)) + + +def parse_str(raw: Dict) -> Str: + return Str(value=raw["value"], **_extract_base_props(raw)) + + +def parse_tuple(raw: Dict) -> ASTNode: + return Tuple(elements=[parse(elem) for elem in raw["elements"]], **_extract_base_props(raw)) + + +def parse_function_def(raw: Dict) -> FunctionDef: + body_parsed: List[ASTNode] = [] + for node in raw["body"]: + body_parsed.append(parse(node)) + + decorators_parsed: List[ASTNode] = [] + for node in raw["decorator_list"]: + decorators_parsed.append(parse(node)) + + return FunctionDef( + name=raw["name"], + args=parse_arguments(raw["args"]), + returns=parse(raw["returns"]) if raw["returns"] else None, + body=body_parsed, + pos=raw["pos"], + decorators=decorators_parsed, + **_extract_decl_props(raw), + ) + + +def parse_assign(raw: Dict) -> Assign: + return Assign( + target=parse(raw["target"]), + value=parse(raw["value"]), + **_extract_base_props(raw), + ) + + +def parse_attribute(raw: Dict) -> Attribute: + return Attribute( + value=parse(raw["value"]), + attr=raw["attr"], + **_extract_base_props(raw), + ) + + +def parse_arguments(raw: Dict) -> Arguments: + return Arguments( + args=[parse_arg(arg) for arg in raw["args"]], + default=parse(raw["default"]) if raw["default"] else None, + defaults=[parse(x) for x in raw["defaults"]], + **_extract_base_props(raw), + ) + + +def parse_arg(raw: Dict) -> Arg: + return Arg(arg=raw["arg"], annotation=parse(raw["annotation"]), **_extract_base_props(raw)) + + +def parse_assert(raw: Dict) -> Assert: + return Assert( + test=parse(raw["test"]), + msg=parse(raw["msg"]) if raw["msg"] else None, + **_extract_base_props(raw), + ) + + +def parse_raise(raw: Dict) -> Raise: + return Raise(exc=parse(raw["exc"]) if raw["exc"] else None, **_extract_base_props(raw)) + + +def parse_expr(raw: Dict) -> Expr: + return Expr(value=parse(raw["value"]), **_extract_base_props(raw)) + + +def parse_unary_op(raw: Dict) -> UnaryOp: + return UnaryOp(op=raw["op"], operand=parse(raw["operand"]), **_extract_base_props(raw)) + +binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "-", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>"} + +def parse_bin_op(raw: Dict) -> BinOp: + op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] + return BinOp( + left=parse(raw["left"]), op=op_str, right=parse(raw["right"]), **_extract_base_props(raw) + ) + + +def parse_keyword(raw: Dict) -> Keyword: + return Keyword(arg=raw["arg"], value=parse(raw["value"]), **_extract_base_props(raw)) + + +def parse_log(raw: Dict) -> Log: + return Log(value=parse(raw["value"]), **_extract_base_props(raw)) + + +def parse_return(raw: Dict) -> Return: + return Return(value=parse(raw["value"]) if raw["value"] else None, **_extract_base_props(raw)) + + +def parse_dict(raw: Dict) -> ASTNode: + return VyDict( + keys=[parse(x) for x in raw["keys"]], + values=[parse(x) for x in raw["values"]], + **_extract_base_props(raw), + ) + + +def parse_list(raw: Dict) -> VyList: + return VyList(elements=[parse(x) for x in raw["elements"]], **_extract_base_props(raw)) + + +def parse_name_constant(raw: Dict) -> NameConstant: + return NameConstant(value=raw["value"], **_extract_base_props(raw)) + + +def parse_doc_str(raw: Dict) -> str: + assert isinstance(raw["value"], str) + return raw["value"] + + +def parse_compare(raw: Dict) -> Compare: + return Compare( + left=parse(raw["left"]), op=raw["op"], right=parse(raw["right"]), **_extract_base_props(raw) + ) + + +def parse_if(raw: Dict) -> ASTNode: + return If( + test=parse(raw["test"]), + body=[parse(x) for x in raw["body"]], + orelse=[parse(x) for x in raw["orelse"]], + **_extract_base_props(raw), + ) + + +def parse_for(raw: Dict) -> For: + return For( + target=parse(raw["target"]), + iter=parse(raw["iter"]), + body=[parse(x) for x in raw["body"]], + **_extract_base_props(raw), + ) + + +def parse_break(raw: Dict) -> Break: + return Break(**_extract_base_props(raw)) + + +def parse_continue(raw: Dict) -> Continue: + return Continue(**_extract_base_props(raw)) + + +def parse_pass(raw: Dict) -> Pass: + return Pass( + **_extract_base_props(raw), + ) + + +def parse_interface_def(raw: Dict) -> InterfaceDef: + nodes_parsed: List[ASTNode] = [] + + for node in raw["body"]: + nodes_parsed.append(parse(node)) + return InterfaceDef(name=raw["name"], body=nodes_parsed, **_extract_base_props(raw)) + + +def parse_enum_def(raw: Dict) -> EnumDef: + nodes_parsed: List[ASTNode] = [] + + for node in raw["body"]: + nodes_parsed.append(parse(node)) + + return EnumDef(name=raw["name"], body=nodes_parsed, **_extract_base_props(raw)) + + +def parse_aug_assign(raw: Dict) -> AugAssign: + return AugAssign( + target=parse(raw["target"]), + op=raw["op"], + value=parse(raw["value"]), + **_extract_base_props(raw), + ) + + +def parse_unsupported(raw: Dict) -> ASTNode: + raise ParsingError("unsupported Vyper node", raw["ast_type"], raw.keys(), raw) + + +def parse_bool_op(raw: Dict) -> BoolOp: + return BoolOp( + op=raw["op"], values=[parse(x) for x in raw["values"]], **_extract_base_props(raw) + ) + + +def parse(raw: Dict) -> ASTNode: + try: + return PARSERS.get(raw["ast_type"], parse_unsupported)(raw) + except ParsingError as e: + raise e + except Exception as e: + raise e + # raise ParsingError("failed to parse Vyper node", raw["ast_type"], e, raw.keys(), raw) + + +PARSERS: Dict[str, Callable[[Dict], ASTNode]] = { + "Module": parse_module, + "ImportFrom": parse_import_from, + "EventDef": parse_event_def, + "AnnAssign": parse_ann_assign, + "Name": parse_name, + "Call": parse_call, + "Pass": parse_pass, + "StructDef": parse_struct_def, + "VariableDecl": parse_variable_decl, + "Subscript": parse_subscript, + "Index": parse_index, + "Hex": parse_hex, + "Int": parse_int, + "Str": parse_str, + "DocStr": parse_doc_str, + "Tuple": parse_tuple, + "FunctionDef": parse_function_def, + "Assign": parse_assign, + "Raise": parse_raise, + "Attribute": parse_attribute, + "Assert": parse_assert, + "keyword": parse_keyword, + "arguments": parse_arguments, + "arg": parse_arg, + "UnaryOp": parse_unary_op, + "BinOp": parse_bin_op, + "Expr": parse_expr, + "Log": parse_log, + "Return": parse_return, + "If": parse_if, + "Dict": parse_dict, + "List": parse_list, + "Compare": parse_compare, + "NameConstant": parse_name_constant, + "For": parse_for, + "Break": parse_break, + "Continue": parse_continue, + "InterfaceDef": parse_interface_def, + "EnumDef": parse_enum_def, + "Bytes": parse_bytes, + "AugAssign": parse_aug_assign, + "BoolOp": parse_bool_op, +} diff --git a/slither/vyper_parsing/ast/types.py b/slither/vyper_parsing/ast/types.py new file mode 100644 index 000000000..619df4f14 --- /dev/null +++ b/slither/vyper_parsing/ast/types.py @@ -0,0 +1,270 @@ +from __future__ import annotations +from typing import List, Optional, Dict, Union, ForwardRef +from dataclasses import dataclass + + +@dataclass +class ASTNode: + src: str + node_id: int + + +@dataclass +class Definition(ASTNode): + doc_string: Optional[str] + + +@dataclass +class Module(Definition): + body: List[ASTNode] + name: str + + +@dataclass +class ImportFrom(ASTNode): + module: str + name: str + alias: Optional[str] + + +@dataclass +class EventDef(ASTNode): + name: str + body: List[AnnAssign] + + +@dataclass +class AnnAssign(ASTNode): + target: Name + annotation: Union[Subscript, Name, Call] + value: Optional[ASTNode] + + +@dataclass +class Name(ASTNode): # type or identifier + id: str + + +@dataclass +class Call(ASTNode): + func: ASTNode + args: List[ASTNode] + keyword: Optional[ASTNode] + keywords: List[ASTNode] + + +@dataclass +class Pass(ASTNode): + pass + + +@dataclass +class StructDef(ASTNode): + name: str + body: List[AnnAssign] + + +@dataclass +class VariableDecl(ASTNode): + annotation: ASTNode + target: ASTNode + value: Optional[ASTNode] + is_constant: bool + is_immutable: bool + is_public: bool + + +@dataclass +class Subscript(ASTNode): + value: ASTNode + slice: ASTNode + + +@dataclass +class Index(ASTNode): + value: ASTNode + + +# TODO CONSTANT? + + +@dataclass +class Bytes(ASTNode): + value: bytes + + +@dataclass +class Hex(ASTNode): + value: str + + +@dataclass +class Int(ASTNode): + value: int + + +@dataclass +class Str(ASTNode): + value: str + + +@dataclass +class VyList(ASTNode): + elements: List[ASTNode] + + +@dataclass +class VyDict(ASTNode): + keys: List[ASTNode] + values: List[ASTNode] + + +@dataclass +class Tuple(ASTNode): + elements: List[ASTNode] + + +@dataclass +class FunctionDef(Definition): + name: str + args: Optional[Arguments] + returns: Optional[List[ASTNode]] + body: List[ASTNode] + decorators: Optional[List[ASTNode]] + pos: Optional[any] # not sure what this is + + +@dataclass +class Assign(ASTNode): + target: ASTNode + value: ASTNode + + +@dataclass +class Attribute(ASTNode): + value: ASTNode + attr: str + + +@dataclass +class Arguments(ASTNode): + args: List[Arg] + default: Optional[ASTNode] + defaults: List[ASTNode] + + +@dataclass +class Arg(ASTNode): + arg: str + annotation: Optional[ASTNode] + + +@dataclass +class Assert(ASTNode): + test: ASTNode + msg: Optional[Str] + + +@dataclass +class Raise(ASTNode): + exc: ASTNode + + +from enum import Enum + + +@dataclass +class Expr(ASTNode): + value: ASTNode + + +@dataclass +class UnaryOp(ASTNode): + op: ASTNode + operand: ASTNode + + + + +@dataclass +class BinOp(ASTNode): + left: ASTNode + op: str + right: ASTNode + + +@dataclass +class Keyword(ASTNode): + arg: str + value: ASTNode + + +@dataclass +class Log(ASTNode): + value: ASTNode + + +@dataclass +class Return(ASTNode): + value: Optional[ASTNode] + + +@dataclass +class If(ASTNode): + test: ASTNode + body: List[ASTNode] + orelse: List[ASTNode] + + +@dataclass +class Compare(ASTNode): + left: ASTNode + op: ASTNode + right: ASTNode + + +@dataclass +class NameConstant(ASTNode): + value: bool + + +@dataclass +class For(ASTNode): + target: ASTNode + iter: ASTNode + body: List[ASTNode] + + +@dataclass +class Continue(ASTNode): + pass + + +@dataclass +class Break(ASTNode): + pass + + +@dataclass +class InterfaceDef(ASTNode): + name: str + body: List[ASTNode] + + +@dataclass +class EnumDef(ASTNode): + name: str + body: List[ASTNode] + + +@dataclass +class AugAssign(ASTNode): + target: ASTNode + op: ASTNode + value: ASTNode + + +@dataclass +class BoolOp(ASTNode): + op: ASTNode + values: List[ASTNode] diff --git a/slither/vyper_parsing/cfg/__init__.py b/slither/vyper_parsing/cfg/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/cfg/node.py b/slither/vyper_parsing/cfg/node.py new file mode 100644 index 000000000..cf8a8f160 --- /dev/null +++ b/slither/vyper_parsing/cfg/node.py @@ -0,0 +1,66 @@ +from typing import Union, Optional, Dict, TYPE_CHECKING + +from slither.core.cfg.node import Node +from slither.core.cfg.node import NodeType +from slither.core.expressions.assignment_operation import ( + AssignmentOperation, + AssignmentOperationType, +) +from slither.core.expressions.identifier import Identifier +from slither.vyper_parsing.expressions.expression_parsing import parse_expression +from slither.visitors.expression.find_calls import FindCalls +from slither.visitors.expression.read_var import ReadVar +from slither.visitors.expression.write_var import WriteVar + + +class NodeVyper: + def __init__(self, node: Node) -> None: + self._unparsed_expression: Optional[Dict] = None + self._node = node + + @property + def underlying_node(self) -> Node: + return self._node + + def add_unparsed_expression(self, expression: Dict) -> None: + assert self._unparsed_expression is None + self._unparsed_expression = expression + + def analyze_expressions(self, caller_context) -> None: + if self._node.type == NodeType.VARIABLE and not self._node.expression: + self._node.add_expression(self._node.variable_declaration.expression) + if self._unparsed_expression: + expression = parse_expression(self._unparsed_expression, caller_context) + self._node.add_expression(expression) + # self._unparsed_expression = None + + if self._node.expression: + + if self._node.type == NodeType.VARIABLE: + # Update the expression to be an assignement to the variable + _expression = AssignmentOperation( + Identifier(self._node.variable_declaration), + self._node.expression, + AssignmentOperationType.ASSIGN, + self._node.variable_declaration.type, + ) + # _expression.set_offset( + # self._node.expression.source_mapping, self._node.compilation_unit + # ) + self._node.add_expression(_expression, bypass_verif_empty=True) + + expression = self._node.expression + read_var = ReadVar(expression) + self._node.variables_read_as_expression = read_var.result() + + write_var = WriteVar(expression) + self._node.variables_written_as_expression = write_var.result() + + find_call = FindCalls(expression) + self._node.calls_as_expression = find_call.result() + self._node.external_calls_as_expressions = [ + c for c in self._node.calls_as_expression if not isinstance(c.called, Identifier) + ] + self._node.internal_calls_as_expressions = [ + c for c in self._node.calls_as_expression if isinstance(c.called, Identifier) + ] diff --git a/slither/vyper_parsing/declarations/__init__.py b/slither/vyper_parsing/declarations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py new file mode 100644 index 000000000..3a01a22f7 --- /dev/null +++ b/slither/vyper_parsing/declarations/contract.py @@ -0,0 +1,176 @@ +import logging +from typing import List, TYPE_CHECKING +from slither.vyper_parsing.ast.types import ( + Module, + FunctionDef, + EventDef, + EnumDef, + StructDef, + VariableDecl, + ImportFrom, + InterfaceDef, + AnnAssign, +) + +from slither.vyper_parsing.declarations.event import EventVyper +from slither.vyper_parsing.declarations.struct import StructVyper +from slither.vyper_parsing.variables.state_variable import StateVariableVyper +from slither.vyper_parsing.declarations.function import FunctionVyper +from slither.core.declarations.function_contract import FunctionContract +from slither.core.declarations import Contract, StructureContract, EnumContract, Event + +from slither.core.variables.state_variable import StateVariable + +if TYPE_CHECKING: + from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit + + +class ContractVyper: + def __init__( + self, slither_parser: "VyperCompilationUnit", contract: Contract, module: Module + ) -> None: + + self._contract: Contract = contract + self._slither_parser: "VyperCompilationUnit" = slither_parser + self._data = module + self._contract.name = module.name + self._contract.id = module.node_id + self._is_analyzed: bool = False + + self._enumsNotParsed: List[EnumDef] = [] + self._structuresNotParsed: List[StructDef] = [] + self._variablesNotParsed: List[VariableDecl] = [] + self._eventsNotParsed: List[EventDef] = [] + self._functionsNotParsed: List[FunctionDef] = [] + + self._structures_parser: List[StructVyper] = [] + self._variables_parser: List[StateVariableVyper] = [] + self._events_parser: List[EventVyper] = [] + self._functions_parser: List[FunctionVyper] = [] + + self._parse_contract_items() + + @property + def is_analyzed(self) -> bool: + return self._is_analyzed + + def set_is_analyzed(self, is_analyzed: bool) -> None: + self._is_analyzed = is_analyzed + + @property + def underlying_contract(self) -> Contract: + return self._contract + + def _parse_contract_items(self) -> None: + for node in self._data.body: + if isinstance(node, FunctionDef): + self._functionsNotParsed.append(node) + elif isinstance(node, EventDef): + self._eventsNotParsed.append(node) + elif isinstance(node, VariableDecl): + self._variablesNotParsed.append(node) + elif isinstance(node, EnumDef): + self._enumsNotParsed.append(node) + elif isinstance(node, StructDef): + self._structuresNotParsed.append(node) + elif isinstance(node, ImportFrom): + # https://github.com/vyperlang/vyper/tree/master/vyper/builtins/interfaces + if node.module == "vyper.interfaces": + # TODO add functions + contract = Contract(self._contract.compilation_unit, self._contract.file_scope) + contract.set_offset("-1:-1:-1", self._contract.compilation_unit) + + contract.name = node.name + contract.is_interface = True + self._contract.file_scope.contracts[contract.name] = contract + + elif isinstance(node, InterfaceDef): + contract = Contract(self._contract.compilation_unit, self._contract.file_scope) + contract_parser = ContractVyper(self._slither_parser, contract, node) + contract.set_offset(node.src, self._contract.compilation_unit) + self._contract.file_scope.contracts[contract.name] = contract + self._slither_parser._underlying_contract_to_parser[contract] = contract_parser + + elif isinstance(node, AnnAssign): # implements: ERC20 + pass # TODO + else: + raise ValueError("Unknown contract node: ", node) + + def parse_enums(self) -> None: + for enum in self._enumsNotParsed: + name = enum.name + canonicalName = self._contract.name + "." + enum.name + values = [x.value.id for x in enum.body] + new_enum = EnumContract(name, canonicalName, values) + new_enum.set_contract(self._contract) + new_enum.set_offset(enum.src, self._contract.compilation_unit) + self._contract.enums_as_dict[name] = new_enum # TODO solidity using canonicalName + self._enumsNotParsed = [] + + def parse_structs(self) -> None: + for struct in self._structuresNotParsed: + st = StructureContract(self._contract.compilation_unit) + st.set_contract(self._contract) + st.set_offset(struct.src, self._contract.compilation_unit) + + st_parser = StructVyper(st, struct) + self._contract.structures_as_dict[st.name] = st + self._structures_parser.append(st_parser) + + self._structuresNotParsed = [] + + def parse_state_variables(self) -> None: + for varNotParsed in self._variablesNotParsed: + print(varNotParsed) + var = StateVariable() + var.set_contract(self._contract) + var.set_offset(varNotParsed.src, self._contract.compilation_unit) + + var_parser = StateVariableVyper(var, varNotParsed) + self._variables_parser.append(var_parser) + + assert var.name + self._contract.variables_as_dict[var.name] = var + self._contract.add_variables_ordered([var]) + + self._variablesNotParsed = [] + + def parse_events(self) -> None: + for event_to_parse in self._eventsNotParsed: + event = Event() + event.set_contract(self._contract) + event.set_offset(event_to_parse.src, self._contract.compilation_unit) + + event_parser = EventVyper(event, event_to_parse) + self._events_parser.append(event_parser) + self._contract.events_as_dict[event.full_name] = event + + def parse_functions(self) -> None: + + for function in self._functionsNotParsed: + func = FunctionContract(self._contract.compilation_unit) + func.set_offset(function.src, self._contract.compilation_unit) + func.set_contract(self._contract) + func.set_contract_declarer(self._contract) + + func_parser = FunctionVyper(func, function) + self._contract.add_function(func) + self._functions_parser.append(func_parser) + + self._functionsNotParsed = [] + + def analyze(self) -> None: + for p in self._structures_parser: + p.analyze(self._contract) + for p in self._variables_parser: + p.analyze(self._contract) + for p in self._events_parser: + p.analyze(self._contract) + + for function in self._functions_parser: + function.analyze_params() + for function in self._functions_parser: + function.analyze_content() + + def __hash__(self) -> int: + return self._contract.id diff --git a/slither/vyper_parsing/declarations/event.py b/slither/vyper_parsing/declarations/event.py new file mode 100644 index 000000000..a0152ec0e --- /dev/null +++ b/slither/vyper_parsing/declarations/event.py @@ -0,0 +1,43 @@ +""" + Event module +""" +from typing import TYPE_CHECKING, Dict + +from slither.core.variables.event_variable import EventVariable +from slither.vyper_parsing.variables.event_variable import EventVariableVyper +from slither.core.declarations.event import Event +from slither.vyper_parsing.ast.types import AnnAssign, Pass + + +from slither.vyper_parsing.ast.types import EventDef + + +class EventVyper: + """ + Event class + """ + + def __init__(self, event: Event, event_def: EventDef) -> None: + + self._event = event + self._event.name = event_def.name + self._elemsNotParsed = event_def.body + print(event_def) + # assert False + # self.analyze() # TODO create `VariableDecl` from `AnnAssign` from `event_def.body` (also for `StructDef`) + + def analyze(self, contract) -> None: + for elem_to_parse in self._elemsNotParsed: + if not isinstance(elem_to_parse, AnnAssign): + assert isinstance(elem_to_parse, Pass) + continue + + elem = EventVariable() + + elem.set_offset(elem_to_parse.src, self._event.contract.compilation_unit) + event_parser = EventVariableVyper(elem, elem_to_parse) + event_parser.analyze(contract) + + self._event.elems.append(elem) + + self._elemsNotParsed = [] diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py new file mode 100644 index 000000000..b652efc5f --- /dev/null +++ b/slither/vyper_parsing/declarations/function.py @@ -0,0 +1,340 @@ +import logging +from typing import Dict, Optional, Union, List, TYPE_CHECKING, Tuple, Set + +from slither.core.cfg.node import NodeType, link_nodes, insert_node, Node +from slither.core.cfg.scope import Scope +from slither.core.declarations.contract import Contract +from slither.core.declarations.function import ( + Function, + FunctionType, +) +from slither.core.declarations.function_contract import FunctionContract +from slither.core.expressions import AssignmentOperation +from slither.core.source_mapping.source_mapping import Source +from slither.core.variables.local_variable import LocalVariable +from slither.vyper_parsing.cfg.node import NodeVyper +from slither.solc_parsing.exceptions import ParsingError +from slither.vyper_parsing.variables.local_variable import LocalVariableVyper +from slither.vyper_parsing.ast.types import * + +if TYPE_CHECKING: + from slither.core.compilation_unit import SlitherCompilationUnit + + +def link_underlying_nodes(node1: NodeVyper, node2: NodeVyper): + link_nodes(node1.underlying_node, node2.underlying_node) + + +class FunctionVyper: + def __init__( + self, + function: Function, + function_data: Dict, + ) -> None: + self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} + + self._function = function + print(function_data.name) + print(function_data) + self._function.name = function_data.name + self._function.id = function_data.node_id + + self._local_variables_parser: List = [] + + for decorator in function_data.decorators: + if not hasattr(decorator, "id"): + continue # TODO isinstance Name + if decorator.id in ["external", "public", "internal"]: + self._function.visibility = decorator.id + elif decorator.id == "view": + self._function.view = True + elif decorator.id == "pure": + self._function.pure = True + elif decorator.id == "payable": + self._function.payable = True + else: + raise ValueError(f"Unknown decorator {decorator.id}") + # Interfaces do not have decorators and are external + if self._function._visibility is None: + self._function.visibility = "external" + self._functionNotParsed = function_data + self._params_was_analyzed = False + self._content_was_analyzed = False + + # self._counter_scope_local_variables = 0 + # # variable renamed will map the solc id + # # to the variable. It only works for compact format + # # Later if an expression provides the referencedDeclaration attr + # # we can retrieve the variable + # # It only matters if two variables have the same name in the function + # # which is only possible with solc > 0.5 + # self._variables_renamed: Dict[ + # int, Union[LocalVariableVyper, LocalVariableInitFromTupleSolc] + # ] = {} + + self._analyze_function_type() + + # self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} + # self._node_to_yulobject: Dict[Node, YulBlock] = {} + + # self._local_variables_parser: List[ + # Union[LocalVariableVyper, LocalVariableInitFromTupleSolc] + # ] = [] + + if function_data.doc_string is not None: + function.has_documentation = True + + @property + def underlying_function(self) -> Function: + return self._function + + @property + def compilation_unit(self) -> "SlitherCompilationUnit": + return self._function.compilation_unit + + ################################################################################### + ################################################################################### + # region Variables + ################################################################################### + ################################################################################### + + @property + def variables_renamed( + self, + ) -> Dict[int, LocalVariableVyper]: + return self._variables_renamed + + def _add_local_variable(self, local_var_parser: LocalVariableVyper) -> None: + # If two local variables have the same name + # We add a suffix to the new variable + # This is done to prevent collision during SSA translation + # Use of while in case of collision + # In the worst case, the name will be really long + # TODO no shadowing? + # if local_var_parser.underlying_variable.name: + # known_variables = [v.name for v in self._function.variables] + # while local_var_parser.underlying_variable.name in known_variables: + # local_var_parser.underlying_variable.name += ( + # f"_scope_{self._counter_scope_local_variables}" + # ) + # self._counter_scope_local_variables += 1 + # known_variables = [v.name for v in self._function.variables] + # TODO no reference ID + # if local_var_parser.reference_id is not None: + # self._variables_renamed[local_var_parser.reference_id] = local_var_parser + self._function.variables_as_dict[ + local_var_parser.underlying_variable.name + ] = local_var_parser.underlying_variable + self._local_variables_parser.append(local_var_parser) + + # endregion + ################################################################################### + ################################################################################### + # region Analyses + ################################################################################### + ################################################################################### + + @property + def function_not_parsed(self) -> Dict: + return self._functionNotParsed + + def _analyze_function_type(self) -> None: + if self._function.name == "__init__": + self._function.function_type = FunctionType.CONSTRUCTOR + elif self._function.name == "__default__": + self._function.function_type = FunctionType.FALLBACK + else: + self._function.function_type = FunctionType.NORMAL + + def analyze_params(self) -> None: + if self._params_was_analyzed: + return + + self._params_was_analyzed = True + + params = self._functionNotParsed.args + returns = self._functionNotParsed.returns + + if params: + self._parse_params(params) + if returns: + self._parse_returns(returns) + + def analyze_content(self) -> None: + if self._content_was_analyzed: + return + + self._content_was_analyzed = True + + body = self._functionNotParsed.body + + print(self._functionNotParsed) + if body: + self._function.is_implemented = True + self._parse_cfg(body) + + for local_var_parser in self._local_variables_parser: + local_var_parser.analyze(self._function.contract) + + for node_parser in self._node_to_NodeVyper.values(): + node_parser.analyze_expressions(self._function.contract) + + # endregion + ################################################################################### + ################################################################################### + # region Nodes + ################################################################################### + ################################################################################### + + def _new_node( + self, node_type: NodeType, src: Union[str, Source], scope: Union[Scope, "Function"] + ) -> NodeVyper: + node = self._function.new_node(node_type, src, scope) + node_parser = NodeVyper(node) + self._node_to_NodeVyper[node] = node_parser + return node_parser + + # endregion + ################################################################################### + ################################################################################### + # region Parsing function + ################################################################################### + ################################################################################### + + def _parse_cfg(self, cfg: Dict) -> None: + + + curr_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) + self._function.entry_point = curr_node.underlying_node + scope = None + + if cfg: + self._function.is_empty = False + for expr in cfg: + def parse_statement(curr_node, expr): + if isinstance(expr, AnnAssign): + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + + local_var_parser = LocalVariableVyper(local_var, expr) + self._add_local_variable(local_var_parser) + + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + if expr.value is not None: + new_node.add_unparsed_expression(expr.value) + new_node.underlying_node.add_variable_declaration(local_var) + link_underlying_nodes(curr_node, new_node) + + curr_node = new_node + + elif isinstance(expr, (Assign, AugAssign)): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) + link_underlying_nodes(curr_node, new_node) + + elif isinstance(expr, For): + node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + + node_condition = self._new_node(NodeType.IFLOOP, expr.iter.src, scope) + node_condition.add_unparsed_expression(expr.iter) + # link_underlying_nodes(node_startLoop, node_condition) + for stmt in expr.body: + parse_statement(curr_node, stmt) + + # link_underlying_nodes(curr_node, new_node) + + elif isinstance(expr, Continue): + pass + elif isinstance(expr, Break): + pass + elif isinstance(expr, Return): + node_parser = self._new_node(NodeType.RETURN, expr.src, scope) + if expr.value is not None: + node_parser.add_unparsed_expression(expr.value) + + pass + elif isinstance(expr, Assert): + print(expr) + assert False + pass + elif isinstance(expr, Log): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) + pass + elif isinstance(expr, If): + new_node = self._new_node(NodeType.IF, expr.test.src, scope) + new_node.add_unparsed_expression(expr.test) + + for stmt in expr.body: + parse_statement(new_node, stmt) + + for stmt in expr.orelse: + parse_statement(new_node, stmt) + + pass + elif isinstance(expr, Expr): + pass + elif isinstance(expr, Pass): + pass + elif isinstance(expr, Raise): + print(expr) + assert False + pass + else: + print(f"isinstance(expr, {expr.__class__.__name__})") + assert False + return curr_node + curr_node = parse_statement(curr_node, expr) + # self._parse_block(cfg, node, self.underlying_function) + else: + self._function.is_empty = True + + # endregion + ################################################################################### + ################################################################################### + + def _add_param(self, param: Arg, initialized: bool = False) -> LocalVariableVyper: + + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(param.src, self._function.compilation_unit) + print("add_param", param) + local_var_parser = LocalVariableVyper(local_var, param) + + if initialized: + local_var.initialized = True + + # see https://solidity.readthedocs.io/en/v0.4.24/types.html?highlight=storage%20location#data-location + if local_var.location == "default": + local_var.set_location("memory") + + self._add_local_variable(local_var_parser) + return local_var_parser + + def _parse_params(self, params: Arguments): + + print(params) + self._function.parameters_src().set_offset(params.src, self._function.compilation_unit) + + for param in params.args: + local_var = self._add_param(param) + self._function.add_parameters(local_var.underlying_variable) + + def _parse_returns(self, returns: Union[Name, Tuple, Subscript]): + + print(returns) + self._function.returns_src().set_offset(returns.src, self._function.compilation_unit) + + if isinstance(returns, (Name, Subscript)): + local_var = self._add_param(returns) + self._function.add_return(local_var.underlying_variable) + else: + assert isinstance(returns, Tuple) + for ret in returns.elements: + local_var = self._add_param(ret) + self._function.add_return(local_var.underlying_variable) + + ################################################################################### + ################################################################################### diff --git a/slither/vyper_parsing/declarations/modifier.py b/slither/vyper_parsing/declarations/modifier.py new file mode 100644 index 000000000..c4c5c7177 --- /dev/null +++ b/slither/vyper_parsing/declarations/modifier.py @@ -0,0 +1,107 @@ +""" + Event module +""" +from typing import Dict, TYPE_CHECKING, Union + +from slither.core.cfg.node import NodeType +from slither.core.cfg.node import link_nodes +from slither.core.cfg.scope import Scope +from slither.core.declarations.modifier import Modifier +from slither.solc_parsing.cfg.node import NodeSolc +from slither.solc_parsing.declarations.function import FunctionSolc + +if TYPE_CHECKING: + from slither.solc_parsing.declarations.contract import ContractSolc + from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc + from slither.core.declarations import Function + + +class ModifierSolc(FunctionSolc): + def __init__( + self, + modifier: Modifier, + function_data: Dict, + contract_parser: "ContractSolc", + slither_parser: "SlitherCompilationUnitSolc", + ) -> None: + super().__init__(modifier, function_data, contract_parser, slither_parser) + # _modifier is equal to _function, but keep it here to prevent + # confusion for mypy in underlying_function + self._modifier = modifier + + @property + def underlying_function(self) -> Modifier: + return self._modifier + + def analyze_params(self) -> None: + # Can be re-analyzed due to inheritance + if self._params_was_analyzed: + return + + self._params_was_analyzed = True + + self._analyze_attributes() + + if self.is_compact_ast: + params = self._functionNotParsed["parameters"] + else: + children = self._functionNotParsed["children"] + # It uses to be + # params = children[0] + # But from Solidity 0.6.3 to 0.6.10 (included) + # Comment above a function might be added in the children + params = next(child for child in children if child[self.get_key()] == "ParameterList") + + if params: + self._parse_params(params) + + def analyze_content(self) -> None: + if self._content_was_analyzed: + return + + self._content_was_analyzed = True + + if self.is_compact_ast: + body = self._functionNotParsed.get("body", None) + + if body and body[self.get_key()] == "Block": + self._function.is_implemented = True + self._parse_cfg(body) + + else: + children = self._functionNotParsed["children"] + + self._function.is_implemented = False + if len(children) > 1: + # It uses to be + # params = children[1] + # But from Solidity 0.6.3 to 0.6.10 (included) + # Comment above a function might be added in the children + block = next(child for child in children if child[self.get_key()] == "Block") + self._function.is_implemented = True + self._parse_cfg(block) + + for local_var_parser in self._local_variables_parser: + local_var_parser.analyze(self) + + for node in self._node_to_nodesolc.values(): + node.analyze_expressions(self) + + for yul_parser in self._node_to_yulobject.values(): + yul_parser.analyze_expressions() + + self._rewrite_ternary_as_if_else() + self._remove_alone_endif() + + # self._analyze_read_write() + # self._analyze_calls() + + def _parse_statement( + self, statement: Dict, node: NodeSolc, scope: Union[Scope, "Function"] + ) -> NodeSolc: + name = statement[self.get_key()] + if name == "PlaceholderStatement": + placeholder_node = self._new_node(NodeType.PLACEHOLDER, statement["src"], scope) + link_nodes(node.underlying_node, placeholder_node.underlying_node) + return placeholder_node + return super()._parse_statement(statement, node, scope) diff --git a/slither/vyper_parsing/declarations/struct.py b/slither/vyper_parsing/declarations/struct.py new file mode 100644 index 000000000..0da2c7fed --- /dev/null +++ b/slither/vyper_parsing/declarations/struct.py @@ -0,0 +1,35 @@ +from typing import TYPE_CHECKING, Dict, List + +from slither.core.declarations.structure import Structure +from slither.core.variables.structure_variable import StructureVariable +from slither.vyper_parsing.variables.structure_variable import StructureVariableVyper +from slither.vyper_parsing.ast.types import StructDef, AnnAssign + + +class StructVyper: + def __init__( # pylint: disable=too-many-arguments + self, + st: Structure, + struct: StructDef, + ) -> None: + + print(struct) + + self._structure = st + st.name = struct.name + # st.canonical_name = canonicalName + + self._elemsNotParsed: List[AnnAssign] = struct.body + + def analyze(self, contract) -> None: + for elem_to_parse in self._elemsNotParsed: + elem = StructureVariable() + elem.set_structure(self._structure) + elem.set_offset(elem_to_parse.src, self._structure.contract.compilation_unit) + + elem_parser = StructureVariableVyper(elem, elem_to_parse) + elem_parser.analyze(contract) + + self._structure.elems[elem.name] = elem + self._structure.add_elem_in_order(elem.name) + self._elemsNotParsed = [] diff --git a/slither/vyper_parsing/expressions/__init__.py b/slither/vyper_parsing/expressions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py new file mode 100644 index 000000000..e745c2f7b --- /dev/null +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -0,0 +1,308 @@ +import logging +import re +from typing import Union, Dict, TYPE_CHECKING, List, Any + +import slither.core.expressions.type_conversion +from slither.core.declarations.solidity_variables import ( + SOLIDITY_VARIABLES_COMPOSED, + SolidityVariableComposed, +) +from slither.core.expressions import ( + CallExpression, + ConditionalExpression, + ElementaryTypeNameExpression, + Identifier, + IndexAccess, + Literal, + MemberAccess, + NewArray, + NewContract, + NewElementaryType, + SuperCallExpression, + SuperIdentifier, + TupleExpression, + TypeConversion, + UnaryOperation, + UnaryOperationType, +) +from slither.core.expressions.assignment_operation import ( + AssignmentOperation, + AssignmentOperationType, +) +from slither.core.expressions.binary_operation import ( + BinaryOperation, + BinaryOperationType, +) +from slither.core.solidity_types import ( + ArrayType, + ElementaryType, + UserDefinedType, +) +from slither.solc_parsing.declarations.caller_context import CallerContextExpression +from slither.solc_parsing.exceptions import ParsingError, VariableNotFound +from slither.vyper_parsing.expressions.find_variable import find_variable +from slither.solc_parsing.solidity_types.type_parsing import UnknownType, parse_type + + +if TYPE_CHECKING: + from slither.core.expressions.expression import Expression + +logger = logging.getLogger("ExpressionParsing") + +# pylint: disable=anomalous-backslash-in-string,import-outside-toplevel,too-many-branches,too-many-locals + +# region Filtering +################################################################################### +################################################################################### + + +def filter_name(value: str) -> str: + value = value.replace(" memory", "") + value = value.replace(" storage", "") + value = value.replace(" external", "") + value = value.replace(" internal", "") + value = value.replace("struct ", "") + value = value.replace("contract ", "") + value = value.replace("enum ", "") + value = value.replace(" ref", "") + value = value.replace(" pointer", "") + value = value.replace(" pure", "") + value = value.replace(" view", "") + value = value.replace(" constant", "") + value = value.replace(" payable", "") + value = value.replace("function (", "function(") + value = value.replace("returns (", "returns(") + value = value.replace(" calldata", "") + + # remove the text remaining after functio(...) + # which should only be ..returns(...) + # nested parenthesis so we use a system of counter on parenthesis + idx = value.find("(") + if idx: + counter = 1 + max_idx = len(value) + while counter: + assert idx < max_idx + idx = idx + 1 + if value[idx] == "(": + counter += 1 + elif value[idx] == ")": + counter -= 1 + value = value[: idx + 1] + return value + + +# endregion + +################################################################################### +################################################################################### +# region Parsing +################################################################################### +################################################################################### + +# pylint: disable=too-many-statements +def parse_call( + expression: Dict, caller_context +) -> Union[ + slither.core.expressions.call_expression.CallExpression, + slither.core.expressions.type_conversion.TypeConversion, +]: + src = expression["src"] + if caller_context.is_compact_ast: + attributes = expression + type_conversion = expression["kind"] == "typeConversion" + type_return = attributes["typeDescriptions"]["typeString"] + + else: + attributes = expression["attributes"] + type_conversion = attributes["type_conversion"] + type_return = attributes["type"] + + if type_conversion: + type_call = parse_type(UnknownType(type_return), caller_context) + if caller_context.is_compact_ast: + assert len(expression["arguments"]) == 1 + expression_to_parse = expression["arguments"][0] + else: + children = expression["children"] + assert len(children) == 2 + type_info = children[0] + expression_to_parse = children[1] + assert type_info["name"] in [ + "ElementaryTypenameExpression", + "ElementaryTypeNameExpression", + "Identifier", + "TupleExpression", + "IndexAccess", + "MemberAccess", + ] + + expression = parse_expression(expression_to_parse, caller_context) + t = TypeConversion(expression, type_call) + t.set_offset(src, caller_context.compilation_unit) + if isinstance(type_call, UserDefinedType): + type_call.type.references.append(t.source_mapping) + return t + + call_gas = None + call_value = None + call_salt = None + if caller_context.is_compact_ast: + called = parse_expression(expression["expression"], caller_context) + # If the next expression is a FunctionCallOptions + # We can here the gas/value information + # This is only available if the syntax is {gas: , value: } + # For the .gas().value(), the member are considered as function call + # And converted later to the correct info (convert.py) + if expression["expression"][caller_context.get_key()] == "FunctionCallOptions": + call_with_options = expression["expression"] + for idx, name in enumerate(call_with_options.get("names", [])): + option = parse_expression(call_with_options["options"][idx], caller_context) + if name == "value": + call_value = option + if name == "gas": + call_gas = option + if name == "salt": + call_salt = option + arguments = [] + if expression["arguments"]: + arguments = [parse_expression(a, caller_context) for a in expression["arguments"]] + else: + children = expression["children"] + called = parse_expression(children[0], caller_context) + arguments = [parse_expression(a, caller_context) for a in children[1::]] + + if isinstance(called, SuperCallExpression): + sp = SuperCallExpression(called, arguments, type_return) + sp.set_offset(expression["src"], caller_context.compilation_unit) + return sp + call_expression = CallExpression(called, arguments, type_return) + call_expression.set_offset(src, caller_context.compilation_unit) + + # Only available if the syntax {gas:, value:} was used + call_expression.call_gas = call_gas + call_expression.call_value = call_value + call_expression.call_salt = call_salt + return call_expression + + +def parse_super_name(expression: Dict, is_compact_ast: bool) -> str: + if is_compact_ast: + assert expression["nodeType"] == "MemberAccess" + base_name = expression["memberName"] + arguments = expression["typeDescriptions"]["typeString"] + else: + assert expression["name"] == "MemberAccess" + attributes = expression["attributes"] + base_name = attributes["member_name"] + arguments = attributes["type"] + + assert arguments.startswith("function ") + # remove function (...() + arguments = arguments[len("function ") :] + + arguments = filter_name(arguments) + if " " in arguments: + arguments = arguments[: arguments.find(" ")] + + return base_name + arguments + + +def _parse_elementary_type_name_expression( + expression: Dict, is_compact_ast: bool, caller_context: CallerContextExpression +) -> ElementaryTypeNameExpression: + # nop exression + # uint; + if is_compact_ast: + value = expression["typeName"] + else: + if "children" in expression: + value = expression["children"][0]["attributes"]["name"] + else: + value = expression["attributes"]["value"] + if isinstance(value, dict): + t = parse_type(value, caller_context) + else: + t = parse_type(UnknownType(value), caller_context) + e = ElementaryTypeNameExpression(t) + e.set_offset(expression["src"], caller_context.compilation_unit) + return e + + +if TYPE_CHECKING: + pass + + +def _user_defined_op_call( + caller_context: CallerContextExpression, src, function_id: int, args: List[Any], type_call: str +) -> CallExpression: + var, was_created = find_variable(None, caller_context, function_id) + + if was_created: + var.set_offset(src, caller_context.compilation_unit) + + identifier = Identifier(var) + identifier.set_offset(src, caller_context.compilation_unit) + + var.references.append(identifier.source_mapping) + + call = CallExpression(identifier, args, type_call) + call.set_offset(src, caller_context.compilation_unit) + return call + + +from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str + +def parse_expression(expression: Dict, caller_context) -> "Expression": + print("parse_expression") + print(expression, "\n") + # assert False + + if isinstance(expression, Int): + return Literal(str(expression.value), ElementaryType("uint256")) + + if isinstance(expression, Hex): + # TODO this is an implicit conversion and could potentially be bytes20 or other? + return Literal(str(expression.value), ElementaryType("address")) + + if isinstance(expression, Str): + return Literal(str(expression.value), ElementaryType("string")) + + + + if isinstance(expression, Call): + called = parse_expression(expression.func, caller_context) + arguments = [parse_expression(a, caller_context) for a in expression.args] + # Since the AST lacks the type of the return values, we recover it. + rets = called.value.returns + def get_type_str(x): + return str(x.type) + type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" + print(type_str) + + + return CallExpression(called, arguments, type_str) + + if isinstance(expression, Attribute): + var, was_created = find_variable(expression.attr, caller_context) + assert var + return Identifier(var) + + if isinstance(expression, Name): + var, was_created = find_variable(expression.id, caller_context) + assert var + return Identifier(var) + + if isinstance(expression, Tuple): + tuple_vars = [parse_expression(x, caller_context) for x in expression.elements] + return TupleExpression(tuple_vars) + + if isinstance(expression, BinOp): + lhs = parse_expression(expression.left, caller_context) + rhs = parse_expression(expression.right, caller_context) + + op = BinaryOperationType.get_type(expression.op) + return BinaryOperation(lhs, rhs, op) + + + raise ParsingError(f"Expression not parsed {expression}") diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py new file mode 100644 index 000000000..9037af110 --- /dev/null +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -0,0 +1,240 @@ +from typing import TYPE_CHECKING, Optional, Union, List, Tuple + +from slither.core.declarations import Event, Enum, Structure +from slither.core.declarations.contract import Contract +from slither.core.declarations.custom_error import CustomError +from slither.core.declarations.function import Function +from slither.core.declarations.function_contract import FunctionContract +from slither.core.declarations.function_top_level import FunctionTopLevel +from slither.core.declarations.solidity_import_placeholder import SolidityImportPlaceHolder +from slither.core.declarations.solidity_variables import ( + SOLIDITY_FUNCTIONS, + SOLIDITY_VARIABLES, + SolidityFunction, + SolidityVariable, +) +from slither.core.scope.scope import FileScope +from slither.core.solidity_types import ( + ArrayType, + FunctionType, + MappingType, + TypeAlias, +) +from slither.core.variables.top_level_variable import TopLevelVariable +from slither.core.variables.variable import Variable +from slither.exceptions import SlitherError +from slither.solc_parsing.declarations.caller_context import CallerContextExpression +from slither.solc_parsing.exceptions import VariableNotFound + +if TYPE_CHECKING: + from slither.solc_parsing.declarations.function import FunctionSolc + from slither.solc_parsing.declarations.contract import ContractSolc + +# pylint: disable=import-outside-toplevel,too-many-branches,too-many-locals + + +# CallerContext =Union["ContractSolc", "FunctionSolc", "CustomErrorSolc", "StructureTopLevelSolc"] + + + +def _find_variable_in_function_parser( + var_name: str, + function_parser: Optional["FunctionSolc"], +) -> Optional[Variable]: + if function_parser is None: + return None + func_variables = function_parser.underlying_function.variables_as_dict + if var_name in func_variables: + return func_variables[var_name] + + return None + + + + +def _find_in_contract( + var_name: str, + contract: Optional[Contract], + contract_declarer: Optional[Contract], +) -> Optional[Union[Variable, Function, Contract, Event, Enum, Structure, CustomError]]: + if contract is None or contract_declarer is None: + return None + + # variable are looked from the contract declarer + print(contract) + contract_variables = contract.variables_as_dict + print(contract_variables) + if var_name in contract_variables: + return contract_variables[var_name] + + + + functions = {f.name: f for f in contract.functions if not f.is_shadowed} + print(functions) + if var_name in functions: + return functions[var_name] + + # structures are looked on the contract declarer + structures = contract.structures_as_dict + if var_name in structures: + return structures[var_name] + + events = contract.events_as_dict + if var_name in events: + return events[var_name] + + enums = contract.enums_as_dict + if var_name in enums: + return enums[var_name] + + # Note: contract.custom_errors_as_dict uses the name (not the sol sig) as key + # This is because when the dic is populated the underlying object is not yet parsed + # As a result, we need to iterate over all the custom errors here instead of using the dict + custom_errors = contract.custom_errors + try: + for custom_error in custom_errors: + if var_name in [custom_error.solidity_signature, custom_error.full_name]: + return custom_error + except ValueError: + # This can happen as custom error sol signature might not have been built + # when find_variable was called + # TODO refactor find_variable to prevent this from happening + pass + + # If the enum is refered as its name rather than its canonicalName + enums = {e.name: e for e in contract.enums} + if var_name in enums: + return enums[var_name] + + + return None + + +def _find_variable_init( + caller_context: CallerContextExpression, +) -> Tuple[List[Contract], List["Function"], FileScope,]: + from slither.vyper_parsing.declarations.contract import ContractVyper + from slither.vyper_parsing.declarations.function import FunctionVyper + + + direct_contracts: List[Contract] + direct_functions_parser: List[Function] + scope: FileScope + + if isinstance(caller_context, FileScope): + direct_contracts = [] + direct_functions_parser = [] + scope = caller_context + elif isinstance(caller_context, ContractVyper): + direct_contracts = [caller_context.underlying_contract] + direct_functions_parser = [ + f.underlying_function + for f in caller_context.functions_parser + caller_context.modifiers_parser + ] + scope = caller_context.underlying_contract.file_scope + elif isinstance(caller_context, FunctionVyper): + + direct_contracts = [caller_context.underlying_contract] + direct_functions_parser = [ + f.underlying_function + for f in caller_context.functions_parser + ] + + + scope = contract.file_scope + else: + raise SlitherError( + f"{type(caller_context)} ({caller_context} is not valid for find_variable" + ) + + return direct_contracts, direct_functions_parser, scope + + +def find_variable( + var_name: str, + caller_context: CallerContextExpression, +) -> Tuple[ + Union[ + Variable, + Function, + Contract, + SolidityVariable, + SolidityFunction, + Event, + Enum, + Structure, + CustomError, + TypeAlias, + ], + bool, +]: + """ + Return the variable found and a boolean indicating if the variable was created + If the variable was created, it has no source mapping, and it the caller must add it + + :param var_name: + :type var_name: + :param caller_context: + :type caller_context: + :param referenced_declaration: + :return: + :rtype: + """ + + # variable are looked from the contract declarer + # functions can be shadowed, but are looked from the contract instance, rather than the contract declarer + # the difference between function and variable come from the fact that an internal call, or an variable access + # in a function does not behave similariy, for example in: + # contract C{ + # function f(){ + # state_var = 1 + # f2() + # } + # state_var will refer to C.state_var, no mater if C is inherited + # while f2() will refer to the function definition of the inherited contract (C.f2() in the context of C, or + # the contract inheriting from C) + # for events it's unclear what should be the behavior, as they can be shadowed, but there is not impact + # structure/enums cannot be shadowed + + direct_contracts = [caller_context] + direct_functions = caller_context.functions_declared + print(direct_functions) + current_scope = caller_context.file_scope + + # Only look for reference declaration in the direct contract, see comment at the end + # Reference looked are split between direct and all + # Because functions are copied between contracts, two functions can have the same ref + # So we need to first look with respect to the direct context + + from slither.vyper_parsing.declarations.contract import ContractVyper + from slither.vyper_parsing.declarations.function import FunctionVyper + function_parser: Optional[FunctionSolc] = ( + caller_context if isinstance(caller_context, FunctionVyper) else None + ) + ret1 = _find_variable_in_function_parser(var_name, function_parser) + if ret1: + return ret1, False + + ret = _find_in_contract(var_name, caller_context, caller_context) + if ret: + return ret, False + + # Could refer to any enum + all_enumss = [c.enums_as_dict for c in current_scope.contracts.values()] + all_enums = {k: v for d in all_enumss for k, v in d.items()} + if var_name in all_enums: + return all_enums[var_name], False + + contracts = current_scope.contracts + if var_name in contracts: + return contracts[var_name], False + + if var_name in SOLIDITY_VARIABLES: + return SolidityVariable(var_name), False + + if var_name in SOLIDITY_FUNCTIONS: + return SolidityFunction(var_name), False + + + + raise VariableNotFound(f"Variable not found: {var_name} (context {caller_context})") diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py new file mode 100644 index 000000000..e9a855567 --- /dev/null +++ b/slither/vyper_parsing/type_parsing.py @@ -0,0 +1,55 @@ +from slither.core.solidity_types.elementary_type import ( + ElementaryType, + ElementaryTypeName, +) # TODO rename solidity type +from slither.core.solidity_types.array_type import ArrayType +from slither.vyper_parsing.expressions.expression_parsing import parse_expression +from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple +from typing import Union +from slither.core.solidity_types.user_defined_type import UserDefinedType + + +def parse_type(annotation: Union[Name, Subscript, Call], contract): + assert isinstance(annotation, (Name, Subscript, Call)) + print(annotation) + if isinstance(annotation, Name): + name = annotation.id + elif isinstance(annotation, Subscript): + assert isinstance(annotation.slice, Index) + + # This is also a strange construct... + if isinstance(annotation.slice.value, Tuple): + type_ = parse_type(annotation.slice.value.elements[0], contract) + length = parse_expression(annotation.slice.value.elements[1], contract) + else: + # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression + # so we grab the value + type_ = parse_type(annotation.value, contract) + length = parse_expression(annotation.slice.value, contract) + + # TODO this can also me `HashMaps` + return ArrayType(type_, length) + + elif isinstance(annotation, Call): + return parse_type(annotation.args[0], contract) + + else: + assert False + + lname = name.lower() # todo map String to string + if lname in ElementaryTypeName: + return ElementaryType(lname) + + print(contract.structures_as_dict) + + if name in contract.structures_as_dict: + return UserDefinedType(contract.structures_as_dict[name]) + + print(contract.enums_as_dict) + if name in contract.enums_as_dict: + return UserDefinedType(contract.enums_as_dict[name]) + + print(contract.file_scope.contracts) + if name in contract.file_scope.contracts: + return UserDefinedType(contract.file_scope.contracts[name]) + assert False diff --git a/slither/vyper_parsing/variables/__init__.py b/slither/vyper_parsing/variables/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/vyper_parsing/variables/event_variable.py b/slither/vyper_parsing/variables/event_variable.py new file mode 100644 index 000000000..10b8aa06c --- /dev/null +++ b/slither/vyper_parsing/variables/event_variable.py @@ -0,0 +1,21 @@ +from typing import Dict + +from slither.core.variables.event_variable import EventVariable +from slither.vyper_parsing.type_parsing import parse_type +from slither.vyper_parsing.ast.types import AnnAssign + + +class EventVariableVyper: + def __init__(self, variable: EventVariable, variable_data: AnnAssign): + print(variable_data) + self._variable = variable + self._variable.name = variable_data.target.id + # TODO self._variable.indexed + self._elem_to_parse = variable_data.annotation + + @property + def underlying_variable(self) -> EventVariable: + return self._variable + + def analyze(self, contract) -> None: + self._variable.type = parse_type(self._elem_to_parse, contract) diff --git a/slither/vyper_parsing/variables/function_type_variable.py b/slither/vyper_parsing/variables/function_type_variable.py new file mode 100644 index 000000000..309f4d8b7 --- /dev/null +++ b/slither/vyper_parsing/variables/function_type_variable.py @@ -0,0 +1,13 @@ +from typing import Dict + +from slither.solc_parsing.variables.variable_declaration import VariableDeclarationSolc +from slither.core.variables.function_type_variable import FunctionTypeVariable + + +class FunctionTypeVariableSolc(VariableDeclarationSolc): + def __init__(self, variable: FunctionTypeVariable, variable_data: Dict): + super().__init__(variable, variable_data) + + @property + def underlying_variable(self) -> FunctionTypeVariable: + return self._variable diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py new file mode 100644 index 000000000..45eb55351 --- /dev/null +++ b/slither/vyper_parsing/variables/local_variable.py @@ -0,0 +1,32 @@ +from typing import Union + +from slither.core.variables.local_variable import LocalVariable +from slither.vyper_parsing.ast.types import Arg, Name, AnnAssign, Subscript, Call +from slither.vyper_parsing.type_parsing import parse_type + + +class LocalVariableVyper: + def __init__(self, variable: LocalVariable, variable_data: Union[Arg, Name]) -> None: + self._variable: LocalVariable = variable + + if isinstance(variable_data, (Arg, )): + self._variable.name = variable_data.arg + self._elem_to_parse = variable_data.annotation + elif isinstance(variable_data, (AnnAssign, )): + self._variable.name = variable_data.target.id + self._elem_to_parse = variable_data.annotation + else: + self._variable.name = "" + self._elem_to_parse = variable_data + + assert isinstance(self._elem_to_parse, (Name, Subscript, Call)) + + self._variable.set_location("default") + + + @property + def underlying_variable(self) -> LocalVariable: + return self._variable + + def analyze(self, contract) -> None: + self._variable.type = parse_type(self._elem_to_parse, contract) diff --git a/slither/vyper_parsing/variables/state_variable.py b/slither/vyper_parsing/variables/state_variable.py new file mode 100644 index 000000000..f17a4132e --- /dev/null +++ b/slither/vyper_parsing/variables/state_variable.py @@ -0,0 +1,30 @@ +from typing import Dict + +from slither.core.variables.state_variable import StateVariable +from slither.vyper_parsing.ast.types import VariableDecl +from slither.vyper_parsing.type_parsing import parse_type +from slither.vyper_parsing.expressions.expression_parsing import parse_expression + +class StateVariableVyper: + def __init__(self, variable: StateVariable, variable_data: VariableDecl) -> None: + self._variable: StateVariable = variable + self._variable.name = variable_data.target.id + self._variable.is_constant = variable_data.is_constant + self._variable.is_immutable = variable_data.is_immutable + self._variable.visibility = "public" if variable_data.is_public else "internal" + self._elem_to_parse = variable_data.annotation + + if variable_data.value is not None: + self._variable.initialized = True + self._initializedNotParsed = variable_data.value + + @property + def underlying_variable(self) -> StateVariable: + return self._variable + + def analyze(self, contract) -> None: + self._variable.type = parse_type(self._elem_to_parse, contract) + + if self._variable.initialized: + self._variable.expression = parse_expression(self._initializedNotParsed, contract) + self._initializedNotParsed = None diff --git a/slither/vyper_parsing/variables/structure_variable.py b/slither/vyper_parsing/variables/structure_variable.py new file mode 100644 index 000000000..eab7a71c4 --- /dev/null +++ b/slither/vyper_parsing/variables/structure_variable.py @@ -0,0 +1,20 @@ +from typing import Dict + + +from slither.core.variables.structure_variable import StructureVariable +from slither.vyper_parsing.type_parsing import parse_type +from slither.vyper_parsing.ast.types import AnnAssign + + +class StructureVariableVyper: + def __init__(self, variable: StructureVariable, variable_data: AnnAssign): + self._variable: StructureVariable = variable + self._variable.name = variable_data.target.id + self._elem_to_parse = variable_data.annotation + + @property + def underlying_variable(self) -> StructureVariable: + return self._variable + + def analyze(self, contract) -> None: + self._variable.type = parse_type(self._elem_to_parse, contract) diff --git a/slither/vyper_parsing/variables/variable_declaration.py b/slither/vyper_parsing/variables/variable_declaration.py new file mode 100644 index 000000000..64878163c --- /dev/null +++ b/slither/vyper_parsing/variables/variable_declaration.py @@ -0,0 +1,150 @@ +import logging +import re +from typing import Dict, Optional, Union + + +from slither.core.variables.variable import Variable +from slither.core.solidity_types.elementary_type import ( + ElementaryType, + NonElementaryType, +) +from slither.solc_parsing.exceptions import ParsingError + +from slither.vyper_parsing.ast.types import VariableDecl, Name, Subscript, ASTNode, Call, Arg +from slither.vyper_parsing.type_parsing import parse_type + + +class VariableDeclarationVyper: + # pylint: disable=too-many-branches + def __init__(self, variable: Variable, variable_data: VariableDecl) -> None: + """ + A variable can be declared through a statement, or directly. + If it is through a statement, the following children may contain + the init value. + It may be possible that the variable is declared through a statement, + but the init value is declared at the VariableDeclaration children level + """ + + self._variable = variable + if isinstance(variable_data, Arg): + self._variable.name = variable_data.arg + else: + self._variable.name = variable_data.target.id + self._was_analyzed: bool = False + self._initializedNotParsed: Optional[ASTNode] = None + + if isinstance(variable_data.annotation, Subscript): + self._elem_to_parse = variable_data.annotation.value.id + elif isinstance(variable_data.annotation, Name): + self._elem_to_parse = variable_data.annotation.id + else: # Event defs with indexed args + assert isinstance(variable_data.annotation, Call) + self._elem_to_parse = variable_data.annotation.args[0].id + self._init_from_declaration(variable_data) + # self._elem_to_parse: Optional[Union[Dict, UnknownType]] = None + # self._initializedNotParsed: Optional[Dict] = None + + # self._is_compact_ast = False + + # self._reference_id: Optional[int] = None + + @property + def underlying_variable(self) -> Variable: + return self._variable + + def _init_from_declaration(self, var: VariableDecl): + # Only state variables + + pass + + # self._handle_comment(attributes) + # Args do not have intial value + # print(var.value) + # assert var.value is None + # def _init_from_declaration( + # self, var: Dict, init: Optional[Dict] + # ) -> None: # pylint: disable=too-many-branches + # if self._is_compact_ast: + # attributes = var + # self._typeName = attributes["typeDescriptions"]["typeString"] + # else: + # assert len(var["children"]) <= 2 + # assert var["name"] == "VariableDeclaration" + + # attributes = var["attributes"] + # self._typeName = attributes["type"] + + # self._variable.name = attributes["name"] + # # self._arrayDepth = 0 + # # self._isMapping = False + # # self._mappingFrom = None + # # self._mappingTo = False + # # self._initial_expression = None + # # self._type = None + + # # Only for comapct ast format + # # the id can be used later if referencedDeclaration + # # is provided + # if "id" in var: + # self._reference_id = var["id"] + + # if "constant" in attributes: + # self._variable.is_constant = attributes["constant"] + + # if "mutability" in attributes: + # # Note: this checked is not needed if "constant" was already in attribute, but we keep it + # # for completion + # if attributes["mutability"] == "constant": + # self._variable.is_constant = True + # if attributes["mutability"] == "immutable": + # self._variable.is_immutable = True + + # self._analyze_variable_attributes(attributes) + + # if self._is_compact_ast: + # if var["typeName"]: + # self._elem_to_parse = var["typeName"] + # else: + # self._elem_to_parse = UnknownType(var["typeDescriptions"]["typeString"]) + # else: + # if not var["children"]: + # # It happens on variable declared inside loop declaration + # try: + # self._variable.type = ElementaryType(self._typeName) + # self._elem_to_parse = None + # except NonElementaryType: + # self._elem_to_parse = UnknownType(self._typeName) + # else: + # self._elem_to_parse = var["children"][0] + + # if self._is_compact_ast: + # self._initializedNotParsed = init + # if init: + # self._variable.initialized = True + # else: + # if init: # there are two way to init a var local in the AST + # assert len(var["children"]) <= 1 + # self._variable.initialized = True + # self._initializedNotParsed = init + # elif len(var["children"]) in [0, 1]: + # self._variable.initialized = False + # self._initializedNotParsed = None + # else: + # assert len(var["children"]) == 2 + # self._variable.initialized = True + # self._initializedNotParsed = var["children"][1] + + def analyze(self) -> None: + if self._was_analyzed: + return + self._was_analyzed = True + + if self._elem_to_parse is not None: + print(self._elem_to_parse) + # assert False + self._variable.type = parse_type(self._elem_to_parse) + self._elem_to_parse = None + + # if self._variable.initialized is not None: + # self._variable.expression = parse_expression(self._initializedNotParsed) + # self._initializedNotParsed = None diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py new file mode 100644 index 000000000..78cb83748 --- /dev/null +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -0,0 +1,94 @@ +from typing import Dict +from dataclasses import dataclass, field +from slither.core.declarations import Contract +from slither.core.compilation_unit import SlitherCompilationUnit +from slither.vyper_parsing.declarations.contract import ContractVyper +from slither.analyses.data_dependency.data_dependency import compute_dependency +from slither.vyper_parsing.declarations.struct import Structure +from slither.core.variables.state_variable import StateVariable + +from slither.exceptions import SlitherException + + +@dataclass +class VyperCompilationUnit: + _compilation_unit: SlitherCompilationUnit + _parsed: bool = False + _analyzed: bool = False + _underlying_contract_to_parser: Dict[Contract, ContractVyper] = field(default_factory=dict) + _contracts_by_id: Dict[int, Contract] = field(default_factory=dict) + + def parse_module(self, data: Dict, filename: str): + scope = self._compilation_unit.get_scope(filename) + contract = Contract(self._compilation_unit, scope) + contract_parser = ContractVyper(self, contract, data) + contract.set_offset(data.src, self._compilation_unit) + + self._underlying_contract_to_parser[contract] = contract_parser + + def parse_contracts(self): + for contract, contract_parser in self._underlying_contract_to_parser.items(): + self._contracts_by_id[contract.id] = contract + self._compilation_unit.contracts.append(contract) + + contract_parser.parse_enums() + contract_parser.parse_structs() + contract_parser.parse_state_variables() + contract_parser.parse_events() + contract_parser.parse_functions() + + self._parsed = True + + def analyze_contracts(self) -> None: + if not self._parsed: + raise SlitherException("Parse the contract before running analyses") + for contract, contract_parser in self._underlying_contract_to_parser.items(): + contract_parser.analyze() + self._convert_to_slithir() + + compute_dependency(self._compilation_unit) + + self._analyzed = True + + def _convert_to_slithir(self) -> None: + + for contract in self._compilation_unit.contracts: + contract.add_constructor_variables() + for func in contract.functions: + func.generate_slithir_and_analyze() + + # def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: + + # self._contracts_by_id: Dict[int, ContractSolc] = {} + # self._parsed = False + # self._analyzed = False + + # self._underlying_contract_to_parser: Dict[Contract, ContractSolc] = {} + # self._structures_top_level_parser: List[StructureTopLevelSolc] = [] + # self._custom_error_parser: List[CustomErrorSolc] = [] + # self._variables_top_level_parser: List[TopLevelVariableSolc] = [] + # self._functions_top_level_parser: List[FunctionSolc] = [] + # self._using_for_top_level_parser: List[UsingForTopLevelSolc] = [] + + # self._all_functions_and_modifier_parser: List[FunctionSolc] = [] + + # self._top_level_contracts_counter = 0 + + # @property + # def compilation_unit(self) -> SlitherCompilationUnit: + # return self._compilation_unit + + # @property + # def all_functions_and_modifiers_parser(self) -> List[FunctionSolc]: + # return self._all_functions_and_modifier_parser + + # def add_function_or_modifier_parser(self, f: FunctionSolc) -> None: + # self._all_functions_and_modifier_parser.append(f) + + # @property + # def underlying_contract_to_parser(self) -> Dict[Contract, ContractSolc]: + # return self._underlying_contract_to_parser + + # @property + # def slither_parser(self) -> "SlitherCompilationUnitSolc": + # return self From b264512509fef6f614b373fe98744cb4d4ee8bb0 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 18 Aug 2023 15:20:22 -0500 Subject: [PATCH 161/338] improve parse_types --- slither/vyper_parsing/ast/ast.py | 22 ++++++------ .../vyper_parsing/declarations/contract.py | 20 +++++++---- .../vyper_parsing/declarations/function.py | 9 ++--- .../expressions/expression_parsing.py | 27 ++++++++++++--- .../expressions/find_variable.py | 8 ++++- slither/vyper_parsing/type_parsing.py | 34 ++++++++++++++----- 6 files changed, 86 insertions(+), 34 deletions(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index b0a687528..1ea4f3410 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -197,16 +197,24 @@ def parse_raise(raw: Dict) -> Raise: def parse_expr(raw: Dict) -> Expr: return Expr(value=parse(raw["value"]), **_extract_base_props(raw)) +unop_ast_type_to_op_symbol = {"Not": "!", "USub": "-"} def parse_unary_op(raw: Dict) -> UnaryOp: - return UnaryOp(op=raw["op"], operand=parse(raw["operand"]), **_extract_base_props(raw)) + unop_str = unop_ast_type_to_op_symbol[raw["op"]["ast_type"]] + return UnaryOp(op=unop_str, operand=parse(raw["operand"]), **_extract_base_props(raw)) -binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "-", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>"} +binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "-", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>", "NotEq": "!=", "Eq": "==", "LtE": "<=", "GtE": ">=", "Lt": "<", "Gt": ">", "In": "In", "NotIn": "NotIn"} def parse_bin_op(raw: Dict) -> BinOp: - op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] + arith_op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] return BinOp( - left=parse(raw["left"]), op=op_str, right=parse(raw["right"]), **_extract_base_props(raw) + left=parse(raw["left"]), op=arith_op_str, right=parse(raw["right"]), **_extract_base_props(raw) + ) + +def parse_compare(raw: Dict) -> Compare: + logical_op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] + return Compare( + left=parse(raw["left"]), op=logical_op_str, right=parse(raw["right"]), **_extract_base_props(raw) ) @@ -243,12 +251,6 @@ def parse_doc_str(raw: Dict) -> str: return raw["value"] -def parse_compare(raw: Dict) -> Compare: - return Compare( - left=parse(raw["left"]), op=raw["op"], right=parse(raw["right"]), **_extract_base_props(raw) - ) - - def parse_if(raw: Dict) -> ASTNode: return If( test=parse(raw["test"]), diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 3a01a22f7..d95ae6855 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -85,6 +85,7 @@ class ContractVyper: self._contract.file_scope.contracts[contract.name] = contract elif isinstance(node, InterfaceDef): + # TODO This needs to be done lazily as interfaces can refer to constant state variables contract = Contract(self._contract.compilation_unit, self._contract.file_scope) contract_parser = ContractVyper(self._slither_parser, contract, node) contract.set_offset(node.src, self._contract.compilation_unit) @@ -132,6 +133,8 @@ class ContractVyper: assert var.name self._contract.variables_as_dict[var.name] = var self._contract.add_variables_ordered([var]) + # Interfaces can refer to constants + self._contract.file_scope.variables[var.name] = var self._variablesNotParsed = [] @@ -160,15 +163,20 @@ class ContractVyper: self._functionsNotParsed = [] def analyze(self) -> None: - for p in self._structures_parser: - p.analyze(self._contract) - for p in self._variables_parser: - p.analyze(self._contract) - for p in self._events_parser: - p.analyze(self._contract) + print("Analyze", self._contract._name) + # Struct defs can refer to constant state variables + for var_parser in self._variables_parser: + var_parser.analyze(self._contract) + + for struct_parser in self._structures_parser: + struct_parser.analyze(self._contract) + + for event_parser in self._events_parser: + event_parser.analyze(self._contract) for function in self._functions_parser: function.analyze_params() + for function in self._functions_parser: function.analyze_content() diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index b652efc5f..7960e2ed8 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -168,7 +168,6 @@ class FunctionVyper: body = self._functionNotParsed.body - print(self._functionNotParsed) if body: self._function.is_implemented = True self._parse_cfg(body) @@ -256,9 +255,11 @@ class FunctionVyper: pass elif isinstance(expr, Assert): - print(expr) - assert False - pass + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) + + + elif isinstance(expr, Log): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) new_node.add_unparsed_expression(expr.value) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index e745c2f7b..b874ddb1f 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -7,6 +7,7 @@ from slither.core.declarations.solidity_variables import ( SOLIDITY_VARIABLES_COMPOSED, SolidityVariableComposed, ) +from slither.core.declarations import SolidityFunction from slither.core.expressions import ( CallExpression, ConditionalExpression, @@ -251,7 +252,7 @@ def _user_defined_op_call( return call -from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str +from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str, Assert, Compare, UnaryOp def parse_expression(expression: Dict, caller_context) -> "Expression": print("parse_expression") @@ -275,11 +276,11 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": arguments = [parse_expression(a, caller_context) for a in expression.args] # Since the AST lacks the type of the return values, we recover it. rets = called.value.returns + def get_type_str(x): return str(x.type) + type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" - print(type_str) - return CallExpression(called, arguments, type_str) @@ -290,6 +291,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Name): var, was_created = find_variable(expression.id, caller_context) + print(var) + print(var.__class__) assert var return Identifier(var) @@ -297,12 +300,28 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": tuple_vars = [parse_expression(x, caller_context) for x in expression.elements] return TupleExpression(tuple_vars) - if isinstance(expression, BinOp): + if isinstance(expression, UnaryOp): + operand = parse_expression(expression.operand, caller_context) + op = UnaryOperationType.get_type(expression.op, isprefix=True) #TODO does vyper have postfix? + + return UnaryOperation(operand, op) + + if isinstance(expression, (BinOp, Compare)): lhs = parse_expression(expression.left, caller_context) rhs = parse_expression(expression.right, caller_context) op = BinaryOperationType.get_type(expression.op) return BinaryOperation(lhs, rhs, op) + if isinstance(expression, Assert): + type_str = "tuple()" + if expression.msg is None: + func = SolidityFunction("require(bool)") + args = [parse_expression(expression.test, caller_context)] + else: + func = SolidityFunction("require(bool,string)") + args = [parse_expression(expression.test, caller_context), parse_expression(expression.msg, caller_context)] + return CallExpression(Identifier(func), args, type_str) + raise ParsingError(f"Expression not parsed {expression}") diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 9037af110..4e0564a42 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -44,6 +44,7 @@ def _find_variable_in_function_parser( if function_parser is None: return None func_variables = function_parser.underlying_function.variables_as_dict + print("func_variables", func_variables) if var_name in func_variables: return func_variables[var_name] @@ -208,9 +209,10 @@ def find_variable( from slither.vyper_parsing.declarations.contract import ContractVyper from slither.vyper_parsing.declarations.function import FunctionVyper - function_parser: Optional[FunctionSolc] = ( + function_parser: Optional[FunctionVyper] = ( caller_context if isinstance(caller_context, FunctionVyper) else None ) + print("function_parser", function_parser) ret1 = _find_variable_in_function_parser(var_name, function_parser) if ret1: return ret1, False @@ -219,6 +221,10 @@ def find_variable( if ret: return ret, False + print(current_scope.variables) + if var_name in current_scope.variables: + return current_scope.variables[var_name], False + # Could refer to any enum all_enumss = [c.enums_as_dict for c in current_scope.contracts.values()] all_enums = {k: v for d in all_enumss for k, v in d.items()} diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index e9a855567..49cfd6b2d 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -3,6 +3,8 @@ from slither.core.solidity_types.elementary_type import ( ElementaryTypeName, ) # TODO rename solidity type from slither.core.solidity_types.array_type import ArrayType +from slither.core.solidity_types.mapping_type import MappingType + from slither.vyper_parsing.expressions.expression_parsing import parse_expression from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple from typing import Union @@ -16,19 +18,33 @@ def parse_type(annotation: Union[Name, Subscript, Call], contract): name = annotation.id elif isinstance(annotation, Subscript): assert isinstance(annotation.slice, Index) - # This is also a strange construct... if isinstance(annotation.slice.value, Tuple): - type_ = parse_type(annotation.slice.value.elements[0], contract) - length = parse_expression(annotation.slice.value.elements[1], contract) - else: - # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression - # so we grab the value - type_ = parse_type(annotation.value, contract) - length = parse_expression(annotation.slice.value, contract) + assert isinstance(annotation.value, Name) + if annotation.value.id == "DynArray": + type_ = parse_type(annotation.slice.value.elements[0], contract) + length = parse_expression(annotation.slice.value.elements[1], contract) + return ArrayType(type_, length) + else: + assert annotation.value.id == "HashMap" + type_from = parse_type(annotation.slice.value.elements[0], contract) + type_to = parse_type(annotation.slice.value.elements[1], contract) - # TODO this can also me `HashMaps` + return MappingType(type_from, type_to) + + elif isinstance(annotation.value, Subscript): + type_ = parse_type(annotation.value, contract) + + elif isinstance(annotation.value, Name): + # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression, so we grab the value. + # Subscript(src='13:10:0', node_id=7, value=Name(src='13:6:0', node_id=8, id='String'), slice=Index(src='13:10:0', node_id=12, value=Int(src='20:2:0', node_id=10, value=64))) + type_ = parse_type(annotation.value, contract) + if annotation.value.id == "String": + return type_ + + length = parse_expression(annotation.slice.value, contract) return ArrayType(type_, length) + elif isinstance(annotation, Call): return parse_type(annotation.args[0], contract) From 90dc42fafe8a5d03d60f33236fd93b037f165117 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sat, 19 Aug 2023 19:38:41 -0500 Subject: [PATCH 162/338] fix interface referring to constants, plus comments --- slither/vyper_parsing/ast/ast.py | 2 ++ slither/vyper_parsing/declarations/contract.py | 12 +++++++++--- .../vyper_parsing/expressions/expression_parsing.py | 2 ++ slither/vyper_parsing/vyper_compilation_unit.py | 7 +++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index 1ea4f3410..2c2470c74 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -197,12 +197,14 @@ def parse_raise(raw: Dict) -> Raise: def parse_expr(raw: Dict) -> Expr: return Expr(value=parse(raw["value"]), **_extract_base_props(raw)) +# This is done for convenience so we can call `UnaryOperationType.get_type` during expression parsing. unop_ast_type_to_op_symbol = {"Not": "!", "USub": "-"} def parse_unary_op(raw: Dict) -> UnaryOp: unop_str = unop_ast_type_to_op_symbol[raw["op"]["ast_type"]] return UnaryOp(op=unop_str, operand=parse(raw["operand"]), **_extract_base_props(raw)) +# This is done for convenience so we can call `BinaryOperationType.get_type` during expression parsing. binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "-", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>", "NotEq": "!=", "Eq": "==", "LtE": "<=", "GtE": ">=", "Lt": "<", "Gt": ">", "In": "In", "NotIn": "NotIn"} def parse_bin_op(raw: Dict) -> BinOp: diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index d95ae6855..d252c5bce 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -87,8 +87,10 @@ class ContractVyper: elif isinstance(node, InterfaceDef): # TODO This needs to be done lazily as interfaces can refer to constant state variables contract = Contract(self._contract.compilation_unit, self._contract.file_scope) - contract_parser = ContractVyper(self._slither_parser, contract, node) contract.set_offset(node.src, self._contract.compilation_unit) + contract.is_interface = True + + contract_parser = ContractVyper(self._slither_parser, contract, node) self._contract.file_scope.contracts[contract.name] = contract self._slither_parser._underlying_contract_to_parser[contract] = contract_parser @@ -162,12 +164,16 @@ class ContractVyper: self._functionsNotParsed = [] - def analyze(self) -> None: - print("Analyze", self._contract._name) + + def analyze_state_variables(self): # Struct defs can refer to constant state variables for var_parser in self._variables_parser: var_parser.analyze(self._contract) + + def analyze(self) -> None: + print("Analyze", self._contract._name) + for struct_parser in self._structures_parser: struct_parser.analyze(self._contract) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index b874ddb1f..220e15520 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -314,6 +314,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return BinaryOperation(lhs, rhs, op) if isinstance(expression, Assert): + # Treat assert the same as a Solidity `require`. + # TODO rename from `SolidityFunction` to `Builtin`? type_str = "tuple()" if expression.msg is None: func = SolidityFunction("require(bool)") diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index 78cb83748..0a3bb7d3e 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -42,8 +42,15 @@ class VyperCompilationUnit: def analyze_contracts(self) -> None: if not self._parsed: raise SlitherException("Parse the contract before running analyses") + + for contract, contract_parser in self._underlying_contract_to_parser.items(): + # State variables are analyzed for all contracts because interfaces may + # reference them, specifically, constants. + contract_parser.analyze_state_variables() + for contract, contract_parser in self._underlying_contract_to_parser.items(): contract_parser.analyze() + self._convert_to_slithir() compute_dependency(self._compilation_unit) From b142d236d731f02204198b1fbbf3c6b33a77ef86 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 22 Aug 2023 16:10:53 -0500 Subject: [PATCH 163/338] check in progress on comparison operators and builtins --- .../core/declarations/solidity_variables.py | 17 ++ .../vyper_parsing/declarations/function.py | 18 +- .../expressions/expression_parsing.py | 162 ++++++++++++++++-- .../expressions/find_variable.py | 50 ++++-- slither/vyper_parsing/type_parsing.py | 29 ++-- 5 files changed, 225 insertions(+), 51 deletions(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index f6a0f0839..76c28552e 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -10,6 +10,7 @@ from slither.exceptions import SlitherException SOLIDITY_VARIABLES = { "now": "uint256", "this": "address", + "self": "address", "abi": "address", # to simplify the conversion, assume that abi return an address "msg": "", "tx": "", @@ -81,6 +82,22 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "balance(address)": ["uint256"], "code(address)": ["bytes"], "codehash(address)": ["bytes32"], + # Vyper + "create_from_blueprint()":[], + "empty()":[], + "convert()":[], # TODO make type conversion + "len()":[], + "method_id()":[], + "unsafe_sub()": [], + "unsafe_add()": [], + "unsafe_div()":[], + "unsafe_mul()":[], + "pow_mod256()":[], + "max_value()":[], + "min_value()":[], + "concat()":[], + "ecrecover()":[], + "isqrt()":[] } diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 7960e2ed8..cf50fd41a 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -173,10 +173,10 @@ class FunctionVyper: self._parse_cfg(body) for local_var_parser in self._local_variables_parser: - local_var_parser.analyze(self._function.contract) + local_var_parser.analyze(self._function) for node_parser in self._node_to_NodeVyper.values(): - node_parser.analyze_expressions(self._function.contract) + node_parser.analyze_expressions(self._function) # endregion ################################################################################### @@ -205,7 +205,7 @@ class FunctionVyper: curr_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) self._function.entry_point = curr_node.underlying_node - scope = None + scope = Scope(True, False, self.underlying_function) if cfg: self._function.is_empty = False @@ -227,11 +227,17 @@ class FunctionVyper: curr_node = new_node - elif isinstance(expr, (Assign, AugAssign)): + elif isinstance(expr, (AugAssign, Assign)): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr.value) + new_node.add_unparsed_expression(expr) link_underlying_nodes(curr_node, new_node) + # elif isinstance(expr, Assign): + # new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + # new_node.add_unparsed_expression(expr.target) + # new_node.add_unparsed_expression(expr.value) + # link_underlying_nodes(curr_node, new_node) + elif isinstance(expr, For): node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) @@ -281,7 +287,7 @@ class FunctionVyper: pass elif isinstance(expr, Raise): print(expr) - assert False + # assert False pass else: print(f"isinstance(expr, {expr.__class__.__name__})") diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 220e15520..ee6e1c9d1 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -7,7 +7,7 @@ from slither.core.declarations.solidity_variables import ( SOLIDITY_VARIABLES_COMPOSED, SolidityVariableComposed, ) -from slither.core.declarations import SolidityFunction +from slither.core.declarations import SolidityFunction, Function from slither.core.expressions import ( CallExpression, ConditionalExpression, @@ -39,10 +39,11 @@ from slither.core.solidity_types import ( ElementaryType, UserDefinedType, ) +from slither.core.declarations.contract import Contract from slither.solc_parsing.declarations.caller_context import CallerContextExpression from slither.solc_parsing.exceptions import ParsingError, VariableNotFound from slither.vyper_parsing.expressions.find_variable import find_variable -from slither.solc_parsing.solidity_types.type_parsing import UnknownType, parse_type +from slither.vyper_parsing.type_parsing import parse_type if TYPE_CHECKING: @@ -252,7 +253,8 @@ def _user_defined_op_call( return call -from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str, Assert, Compare, UnaryOp +from collections import deque +from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str, Assert, Compare, UnaryOp, Subscript, NameConstant, VyDict, Bytes, BoolOp, Assign, AugAssign, VyList def parse_expression(expression: Dict, caller_context) -> "Expression": print("parse_expression") @@ -268,34 +270,111 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Str): return Literal(str(expression.value), ElementaryType("string")) + + if isinstance(expression, Bytes): + return Literal(str(expression.value), ElementaryType("bytes")) - + if isinstance(expression, NameConstant): + assert str(expression.value) in ["True", "False"] + return Literal(str(expression.value), ElementaryType("bool")) if isinstance(expression, Call): called = parse_expression(expression.func, caller_context) - arguments = [parse_expression(a, caller_context) for a in expression.args] - # Since the AST lacks the type of the return values, we recover it. - rets = called.value.returns + + if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): + if called.value.name == "convert()": + arg = parse_expression(expression.args[0], caller_context) + type_to = parse_type(expression.args[1], caller_context) + return TypeConversion(arg, type_to) + elif called.value.name== "min_value()": + type_to = parse_type(expression.args[0], caller_context) + member_type = str(type_to) + # TODO return Literal + return MemberAccess("min", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + elif called.value.name== "max_value()": + type_to = parse_type(expression.args[0], caller_context) + member_type = str(type_to) + x = MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + print(x) + return x + + + if expression.args and isinstance(expression.args[0], VyDict): + arguments = [] + for val in expression.args[0].values: + arguments.append(parse_expression(val, caller_context)) + else: + arguments = [parse_expression(a, caller_context) for a in expression.args] + + if isinstance(called, Identifier): + # Since the AST lacks the type of the return values, we recover it. + if isinstance(called.value, Function): + rets = called.value.returns + elif isinstance(called.value, SolidityFunction): + rets = called.value.return_type + elif isinstance(called.value, Contract): + # Type conversions are not explicitly represented in the AST e.g. converting address to contract/ interface, + # so we infer that a type conversion is occurring if `called` is a `Contract` type. + type_to = parse_type(expression.func, caller_context) + return TypeConversion(arguments[0], type_to) + + else: + rets = ["tuple()"] + + else: + rets = ["tuple()"] def get_type_str(x): + if isinstance(x, str): + return x return str(x.type) - + type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" return CallExpression(called, arguments, type_str) if isinstance(expression, Attribute): - var, was_created = find_variable(expression.attr, caller_context) - assert var - return Identifier(var) - + member_name = expression.attr + if isinstance(expression.value, Name): + + if expression.value.id == "self": + var, was_created = find_variable(member_name, caller_context) + # TODO replace with self + return SuperIdentifier(var) + + expr = parse_expression(expression.value, caller_context) + member_access = MemberAccess(member_name, None, expr) + # member_access.set_offset(src, caller_context.compilation_unit) + if str(member_access) in SOLIDITY_VARIABLES_COMPOSED: + id_idx = Identifier(SolidityVariableComposed(str(member_access))) + # id_idx.set_offset(src, caller_context.compilation_unit) + return id_idx + + else: + expr = parse_expression(expression.value, caller_context) + + member_access = MemberAccess(member_name, None, expr) + + return member_access + if isinstance(expression, Name): var, was_created = find_variable(expression.id, caller_context) - print(var) - print(var.__class__) + assert var return Identifier(var) + if isinstance(expression, Assign): + lhs = parse_expression(expression.target, caller_context) + rhs = parse_expression(expression.value, caller_context) + return AssignmentOperation(lhs, rhs, AssignmentOperationType.ASSIGN, None) + + if isinstance(expression, AugAssign): + lhs = parse_expression(expression.target, caller_context) + rhs = parse_expression(expression.value, caller_context) + + op = AssignmentOperationType.get_type(expression.op) + return BinaryOperation(lhs, rhs, op) + if isinstance(expression, Tuple): tuple_vars = [parse_expression(x, caller_context) for x in expression.elements] return TupleExpression(tuple_vars) @@ -306,7 +385,46 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return UnaryOperation(operand, op) - if isinstance(expression, (BinOp, Compare)): + if isinstance(expression, Compare): + lhs = parse_expression(expression.left, caller_context) + + if expression.op in ["In", "NotIn"]: + # If we see a membership operator e.g. x in [foo(), bar()] we rewrite it as if-else: + # if (x == foo()) { + # return true + # } else { + # if (x == bar()) { + # return true + # } else { + # return false + # } + # } + # We assume left operand in membership comparison cannot be Array type + assert isinstance(expression.right, VyList) + conditions = deque() + inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") + for elem in expression.right.elements: + elem_expr = parse_expression(elem, caller_context) + + conditions.append(BinaryOperation(lhs, elem_expr, inner_op)) + + assert len(conditions) % 2 == 0 + while len(conditions) > 1: + lhs = conditions.pop() + rhs = conditions.pop() + + conditions.appendleft(BinaryOperation(lhs, rhs, outer_op)) + + return conditions.pop() + + else: + rhs = parse_expression(expression.right, caller_context) + + op = BinaryOperationType.get_type(expression.op) + return BinaryOperation(lhs, rhs, op) + + if isinstance(expression, BinOp): lhs = parse_expression(expression.left, caller_context) rhs = parse_expression(expression.right, caller_context) @@ -326,4 +444,18 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return CallExpression(Identifier(func), args, type_str) + if isinstance(expression, Subscript): + left_expression = parse_expression(expression.value, caller_context) + right_expression = parse_expression(expression.slice.value, caller_context) + index = IndexAccess(left_expression, right_expression) + # index.set_offset(src, caller_context.compilation_unit) + return index + + if isinstance(expression, BoolOp): + lhs = parse_expression(expression.values[0], caller_context) + rhs = parse_expression(expression.values[1], caller_context) + + # op = BinaryOperationType.get_type(expression.op) TODO update BoolOp AST + return BinaryOperation(lhs, rhs,BinaryOperationType.ANDAND) + raise ParsingError(f"Expression not parsed {expression}") diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 4e0564a42..daef44df8 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -43,8 +43,9 @@ def _find_variable_in_function_parser( ) -> Optional[Variable]: if function_parser is None: return None - func_variables = function_parser.underlying_function.variables_as_dict - print("func_variables", func_variables) + func_variables = function_parser.variables_as_dict + # print("func_variables", func_variables) + if var_name in func_variables: return func_variables[var_name] @@ -64,14 +65,14 @@ def _find_in_contract( # variable are looked from the contract declarer print(contract) contract_variables = contract.variables_as_dict - print(contract_variables) + # print(contract_variables) if var_name in contract_variables: return contract_variables[var_name] functions = {f.name: f for f in contract.functions if not f.is_shadowed} - print(functions) + # print(functions) if var_name in functions: return functions[var_name] @@ -196,32 +197,41 @@ def find_variable( # the contract inheriting from C) # for events it's unclear what should be the behavior, as they can be shadowed, but there is not impact # structure/enums cannot be shadowed - - direct_contracts = [caller_context] - direct_functions = caller_context.functions_declared - print(direct_functions) - current_scope = caller_context.file_scope + from slither.vyper_parsing.declarations.contract import ContractVyper + from slither.vyper_parsing.declarations.function import FunctionVyper + print("caller_context") + print(caller_context) + print(caller_context.__class__.__name__) + if isinstance(caller_context, Contract): + direct_contracts = [caller_context] + direct_functions = caller_context.functions_declared + current_scope = caller_context.file_scope + next_context = caller_context + else: + direct_contracts = [caller_context.contract] + direct_functions = caller_context.contract.functions_declared + current_scope = caller_context.contract.file_scope + next_context = caller_context.contract + # print(direct_functions) # Only look for reference declaration in the direct contract, see comment at the end # Reference looked are split between direct and all # Because functions are copied between contracts, two functions can have the same ref # So we need to first look with respect to the direct context - from slither.vyper_parsing.declarations.contract import ContractVyper - from slither.vyper_parsing.declarations.function import FunctionVyper function_parser: Optional[FunctionVyper] = ( - caller_context if isinstance(caller_context, FunctionVyper) else None + caller_context if isinstance(caller_context, FunctionContract) else None ) - print("function_parser", function_parser) + # print("function_parser", function_parser) ret1 = _find_variable_in_function_parser(var_name, function_parser) if ret1: return ret1, False - ret = _find_in_contract(var_name, caller_context, caller_context) + ret = _find_in_contract(var_name, next_context, caller_context) if ret: return ret, False - print(current_scope.variables) + # print(current_scope.variables) if var_name in current_scope.variables: return current_scope.variables[var_name], False @@ -238,9 +248,11 @@ def find_variable( if var_name in SOLIDITY_VARIABLES: return SolidityVariable(var_name), False - if var_name in SOLIDITY_FUNCTIONS: - return SolidityFunction(var_name), False - - + if f"{var_name}()" in SOLIDITY_FUNCTIONS: + return SolidityFunction(f"{var_name}()"), False + print(next_context.events_as_dict) + if f"{var_name}()" in next_context.events_as_dict: + return next_context.events_as_dict[f"{var_name}()"], False + raise VariableNotFound(f"Variable not found: {var_name} (context {caller_context})") diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index 49cfd6b2d..15fc16df6 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -5,13 +5,20 @@ from slither.core.solidity_types.elementary_type import ( from slither.core.solidity_types.array_type import ArrayType from slither.core.solidity_types.mapping_type import MappingType -from slither.vyper_parsing.expressions.expression_parsing import parse_expression from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple from typing import Union from slither.core.solidity_types.user_defined_type import UserDefinedType +from slither.core.declarations.function_contract import FunctionContract + +def parse_type(annotation: Union[Name, Subscript, Call], caller_context): + from slither.vyper_parsing.expressions.expression_parsing import parse_expression + + if isinstance(caller_context, FunctionContract): + contract = caller_context.contract + else: + contract = caller_context -def parse_type(annotation: Union[Name, Subscript, Call], contract): assert isinstance(annotation, (Name, Subscript, Call)) print(annotation) if isinstance(annotation, Name): @@ -22,32 +29,32 @@ def parse_type(annotation: Union[Name, Subscript, Call], contract): if isinstance(annotation.slice.value, Tuple): assert isinstance(annotation.value, Name) if annotation.value.id == "DynArray": - type_ = parse_type(annotation.slice.value.elements[0], contract) - length = parse_expression(annotation.slice.value.elements[1], contract) + type_ = parse_type(annotation.slice.value.elements[0], caller_context) + length = parse_expression(annotation.slice.value.elements[1], caller_context) return ArrayType(type_, length) else: assert annotation.value.id == "HashMap" - type_from = parse_type(annotation.slice.value.elements[0], contract) - type_to = parse_type(annotation.slice.value.elements[1], contract) + type_from = parse_type(annotation.slice.value.elements[0], caller_context) + type_to = parse_type(annotation.slice.value.elements[1], caller_context) return MappingType(type_from, type_to) elif isinstance(annotation.value, Subscript): - type_ = parse_type(annotation.value, contract) + type_ = parse_type(annotation.value, caller_context) elif isinstance(annotation.value, Name): # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression, so we grab the value. # Subscript(src='13:10:0', node_id=7, value=Name(src='13:6:0', node_id=8, id='String'), slice=Index(src='13:10:0', node_id=12, value=Int(src='20:2:0', node_id=10, value=64))) - type_ = parse_type(annotation.value, contract) + type_ = parse_type(annotation.value, caller_context) if annotation.value.id == "String": return type_ - length = parse_expression(annotation.slice.value, contract) + length = parse_expression(annotation.slice.value, caller_context) return ArrayType(type_, length) elif isinstance(annotation, Call): - return parse_type(annotation.args[0], contract) + return parse_type(annotation.args[0], caller_context) else: assert False @@ -56,7 +63,7 @@ def parse_type(annotation: Union[Name, Subscript, Call], contract): if lname in ElementaryTypeName: return ElementaryType(lname) - print(contract.structures_as_dict) + if name in contract.structures_as_dict: return UserDefinedType(contract.structures_as_dict[name]) From 6fd82fee5887cc4e17fa796babf79bd5fbb4e893 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 22 Aug 2023 20:34:21 -0500 Subject: [PATCH 164/338] aug assign op --- slither/vyper_parsing/ast/ast.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index 2c2470c74..f562c7cae 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -301,11 +301,13 @@ def parse_enum_def(raw: Dict) -> EnumDef: return EnumDef(name=raw["name"], body=nodes_parsed, **_extract_base_props(raw)) +aug_assign_ast_type_to_op_symbol = {"Add": "+=", "Mult": "*=", "Sub": "-=", "Div": "-=", "Pow": "**=", "Mod": "%=", "BitAnd": "&=", "BitOr": "|=", "Shr": "<<=", "Shl": ">>="} def parse_aug_assign(raw: Dict) -> AugAssign: + op_str = aug_assign_ast_type_to_op_symbol[raw["op"]["ast_type"]] return AugAssign( target=parse(raw["target"]), - op=raw["op"], + op=op_str, value=parse(raw["value"]), **_extract_base_props(raw), ) From 75c3389ace991a3c05a5fca6436c0d4d43c4ccdb Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 24 Aug 2023 09:39:18 -0500 Subject: [PATCH 165/338] wip rewrite of for loops --- .../vyper_parsing/declarations/function.py | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index cf50fd41a..c16bf16b3 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -178,6 +178,8 @@ class FunctionVyper: for node_parser in self._node_to_NodeVyper.values(): node_parser.analyze_expressions(self._function) + + # endregion ################################################################################### ################################################################################### @@ -239,11 +241,63 @@ class FunctionVyper: # link_underlying_nodes(curr_node, new_node) elif isinstance(expr, For): + node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + + counter_var = AnnAssign(expr.target.src, expr.target.node_id, target=Name("-1:-1:-1", -1, "counter_var"), annotation=Name("-1:-1:-1", -1, "uint256"), value=Int("-1:-1:-1", -1, 0)) + local_var_parser = LocalVariableVyper(local_var, counter_var) + self._add_local_variable(local_var_parser) + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + new_node.add_unparsed_expression(counter_var.value) + new_node.underlying_node.add_variable_declaration(local_var) + + if isinstance(expr.iter, Name): + # TODO use expr.src instead of -1:-1:1? + cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=Call("-1:-1:-1", -1, func=Name("-1:-1:-1", -1, "len"), args=[expr.iter], keywords=[], keyword=None)) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) + + # HACK + # The loop variable is not annotated so we infer its type by looking at the type of the iterator + loop_iterator = list(filter(lambda x: x._variable.name == expr.iter.id, self._local_variables_parser))[0] + # Assumes `Subscript` + # TODO this should go in the body of the loop: expr.body.insert(0, ...) + loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] + value = Subscript("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, loop_iterator._variable.name), slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var"))) + loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=loop_var_annotation, value=value) + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + local_var_parser = LocalVariableVyper(local_var, loop_var) + self._add_local_variable(local_var_parser) + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + new_node.add_unparsed_expression(loop_var.value) + new_node.underlying_node.add_variable_declaration(local_var) + + elif isinstance(expr.iter, Call): + range_val = expr.iter.args[0] + cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=range_val) + loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=Name("-1:-1:-1", -1, "uint256"), value=Name("-1:-1:-1", -1, "counter_var")) + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + local_var_parser = LocalVariableVyper(local_var, loop_var) + self._add_local_variable(local_var_parser) + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + new_node.add_unparsed_expression(loop_var.value) + new_node.underlying_node.add_variable_declaration(local_var) + else: + print(expr) + raise NotImplementedError + # assert False node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) - node_condition = self._new_node(NodeType.IFLOOP, expr.iter.src, scope) - node_condition.add_unparsed_expression(expr.iter) + + # link_underlying_nodes(node_startLoop, node_condition) for stmt in expr.body: parse_statement(curr_node, stmt) From 2f94d1c2517cdd010b2c02d432a8d7c7b11c337b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 24 Aug 2023 13:57:48 -0500 Subject: [PATCH 166/338] more builtins; support params, state vars in loop iterators --- .../core/declarations/solidity_variables.py | 13 +++++- .../vyper_parsing/declarations/contract.py | 4 +- .../vyper_parsing/declarations/function.py | 26 ++++++++--- .../expressions/expression_parsing.py | 43 ++++++++++++++----- .../vyper_parsing/variables/local_variable.py | 8 +++- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 76c28552e..c14efef77 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -16,6 +16,7 @@ SOLIDITY_VARIABLES = { "tx": "", "block": "", "super": "", + "chain": "", } SOLIDITY_VARIABLES_COMPOSED = { @@ -86,7 +87,7 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "create_from_blueprint()":[], "empty()":[], "convert()":[], # TODO make type conversion - "len()":[], + "len()":["uint256"], "method_id()":[], "unsafe_sub()": [], "unsafe_add()": [], @@ -97,7 +98,15 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "min_value()":[], "concat()":[], "ecrecover()":[], - "isqrt()":[] + "isqrt()":[], + "range()":[], + "min()":[], + "max()":[], + "shift()":[], + "abs()":[], + "raw_call()":[], + "_abi_encode()":[], + "slice()":[], } diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index d252c5bce..6ad98296e 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -85,7 +85,7 @@ class ContractVyper: self._contract.file_scope.contracts[contract.name] = contract elif isinstance(node, InterfaceDef): - # TODO This needs to be done lazily as interfaces can refer to constant state variables + # This needs to be done lazily as interfaces can refer to constant state variables contract = Contract(self._contract.compilation_unit, self._contract.file_scope) contract.set_offset(node.src, self._contract.compilation_unit) contract.is_interface = True @@ -158,7 +158,7 @@ class ContractVyper: func.set_contract(self._contract) func.set_contract_declarer(self._contract) - func_parser = FunctionVyper(func, function) + func_parser = FunctionVyper(func, function, self) self._contract.add_function(func) self._functions_parser.append(func_parser) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index c16bf16b3..5541f86df 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -30,6 +30,7 @@ class FunctionVyper: self, function: Function, function_data: Dict, + contract_parser: "ContractVyper", ) -> None: self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} @@ -40,6 +41,7 @@ class FunctionVyper: self._function.id = function_data.node_id self._local_variables_parser: List = [] + self._contract_parser = contract_parser for decorator in function_data.decorators: if not hasattr(decorator, "id"): @@ -255,18 +257,28 @@ class FunctionVyper: new_node.add_unparsed_expression(counter_var.value) new_node.underlying_node.add_variable_declaration(local_var) - if isinstance(expr.iter, Name): + if isinstance(expr.iter, (Attribute,Name)): + # HACK + # The loop variable is not annotated so we infer its type by looking at the type of the iterator + if isinstance(expr.iter, Attribute): # state + iter_expr = expr.iter + loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.attr, self._contract_parser._variables_parser))[0] + + else: # local + iter_expr = expr.iter + loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.id, self._local_variables_parser))[0] + # TODO use expr.src instead of -1:-1:1? - cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=Call("-1:-1:-1", -1, func=Name("-1:-1:-1", -1, "len"), args=[expr.iter], keywords=[], keyword=None)) + cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=Call("-1:-1:-1", -1, func=Name("-1:-1:-1", -1, "len"), args=[iter_expr], keywords=[], keyword=None)) node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) node_condition.add_unparsed_expression(cond_expr) - # HACK - # The loop variable is not annotated so we infer its type by looking at the type of the iterator - loop_iterator = list(filter(lambda x: x._variable.name == expr.iter.id, self._local_variables_parser))[0] - # Assumes `Subscript` # TODO this should go in the body of the loop: expr.body.insert(0, ...) - loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] + if loop_iterator._elem_to_parse.value.id == "DynArray": + loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] + else: + loop_var_annotation = loop_iterator._elem_to_parse.value + value = Subscript("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, loop_iterator._variable.name), slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var"))) loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=loop_var_annotation, value=value) local_var = LocalVariable() diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index ee6e1c9d1..544dcbf65 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -282,7 +282,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": called = parse_expression(expression.func, caller_context) if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): - if called.value.name == "convert()": + if called.value.name == "empty()": + type_to = parse_type(expression.args[0], caller_context) + return CallExpression(called, [], str(type_to)) + elif called.value.name == "convert()": arg = parse_expression(expression.args[0], caller_context) type_to = parse_type(expression.args[1], caller_context) return TypeConversion(arg, type_to) @@ -294,9 +297,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": elif called.value.name== "max_value()": type_to = parse_type(expression.args[0], caller_context) member_type = str(type_to) - x = MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) - print(x) - return x + # TODO return Literal + return MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) if expression.args and isinstance(expression.args[0], VyDict): @@ -320,7 +322,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else: rets = ["tuple()"] - + elif isinstance(called, MemberAccess) and called.type is not None: + # (recover_type_2) Propagate the type collected to the `CallExpression` + # see recover_type_1 + rets = called.type else: rets = ["tuple()"] @@ -330,7 +335,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return str(x.type) type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" - + print(CallExpression(called, arguments, type_str)) + print(type_str) return CallExpression(called, arguments, type_str) if isinstance(expression, Attribute): @@ -352,8 +358,25 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else: expr = parse_expression(expression.value, caller_context) - - member_access = MemberAccess(member_name, None, expr) + member_name_ret_type = None + # (recover_type_1) This may be a call to an interface and we don't have the return types, + # so we see if there's a function identifier with `member_name` and propagate the type to + # its enclosing `CallExpression` + # try: TODO this is using the wrong caller_context and needs to be interface instead of self namespace + # var, was_created = find_variable(member_name, caller_context) + # if isinstance(var, Function): + # rets = var.returns + # def get_type_str(x): + # if isinstance(x, str): + # return x + # return str(x.type) + + # type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" + # member_name_ret_type = type_str + # except: + # pass + + member_access = MemberAccess(member_name, member_name_ret_type, expr) return member_access @@ -373,9 +396,9 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": rhs = parse_expression(expression.value, caller_context) op = AssignmentOperationType.get_type(expression.op) - return BinaryOperation(lhs, rhs, op) + return AssignmentOperation(lhs, rhs, op, None) - if isinstance(expression, Tuple): + if isinstance(expression, (Tuple, VyList)): tuple_vars = [parse_expression(x, caller_context) for x in expression.elements] return TupleExpression(tuple_vars) diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py index 45eb55351..3651b701f 100644 --- a/slither/vyper_parsing/variables/local_variable.py +++ b/slither/vyper_parsing/variables/local_variable.py @@ -9,13 +9,17 @@ class LocalVariableVyper: def __init__(self, variable: LocalVariable, variable_data: Union[Arg, Name]) -> None: self._variable: LocalVariable = variable - if isinstance(variable_data, (Arg, )): + if isinstance(variable_data, Arg): self._variable.name = variable_data.arg self._elem_to_parse = variable_data.annotation - elif isinstance(variable_data, (AnnAssign, )): + elif isinstance(variable_data, AnnAssign): self._variable.name = variable_data.target.id self._elem_to_parse = variable_data.annotation + elif isinstance(variable_data, Name): + self._variable.name = variable_data.id + self._elem_to_parse = variable_data else: + # param Subscript self._variable.name = "" self._elem_to_parse = variable_data From 872d9b59b0c6a37cdc31c5d87d385a7cb40d0f8d Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 24 Aug 2023 17:10:05 -0500 Subject: [PATCH 167/338] support enum bitwise comparison operations --- .../expressions/expression_parsing.py | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 544dcbf65..d3c0dd126 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -423,16 +423,34 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # } # } # We assume left operand in membership comparison cannot be Array type - assert isinstance(expression.right, VyList) conditions = deque() - inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") - for elem in expression.right.elements: - elem_expr = parse_expression(elem, caller_context) + if isinstance(expression.right, VyList): + inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") - conditions.append(BinaryOperation(lhs, elem_expr, inner_op)) + for elem in expression.right.elements: + elem_expr = parse_expression(elem, caller_context) + print("elem", repr(elem_expr)) + conditions.append(BinaryOperation(lhs, elem_expr, inner_op)) + else: + inner_op = BinaryOperationType.get_type("|") #if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type("&") #if expression.op == "NotIn" else BinaryOperationType.get_type("||") - assert len(conditions) % 2 == 0 + x, _ = find_variable(expression.right.value.attr, caller_context) + print(x) + print(x.type.type_to) + print(x.type.type_to.__class__) + enum_members = x.type.type_to.type.values + # for each value, create a literal with value = 2 ^ n (0 indexed) + # and then translate to bitmasking + enum_values = [Literal(2 ** n, ElementaryType("uint256")) for n in range(len(enum_members))] + inner_lhs = enum_values[0] + for expr in enum_values[1:]: + inner_lhs = BinaryOperation(inner_lhs, expr, inner_op) + conditions.append(inner_lhs) + print(conditions) + return BinaryOperation(lhs, conditions[0], outer_op) + while len(conditions) > 1: lhs = conditions.pop() rhs = conditions.pop() From 7549341c66c992e19ad6aae2a6ab23e7657188e2 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 10:53:22 -0500 Subject: [PATCH 168/338] add some builtin variables for vyper --- slither/core/declarations/solidity_variables.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index c14efef77..85844508e 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -36,6 +36,10 @@ SOLIDITY_VARIABLES_COMPOSED = { "msg.value": "uint256", "tx.gasprice": "uint256", "tx.origin": "address", + # Vyper + "chain.id": "uint256", + "block.prevhash": "bytes32", + } SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { From fd7c130d3903918050476bc301a1c1a9f8cfdece Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 10:53:47 -0500 Subject: [PATCH 169/338] allow type conversion to array type for vyper --- slither/slithir/operations/type_conversion.py | 5 +++-- slither/visitors/slithir/expression_to_slithir.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/slither/slithir/operations/type_conversion.py b/slither/slithir/operations/type_conversion.py index e9998bc65..08b87ab49 100644 --- a/slither/slithir/operations/type_conversion.py +++ b/slither/slithir/operations/type_conversion.py @@ -4,6 +4,7 @@ from slither.core.declarations import Contract from slither.core.solidity_types.elementary_type import ElementaryType from slither.core.solidity_types.type_alias import TypeAlias from slither.core.solidity_types.user_defined_type import UserDefinedType +from slither.core.solidity_types.array_type import ArrayType from slither.core.source_mapping.source_mapping import SourceMapping from slither.slithir.operations.lvalue import OperationWithLValue from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue @@ -21,10 +22,10 @@ class TypeConversion(OperationWithLValue): super().__init__() assert is_valid_rvalue(variable) or isinstance(variable, Contract) assert is_valid_lvalue(result) - assert isinstance(variable_type, (TypeAlias, UserDefinedType, ElementaryType)) + assert isinstance(variable_type, (TypeAlias, UserDefinedType, ElementaryType, ArrayType)) self._variable = variable - self._type: Union[TypeAlias, UserDefinedType, ElementaryType] = variable_type + self._type: Union[TypeAlias, UserDefinedType, ElementaryType, ArrayType] = variable_type self._lvalue = result @property diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index a99a6af86..5a6c7de59 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -573,7 +573,7 @@ class ExpressionToSlithIR(ExpressionVisitor): expr = get(expression.expression) val = TemporaryVariable(self._node) expression_type = expression.type - assert isinstance(expression_type, (TypeAlias, UserDefinedType, ElementaryType)) + assert isinstance(expression_type, (TypeAlias, UserDefinedType, ElementaryType, ArrayType)) operation = TypeConversion(val, expr, expression_type) val.set_type(expression.type) operation.set_expression(expression) From a8641d244fb58ee5cf1fd246a9fa79de5daa633a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 10:55:47 -0500 Subject: [PATCH 170/338] add anon. local for return signature --- slither/vyper_parsing/declarations/function.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 5541f86df..0cce65d04 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -399,14 +399,16 @@ class FunctionVyper: print(returns) self._function.returns_src().set_offset(returns.src, self._function.compilation_unit) - + # Only the type of the arg is given, not a name. We create an an `Arg` with an empty name + # so that the function has the correct return type in its signature but doesn't clash with + # other identifiers during name resolution (`find_variable`). if isinstance(returns, (Name, Subscript)): - local_var = self._add_param(returns) + local_var = self._add_param(Arg(returns.src, returns.node_id, "", annotation=returns)) self._function.add_return(local_var.underlying_variable) else: assert isinstance(returns, Tuple) for ret in returns.elements: - local_var = self._add_param(ret) + local_var = self._add_param(Arg(ret.src, ret.node_id, "", annotation=ret)) self._function.add_return(local_var.underlying_variable) ################################################################################### From 4c78fe00c4f9367228502f33b3ffadda55c4775b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 10:57:48 -0500 Subject: [PATCH 171/338] support conversion of interface to address, lookup interface funcs --- .../expressions/expression_parsing.py | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index d3c0dd126..86913ea7b 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -309,6 +309,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": arguments = [parse_expression(a, caller_context) for a in expression.args] if isinstance(called, Identifier): + print("called", called) + print("called.value", called.value.__class__.__name__) # Since the AST lacks the type of the return values, we recover it. if isinstance(called.value, Function): rets = called.value.returns @@ -325,7 +327,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": elif isinstance(called, MemberAccess) and called.type is not None: # (recover_type_2) Propagate the type collected to the `CallExpression` # see recover_type_1 - rets = called.type + rets = [called.type] else: rets = ["tuple()"] @@ -333,7 +335,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(x, str): return x return str(x.type) - + print(rets) type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" print(CallExpression(called, arguments, type_str)) print(type_str) @@ -347,8 +349,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": var, was_created = find_variable(member_name, caller_context) # TODO replace with self return SuperIdentifier(var) - expr = parse_expression(expression.value, caller_context) + # TODO this is ambiguous because it could be a type conversion of an interface or a member access + if expression.attr == "address": + return TypeConversion(expr, ElementaryType("address")) member_access = MemberAccess(member_name, None, expr) # member_access.set_offset(src, caller_context.compilation_unit) if str(member_access) in SOLIDITY_VARIABLES_COMPOSED: @@ -362,17 +366,22 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` - # try: TODO this is using the wrong caller_context and needs to be interface instead of self namespace - # var, was_created = find_variable(member_name, caller_context) - # if isinstance(var, Function): - # rets = var.returns - # def get_type_str(x): - # if isinstance(x, str): - # return x - # return str(x.type) - - # type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" - # member_name_ret_type = type_str + # TODO this is using the wrong caller_context and needs to be interface instead of self namespace + print(expr) + print(expr.__class__.__name__) + + if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType): + # try: + var, was_created = find_variable(member_name, expr.type.type) + if isinstance(var, Function): + rets = var.returns + def get_type_str(x): + if isinstance(x, str): + return x + return str(x.type) + + type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" + member_name_ret_type = type_str # except: # pass From cff917f99a36585ca96ccb8ae2c21768daa33ebe Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 20:51:26 -0500 Subject: [PATCH 172/338] handle stldib interfaces --- .../vyper_parsing/declarations/contract.py | 119 ++++++++++++++++-- 1 file changed, 110 insertions(+), 9 deletions(-) diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 6ad98296e..fde720340 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -10,6 +10,13 @@ from slither.vyper_parsing.ast.types import ( ImportFrom, InterfaceDef, AnnAssign, + Expr, + Name, + Arguments, + Index, + Subscript, + Int, + Arg, ) from slither.vyper_parsing.declarations.event import EventVyper @@ -74,15 +81,111 @@ class ContractVyper: elif isinstance(node, StructDef): self._structuresNotParsed.append(node) elif isinstance(node, ImportFrom): + # TOOD aliases + # We create an `InterfaceDef` sense the compilatuion unit does not contain the actual interface # https://github.com/vyperlang/vyper/tree/master/vyper/builtins/interfaces if node.module == "vyper.interfaces": - # TODO add functions - contract = Contract(self._contract.compilation_unit, self._contract.file_scope) - contract.set_offset("-1:-1:-1", self._contract.compilation_unit) - - contract.name = node.name - contract.is_interface = True - self._contract.file_scope.contracts[contract.name] = contract + interfaces = { + "ERC20Detailed": InterfaceDef( + src="-1:-1:-1", + node_id=-1, + name="ERC20Detailed", + body=[ + FunctionDef( + src="-1:-1:-1", + node_id=-1, + doc_string=None, + name="name", + args=Arguments( + src="-1:-1:-1", + node_id=-1, + args=[], + default=None, + defaults=[], + ), + returns=Subscript( + src="-1:-1:-1", + node_id=-1, + value=Name(src="-1:-1:-1", node_id=-1, id="String"), + slice=Index( + src="-1:-1:-1", + node_id=-1, + value=Int(src="-1:-1:-1", node_id=-1, value=1), + ), + ), + body=[ + Expr( + src="-1:-1:-1", + node_id=-1, + value=Name(src="-1:-1:-1", node_id=-1, id="view"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=-1, + doc_string=None, + name="symbol", + args=Arguments( + src="-1:-1:-1", + node_id=-1, + args=[], + default=None, + defaults=[], + ), + returns=Subscript( + src="-1:-1:-1", + node_id=-1, + value=Name(src="-1:-1:-1", node_id=-1, id="String"), + slice=Index( + src="-1:-1:-1", + node_id=-1, + value=Int(src="-1:-1:-1", node_id=-1, value=1), + ), + ), + body=[ + Expr( + src="-1:-1:-1", + node_id=-1, + value=Name(src="-1:-1:-1", node_id=-1, id="view"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=-1, + doc_string=None, + name="decimals", + args=Arguments( + src="-1:-1:-1", + node_id=-1, + args=[], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=-1, id="uint8"), + body=[ + Expr( + src="-1:-1:-1", + node_id=-1, + value=Name(src="-1:-1:-1", node_id=-1, id="view"), + ) + ], + decorators=[], + pos=None, + ), + ], + ), + "ERC20": InterfaceDef(src="-1:-1:-1", node_id=1, name='ERC20', body=[FunctionDef(src="-1:-1:-1", node_id=2, doc_string=None, name='totalSupply', args=Arguments(src="-1:-1:-1", node_id=3, args=[], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=7, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=4, value=Name(src="-1:-1:-1", node_id=5, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=9, doc_string=None, name='balanceOf', args=Arguments(src="-1:-1:-1", node_id=10, args=[Arg(src="-1:-1:-1", node_id=11, arg='_owner', annotation=Name(src="-1:-1:-1", node_id=12, id='address'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=17, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=14, value=Name(src="-1:-1:-1", node_id=15, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=19, doc_string=None, name='allowance', args=Arguments(src="-1:-1:-1", node_id=20, args=[Arg(src="-1:-1:-1", node_id=21, arg='_owner', annotation=Name(src="-1:-1:-1", node_id=22, id='address')), Arg(src="-1:-1:-1", node_id=24, arg='_spender', annotation=Name(src="-1:-1:-1", node_id=25, id='address'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=30, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=27, value=Name(src="-1:-1:-1", node_id=28, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=32, doc_string=None, name='transfer', args=Arguments(src="-1:-1:-1", node_id=33, args=[Arg(src="-1:-1:-1", node_id=34, arg='_to', annotation=Name(src="-1:-1:-1", node_id=35, id='address')), Arg(src="-1:-1:-1", node_id=37, arg='_value', annotation=Name(src="-1:-1:-1", node_id=38, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=43, id='bool'), body=[Expr(src="-1:-1:-1", node_id=40, value=Name(src="-1:-1:-1", node_id=41, id='nonpayable'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=45, doc_string=None, name='transferFrom', args=Arguments(src="-1:-1:-1", node_id=46, args=[Arg(src="-1:-1:-1", node_id=47, arg='_from', annotation=Name(src="-1:-1:-1", node_id=48, id='address')), Arg(src="-1:-1:-1", node_id=50, arg='_to', annotation=Name(src="-1:-1:-1", node_id=51, id='address')), Arg(src="-1:-1:-1", node_id=53, arg='_value', annotation=Name(src="-1:-1:-1", node_id=54, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=59, id='bool'), body=[Expr(src="-1:-1:-1", node_id=56, value=Name(src="-1:-1:-1", node_id=57, id='nonpayable'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=61, doc_string=None, name='approve', args=Arguments(src="-1:-1:-1", node_id=62, args=[Arg(src="-1:-1:-1", node_id=63, arg='_spender', annotation=Name(src="-1:-1:-1", node_id=64, id='address')), Arg(src="-1:-1:-1", node_id=66, arg='_value', annotation=Name(src="-1:-1:-1", node_id=67, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=72, id='bool'), body=[Expr(src="-1:-1:-1", node_id=69, value=Name(src="-1:-1:-1", node_id=70, id='nonpayable'))], decorators=[], pos=None)]), + "ERC165": [], + "ERC721": [], + "ERC4626": [], + } + self._data.body.append(interfaces[node.name]) elif isinstance(node, InterfaceDef): # This needs to be done lazily as interfaces can refer to constant state variables @@ -164,13 +267,11 @@ class ContractVyper: self._functionsNotParsed = [] - def analyze_state_variables(self): # Struct defs can refer to constant state variables for var_parser in self._variables_parser: var_parser.analyze(self._contract) - def analyze(self) -> None: print("Analyze", self._contract._name) From 3e461ca59c08eca81f7cd7c35f648a56cd92b0f2 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 20:56:14 -0500 Subject: [PATCH 173/338] initialized vars with expr --- slither/vyper_parsing/declarations/function.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 0cce65d04..d1b075864 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -225,6 +225,7 @@ class FunctionVyper: new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) if expr.value is not None: + local_var.initialized = True new_node.add_unparsed_expression(expr.value) new_node.underlying_node.add_variable_declaration(local_var) link_underlying_nodes(curr_node, new_node) @@ -254,6 +255,7 @@ class FunctionVyper: local_var_parser = LocalVariableVyper(local_var, counter_var) self._add_local_variable(local_var_parser) new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + local_var.initialized = True new_node.add_unparsed_expression(counter_var.value) new_node.underlying_node.add_variable_declaration(local_var) @@ -287,6 +289,7 @@ class FunctionVyper: local_var_parser = LocalVariableVyper(local_var, loop_var) self._add_local_variable(local_var_parser) new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + local_var.initialized = True new_node.add_unparsed_expression(loop_var.value) new_node.underlying_node.add_variable_declaration(local_var) @@ -300,6 +303,7 @@ class FunctionVyper: local_var_parser = LocalVariableVyper(local_var, loop_var) self._add_local_variable(local_var_parser) new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + local_var.initialized = True new_node.add_unparsed_expression(loop_var.value) new_node.underlying_node.add_variable_declaration(local_var) else: From 71894bad7ae0458d442b5f03ebda24d36f74909c Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 20:59:54 -0500 Subject: [PATCH 174/338] perform ssa conversion and analysis --- slither/vyper_parsing/vyper_compilation_unit.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index 0a3bb7d3e..f8a2ca216 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -58,12 +58,18 @@ class VyperCompilationUnit: self._analyzed = True def _convert_to_slithir(self) -> None: - for contract in self._compilation_unit.contracts: contract.add_constructor_variables() for func in contract.functions: func.generate_slithir_and_analyze() + contract.convert_expression_to_slithir_ssa() + + self._compilation_unit.propagate_function_calls() + for contract in self._compilation_unit.contracts: + contract.fix_phi() + contract.update_read_write_using_ssa() + # def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: # self._contracts_by_id: Dict[int, ContractSolc] = {} From b1cb181dea19cb968bf7f1e5fe0cbe28bb4a1b4b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 28 Aug 2023 21:02:48 -0500 Subject: [PATCH 175/338] remove unused code --- .../vyper_parsing/declarations/modifier.py | 107 ------------- .../expressions/find_variable.py | 50 +----- .../variables/variable_declaration.py | 150 ------------------ 3 files changed, 2 insertions(+), 305 deletions(-) delete mode 100644 slither/vyper_parsing/declarations/modifier.py delete mode 100644 slither/vyper_parsing/variables/variable_declaration.py diff --git a/slither/vyper_parsing/declarations/modifier.py b/slither/vyper_parsing/declarations/modifier.py deleted file mode 100644 index c4c5c7177..000000000 --- a/slither/vyper_parsing/declarations/modifier.py +++ /dev/null @@ -1,107 +0,0 @@ -""" - Event module -""" -from typing import Dict, TYPE_CHECKING, Union - -from slither.core.cfg.node import NodeType -from slither.core.cfg.node import link_nodes -from slither.core.cfg.scope import Scope -from slither.core.declarations.modifier import Modifier -from slither.solc_parsing.cfg.node import NodeSolc -from slither.solc_parsing.declarations.function import FunctionSolc - -if TYPE_CHECKING: - from slither.solc_parsing.declarations.contract import ContractSolc - from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc - from slither.core.declarations import Function - - -class ModifierSolc(FunctionSolc): - def __init__( - self, - modifier: Modifier, - function_data: Dict, - contract_parser: "ContractSolc", - slither_parser: "SlitherCompilationUnitSolc", - ) -> None: - super().__init__(modifier, function_data, contract_parser, slither_parser) - # _modifier is equal to _function, but keep it here to prevent - # confusion for mypy in underlying_function - self._modifier = modifier - - @property - def underlying_function(self) -> Modifier: - return self._modifier - - def analyze_params(self) -> None: - # Can be re-analyzed due to inheritance - if self._params_was_analyzed: - return - - self._params_was_analyzed = True - - self._analyze_attributes() - - if self.is_compact_ast: - params = self._functionNotParsed["parameters"] - else: - children = self._functionNotParsed["children"] - # It uses to be - # params = children[0] - # But from Solidity 0.6.3 to 0.6.10 (included) - # Comment above a function might be added in the children - params = next(child for child in children if child[self.get_key()] == "ParameterList") - - if params: - self._parse_params(params) - - def analyze_content(self) -> None: - if self._content_was_analyzed: - return - - self._content_was_analyzed = True - - if self.is_compact_ast: - body = self._functionNotParsed.get("body", None) - - if body and body[self.get_key()] == "Block": - self._function.is_implemented = True - self._parse_cfg(body) - - else: - children = self._functionNotParsed["children"] - - self._function.is_implemented = False - if len(children) > 1: - # It uses to be - # params = children[1] - # But from Solidity 0.6.3 to 0.6.10 (included) - # Comment above a function might be added in the children - block = next(child for child in children if child[self.get_key()] == "Block") - self._function.is_implemented = True - self._parse_cfg(block) - - for local_var_parser in self._local_variables_parser: - local_var_parser.analyze(self) - - for node in self._node_to_nodesolc.values(): - node.analyze_expressions(self) - - for yul_parser in self._node_to_yulobject.values(): - yul_parser.analyze_expressions() - - self._rewrite_ternary_as_if_else() - self._remove_alone_endif() - - # self._analyze_read_write() - # self._analyze_calls() - - def _parse_statement( - self, statement: Dict, node: NodeSolc, scope: Union[Scope, "Function"] - ) -> NodeSolc: - name = statement[self.get_key()] - if name == "PlaceholderStatement": - placeholder_node = self._new_node(NodeType.PLACEHOLDER, statement["src"], scope) - link_nodes(node.underlying_node, placeholder_node.underlying_node) - return placeholder_node - return super()._parse_statement(statement, node, scope) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index daef44df8..b75b688db 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -44,8 +44,7 @@ def _find_variable_in_function_parser( if function_parser is None: return None func_variables = function_parser.variables_as_dict - # print("func_variables", func_variables) - + print("func_variables", func_variables) if var_name in func_variables: return func_variables[var_name] @@ -65,7 +64,6 @@ def _find_in_contract( # variable are looked from the contract declarer print(contract) contract_variables = contract.variables_as_dict - # print(contract_variables) if var_name in contract_variables: return contract_variables[var_name] @@ -112,46 +110,6 @@ def _find_in_contract( return None -def _find_variable_init( - caller_context: CallerContextExpression, -) -> Tuple[List[Contract], List["Function"], FileScope,]: - from slither.vyper_parsing.declarations.contract import ContractVyper - from slither.vyper_parsing.declarations.function import FunctionVyper - - - direct_contracts: List[Contract] - direct_functions_parser: List[Function] - scope: FileScope - - if isinstance(caller_context, FileScope): - direct_contracts = [] - direct_functions_parser = [] - scope = caller_context - elif isinstance(caller_context, ContractVyper): - direct_contracts = [caller_context.underlying_contract] - direct_functions_parser = [ - f.underlying_function - for f in caller_context.functions_parser + caller_context.modifiers_parser - ] - scope = caller_context.underlying_contract.file_scope - elif isinstance(caller_context, FunctionVyper): - - direct_contracts = [caller_context.underlying_contract] - direct_functions_parser = [ - f.underlying_function - for f in caller_context.functions_parser - ] - - - scope = contract.file_scope - else: - raise SlitherError( - f"{type(caller_context)} ({caller_context} is not valid for find_variable" - ) - - return direct_contracts, direct_functions_parser, scope - - def find_variable( var_name: str, caller_context: CallerContextExpression, @@ -202,6 +160,7 @@ def find_variable( print("caller_context") print(caller_context) print(caller_context.__class__.__name__) + print("var", var_name) if isinstance(caller_context, Contract): direct_contracts = [caller_context] direct_functions = caller_context.functions_declared @@ -214,11 +173,6 @@ def find_variable( next_context = caller_context.contract # print(direct_functions) - # Only look for reference declaration in the direct contract, see comment at the end - # Reference looked are split between direct and all - # Because functions are copied between contracts, two functions can have the same ref - # So we need to first look with respect to the direct context - function_parser: Optional[FunctionVyper] = ( caller_context if isinstance(caller_context, FunctionContract) else None ) diff --git a/slither/vyper_parsing/variables/variable_declaration.py b/slither/vyper_parsing/variables/variable_declaration.py deleted file mode 100644 index 64878163c..000000000 --- a/slither/vyper_parsing/variables/variable_declaration.py +++ /dev/null @@ -1,150 +0,0 @@ -import logging -import re -from typing import Dict, Optional, Union - - -from slither.core.variables.variable import Variable -from slither.core.solidity_types.elementary_type import ( - ElementaryType, - NonElementaryType, -) -from slither.solc_parsing.exceptions import ParsingError - -from slither.vyper_parsing.ast.types import VariableDecl, Name, Subscript, ASTNode, Call, Arg -from slither.vyper_parsing.type_parsing import parse_type - - -class VariableDeclarationVyper: - # pylint: disable=too-many-branches - def __init__(self, variable: Variable, variable_data: VariableDecl) -> None: - """ - A variable can be declared through a statement, or directly. - If it is through a statement, the following children may contain - the init value. - It may be possible that the variable is declared through a statement, - but the init value is declared at the VariableDeclaration children level - """ - - self._variable = variable - if isinstance(variable_data, Arg): - self._variable.name = variable_data.arg - else: - self._variable.name = variable_data.target.id - self._was_analyzed: bool = False - self._initializedNotParsed: Optional[ASTNode] = None - - if isinstance(variable_data.annotation, Subscript): - self._elem_to_parse = variable_data.annotation.value.id - elif isinstance(variable_data.annotation, Name): - self._elem_to_parse = variable_data.annotation.id - else: # Event defs with indexed args - assert isinstance(variable_data.annotation, Call) - self._elem_to_parse = variable_data.annotation.args[0].id - self._init_from_declaration(variable_data) - # self._elem_to_parse: Optional[Union[Dict, UnknownType]] = None - # self._initializedNotParsed: Optional[Dict] = None - - # self._is_compact_ast = False - - # self._reference_id: Optional[int] = None - - @property - def underlying_variable(self) -> Variable: - return self._variable - - def _init_from_declaration(self, var: VariableDecl): - # Only state variables - - pass - - # self._handle_comment(attributes) - # Args do not have intial value - # print(var.value) - # assert var.value is None - # def _init_from_declaration( - # self, var: Dict, init: Optional[Dict] - # ) -> None: # pylint: disable=too-many-branches - # if self._is_compact_ast: - # attributes = var - # self._typeName = attributes["typeDescriptions"]["typeString"] - # else: - # assert len(var["children"]) <= 2 - # assert var["name"] == "VariableDeclaration" - - # attributes = var["attributes"] - # self._typeName = attributes["type"] - - # self._variable.name = attributes["name"] - # # self._arrayDepth = 0 - # # self._isMapping = False - # # self._mappingFrom = None - # # self._mappingTo = False - # # self._initial_expression = None - # # self._type = None - - # # Only for comapct ast format - # # the id can be used later if referencedDeclaration - # # is provided - # if "id" in var: - # self._reference_id = var["id"] - - # if "constant" in attributes: - # self._variable.is_constant = attributes["constant"] - - # if "mutability" in attributes: - # # Note: this checked is not needed if "constant" was already in attribute, but we keep it - # # for completion - # if attributes["mutability"] == "constant": - # self._variable.is_constant = True - # if attributes["mutability"] == "immutable": - # self._variable.is_immutable = True - - # self._analyze_variable_attributes(attributes) - - # if self._is_compact_ast: - # if var["typeName"]: - # self._elem_to_parse = var["typeName"] - # else: - # self._elem_to_parse = UnknownType(var["typeDescriptions"]["typeString"]) - # else: - # if not var["children"]: - # # It happens on variable declared inside loop declaration - # try: - # self._variable.type = ElementaryType(self._typeName) - # self._elem_to_parse = None - # except NonElementaryType: - # self._elem_to_parse = UnknownType(self._typeName) - # else: - # self._elem_to_parse = var["children"][0] - - # if self._is_compact_ast: - # self._initializedNotParsed = init - # if init: - # self._variable.initialized = True - # else: - # if init: # there are two way to init a var local in the AST - # assert len(var["children"]) <= 1 - # self._variable.initialized = True - # self._initializedNotParsed = init - # elif len(var["children"]) in [0, 1]: - # self._variable.initialized = False - # self._initializedNotParsed = None - # else: - # assert len(var["children"]) == 2 - # self._variable.initialized = True - # self._initializedNotParsed = var["children"][1] - - def analyze(self) -> None: - if self._was_analyzed: - return - self._was_analyzed = True - - if self._elem_to_parse is not None: - print(self._elem_to_parse) - # assert False - self._variable.type = parse_type(self._elem_to_parse) - self._elem_to_parse = None - - # if self._variable.initialized is not None: - # self._variable.expression = parse_expression(self._initializedNotParsed) - # self._initializedNotParsed = None From 5d79bc8c4097006157e7957f641fe61f4338df6c Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 29 Aug 2023 17:43:21 +0200 Subject: [PATCH 176/338] Improve constants extraction of ReferenceVariable --- slither/printers/guidance/echidna.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 25e0968cd..1d1c6657a 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -30,7 +30,7 @@ from slither.slithir.operations import ( TypeConversion, ) from slither.slithir.operations.binary import Binary -from slither.slithir.variables import Constant +from slither.slithir.variables import Constant, ReferenceVariable from slither.utils.output import Output from slither.visitors.expression.constants_folding import ConstantFolding, NotConstant @@ -208,19 +208,20 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n except ValueError: # index could fail; should never happen in working solidity code pass for r in ir.read: + var_read = r.points_to_origin if isinstance(r, ReferenceVariable) else r # Do not report struct_name in a.struct_name if isinstance(ir, Member): continue - if isinstance(r, Constant): - all_cst_used.append(ConstantValue(str(r.value), str(r.type))) - if isinstance(r, StateVariable): - if r.node_initialization: - if r.node_initialization.irs: - if r.node_initialization in context_explored: + if isinstance(var_read, Constant): + all_cst_used.append(ConstantValue(str(var_read.value), str(var_read.type))) + if isinstance(var_read, StateVariable): + if var_read.node_initialization: + if var_read.node_initialization.irs: + if var_read.node_initialization in context_explored: continue - context_explored.add(r.node_initialization) + context_explored.add(var_read.node_initialization) _extract_constants_from_irs( - r.node_initialization.irs, + var_read.node_initialization.irs, all_cst_used, all_cst_used_in_binary, context_explored, From b537b70ef724d8af8c93bc9d62ff84a872ca6c77 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 15:31:24 -0500 Subject: [PATCH 177/338] fix type --- slither/slithir/variables/constant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/slithir/variables/constant.py b/slither/slithir/variables/constant.py index 5321e5250..19aaaa893 100644 --- a/slither/slithir/variables/constant.py +++ b/slither/slithir/variables/constant.py @@ -11,7 +11,7 @@ from slither.utils.integer_conversion import convert_string_to_int class Constant(SlithIRVariable): def __init__( self, - val: Union[int, str], + val: str, constant_type: Optional[ElementaryType] = None, subdenomination: Optional[str] = None, ) -> None: # pylint: disable=too-many-branches From 8a3fb6ad99a5ddd474d89dcd20e9e3c927062a2e Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 15:31:41 -0500 Subject: [PATCH 178/338] fix div symbol --- slither/vyper_parsing/ast/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index f562c7cae..ca748954a 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -205,7 +205,7 @@ def parse_unary_op(raw: Dict) -> UnaryOp: return UnaryOp(op=unop_str, operand=parse(raw["operand"]), **_extract_base_props(raw)) # This is done for convenience so we can call `BinaryOperationType.get_type` during expression parsing. -binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "-", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>", "NotEq": "!=", "Eq": "==", "LtE": "<=", "GtE": ">=", "Lt": "<", "Gt": ">", "In": "In", "NotIn": "NotIn"} +binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "/", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>", "NotEq": "!=", "Eq": "==", "LtE": "<=", "GtE": ">=", "Lt": "<", "Gt": ">", "In": "In", "NotIn": "NotIn"} def parse_bin_op(raw: Dict) -> BinOp: arith_op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] From 472efb9cda4e9a81ee9eae9de837310bf6ba3ac0 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 15:33:02 -0500 Subject: [PATCH 179/338] improve comparison operator support, set_offset of expressions --- slither/vyper_parsing/cfg/node.py | 8 +- .../expressions/expression_parsing.py | 186 +++++++++++++----- 2 files changed, 137 insertions(+), 57 deletions(-) diff --git a/slither/vyper_parsing/cfg/node.py b/slither/vyper_parsing/cfg/node.py index cf8a8f160..3d5ffee91 100644 --- a/slither/vyper_parsing/cfg/node.py +++ b/slither/vyper_parsing/cfg/node.py @@ -32,7 +32,7 @@ class NodeVyper: if self._unparsed_expression: expression = parse_expression(self._unparsed_expression, caller_context) self._node.add_expression(expression) - # self._unparsed_expression = None + self._unparsed_expression = None if self._node.expression: @@ -44,9 +44,9 @@ class NodeVyper: AssignmentOperationType.ASSIGN, self._node.variable_declaration.type, ) - # _expression.set_offset( - # self._node.expression.source_mapping, self._node.compilation_unit - # ) + _expression.set_offset( + self._node.expression.source_mapping, self._node.compilation_unit + ) self._node.add_expression(_expression, bypass_verif_empty=True) expression = self._node.expression diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 86913ea7b..8ce757732 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -262,21 +262,31 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # assert False if isinstance(expression, Int): - return Literal(str(expression.value), ElementaryType("uint256")) + literal = Literal(str(expression.value), ElementaryType("uint256")) + literal.set_offset(expression.src, caller_context.compilation_unit) + return literal if isinstance(expression, Hex): # TODO this is an implicit conversion and could potentially be bytes20 or other? - return Literal(str(expression.value), ElementaryType("address")) + literal = Literal(str(expression.value), ElementaryType("address")) + literal.set_offset(expression.src, caller_context.compilation_unit) + return literal if isinstance(expression, Str): - return Literal(str(expression.value), ElementaryType("string")) + literal = Literal(str(expression.value), ElementaryType("string")) + literal.set_offset(expression.src, caller_context.compilation_unit) + return literal if isinstance(expression, Bytes): - return Literal(str(expression.value), ElementaryType("bytes")) + literal = Literal(str(expression.value), ElementaryType("bytes")) + literal.set_offset(expression.src, caller_context.compilation_unit) + return literal if isinstance(expression, NameConstant): assert str(expression.value) in ["True", "False"] - return Literal(str(expression.value), ElementaryType("bool")) + literal = Literal(str(expression.value), ElementaryType("bool")) + literal.set_offset(expression.src, caller_context.compilation_unit) + return literal if isinstance(expression, Call): called = parse_expression(expression.func, caller_context) @@ -284,21 +294,30 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): if called.value.name == "empty()": type_to = parse_type(expression.args[0], caller_context) - return CallExpression(called, [], str(type_to)) + parsed_expr = CallExpression(called, [], str(type_to)) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr + elif called.value.name == "convert()": arg = parse_expression(expression.args[0], caller_context) type_to = parse_type(expression.args[1], caller_context) - return TypeConversion(arg, type_to) + parsed_expr = TypeConversion(arg, type_to) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr + elif called.value.name== "min_value()": type_to = parse_type(expression.args[0], caller_context) member_type = str(type_to) # TODO return Literal - return MemberAccess("min", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + parsed_expr = MemberAccess("min", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + return parsed_expr + elif called.value.name== "max_value()": type_to = parse_type(expression.args[0], caller_context) member_type = str(type_to) # TODO return Literal - return MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + parsed_expr = MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + return parsed_expr if expression.args and isinstance(expression.args[0], VyDict): @@ -320,10 +339,13 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # Type conversions are not explicitly represented in the AST e.g. converting address to contract/ interface, # so we infer that a type conversion is occurring if `called` is a `Contract` type. type_to = parse_type(expression.func, caller_context) - return TypeConversion(arguments[0], type_to) + parsed_expr = TypeConversion(arguments[0], type_to) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr else: rets = ["tuple()"] + elif isinstance(called, MemberAccess) and called.type is not None: # (recover_type_2) Propagate the type collected to the `CallExpression` # see recover_type_1 @@ -337,9 +359,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return str(x.type) print(rets) type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" - print(CallExpression(called, arguments, type_str)) - print(type_str) - return CallExpression(called, arguments, type_str) + + parsed_expr = CallExpression(called, arguments, type_str) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, Attribute): member_name = expression.attr @@ -348,17 +371,25 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if expression.value.id == "self": var, was_created = find_variable(member_name, caller_context) # TODO replace with self - return SuperIdentifier(var) + if was_created: + var.set_offset(expression.src, caller_context.compilation_unit) + parsed_expr = SuperIdentifier(var) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr + expr = parse_expression(expression.value, caller_context) # TODO this is ambiguous because it could be a type conversion of an interface or a member access if expression.attr == "address": - return TypeConversion(expr, ElementaryType("address")) + parsed_expr = TypeConversion(expr, ElementaryType("address")) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr + member_access = MemberAccess(member_name, None, expr) - # member_access.set_offset(src, caller_context.compilation_unit) + if str(member_access) in SOLIDITY_VARIABLES_COMPOSED: - id_idx = Identifier(SolidityVariableComposed(str(member_access))) - # id_idx.set_offset(src, caller_context.compilation_unit) - return id_idx + parsed_expr = Identifier(SolidityVariableComposed(str(member_access))) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr else: expr = parse_expression(expression.value, caller_context) @@ -387,35 +418,46 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": member_access = MemberAccess(member_name, member_name_ret_type, expr) + member_access.set_offset(expression.src, caller_context.compilation_unit) return member_access if isinstance(expression, Name): var, was_created = find_variable(expression.id, caller_context) - - assert var - return Identifier(var) + if was_created: + var.set_offset(expression.src, caller_context.compilation_unit) + parsed_expr = Identifier(var) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, Assign): lhs = parse_expression(expression.target, caller_context) rhs = parse_expression(expression.value, caller_context) - return AssignmentOperation(lhs, rhs, AssignmentOperationType.ASSIGN, None) + parsed_expr = AssignmentOperation(lhs, rhs, AssignmentOperationType.ASSIGN, None) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, AugAssign): lhs = parse_expression(expression.target, caller_context) rhs = parse_expression(expression.value, caller_context) op = AssignmentOperationType.get_type(expression.op) - return AssignmentOperation(lhs, rhs, op, None) + parsed_expr = AssignmentOperation(lhs, rhs, op, None) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, (Tuple, VyList)): tuple_vars = [parse_expression(x, caller_context) for x in expression.elements] - return TupleExpression(tuple_vars) + parsed_expr = TupleExpression(tuple_vars) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, UnaryOp): operand = parse_expression(expression.operand, caller_context) op = UnaryOperationType.get_type(expression.op, isprefix=True) #TODO does vyper have postfix? - return UnaryOperation(operand, op) + parsed_expr = UnaryOperation(operand, op) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, Compare): lhs = parse_expression(expression.left, caller_context) @@ -440,25 +482,55 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": for elem in expression.right.elements: elem_expr = parse_expression(elem, caller_context) print("elem", repr(elem_expr)) - conditions.append(BinaryOperation(lhs, elem_expr, inner_op)) + parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + conditions.append(parsed_expr) else: - inner_op = BinaryOperationType.get_type("|") #if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type("&") #if expression.op == "NotIn" else BinaryOperationType.get_type("||") - - x, _ = find_variable(expression.right.value.attr, caller_context) - print(x) - print(x.type.type_to) - print(x.type.type_to.__class__) - enum_members = x.type.type_to.type.values - # for each value, create a literal with value = 2 ^ n (0 indexed) - # and then translate to bitmasking - enum_values = [Literal(2 ** n, ElementaryType("uint256")) for n in range(len(enum_members))] - inner_lhs = enum_values[0] - for expr in enum_values[1:]: - inner_lhs = BinaryOperation(inner_lhs, expr, inner_op) - conditions.append(inner_lhs) - print(conditions) - return BinaryOperation(lhs, conditions[0], outer_op) + rhs = parse_expression(expression.right, caller_context) + print(rhs) + print(rhs.__class__.__name__) + if isinstance(rhs, Identifier): + if isinstance(rhs.value.type, ArrayType): + inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") + + enum_members = rhs.value.type.length_value.value + for i in range(enum_members): + elem_expr = IndexAccess(rhs, Literal(str(i), ElementaryType("uint256"))) + elem_expr.set_offset(rhs.source_mapping, caller_context.compilation_unit) + parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) + parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) + conditions.append(parsed_expr) + # elif isinstance(rhs.value.type, UserDefinedType): + + else: + assert False + else: + # This is an indexaccess like hashmap[address, Roles] + inner_op = BinaryOperationType.get_type("|") #if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type("&") #if expression.op == "NotIn" else BinaryOperationType.get_type("||") + + # x, _ = find_variable(expression.right.value.attr, caller_context) + # print(x) + # print(x.type.type_to) + # print(x.type.type_to.__class__) + print(repr(rhs)) + print(rhs) + + enum_members = rhs.expression_left.value.type.type_to.type.values + # for each value, create a literal with value = 2 ^ n (0 indexed) + # and then translate to bitmasking + enum_values = [Literal(str(2 ** n), ElementaryType("uint256")) for n in range(len(enum_members))] + inner_lhs = enum_values[0] + for expr in enum_values[1:]: + inner_lhs = BinaryOperation(inner_lhs, expr, inner_op) + conditions.append(inner_lhs) + + parsed_expr = BinaryOperation(lhs, conditions[0], outer_op) + parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) + return parsed_expr + + while len(conditions) > 1: lhs = conditions.pop() @@ -470,16 +542,20 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else: rhs = parse_expression(expression.right, caller_context) - - op = BinaryOperationType.get_type(expression.op) - return BinaryOperation(lhs, rhs, op) + op = BinaryOperationType.get_type(expression.op) + + parsed_expr = BinaryOperation(lhs, rhs, op) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, BinOp): lhs = parse_expression(expression.left, caller_context) rhs = parse_expression(expression.right, caller_context) op = BinaryOperationType.get_type(expression.op) - return BinaryOperation(lhs, rhs, op) + parsed_expr = BinaryOperation(lhs, rhs, op) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, Assert): # Treat assert the same as a Solidity `require`. @@ -492,20 +568,24 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": func = SolidityFunction("require(bool,string)") args = [parse_expression(expression.test, caller_context), parse_expression(expression.msg, caller_context)] - return CallExpression(Identifier(func), args, type_str) + parsed_expr = CallExpression(Identifier(func), args, type_str) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, Subscript): left_expression = parse_expression(expression.value, caller_context) right_expression = parse_expression(expression.slice.value, caller_context) - index = IndexAccess(left_expression, right_expression) - # index.set_offset(src, caller_context.compilation_unit) - return index + parsed_expr = IndexAccess(left_expression, right_expression) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, BoolOp): lhs = parse_expression(expression.values[0], caller_context) rhs = parse_expression(expression.values[1], caller_context) # op = BinaryOperationType.get_type(expression.op) TODO update BoolOp AST - return BinaryOperation(lhs, rhs,BinaryOperationType.ANDAND) + parsed_expr = BinaryOperation(lhs, rhs,BinaryOperationType.ANDAND) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr raise ParsingError(f"Expression not parsed {expression}") From 011c03a3de1f3b69437c9d2ea7e81ec96e4f4371 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 15:33:59 -0500 Subject: [PATCH 180/338] control flow graph (loops and ifs) --- .../vyper_parsing/declarations/function.py | 147 +++++++++++------- 1 file changed, 90 insertions(+), 57 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index d1b075864..db32ac6ad 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -63,7 +63,7 @@ class FunctionVyper: self._params_was_analyzed = False self._content_was_analyzed = False - # self._counter_scope_local_variables = 0 + self._counter_scope_local_variables = 0 # # variable renamed will map the solc id # # to the variable. It only works for compact format # # Later if an expression provides the referencedDeclaration attr @@ -113,14 +113,14 @@ class FunctionVyper: # Use of while in case of collision # In the worst case, the name will be really long # TODO no shadowing? - # if local_var_parser.underlying_variable.name: - # known_variables = [v.name for v in self._function.variables] - # while local_var_parser.underlying_variable.name in known_variables: - # local_var_parser.underlying_variable.name += ( - # f"_scope_{self._counter_scope_local_variables}" - # ) - # self._counter_scope_local_variables += 1 - # known_variables = [v.name for v in self._function.variables] + if local_var_parser.underlying_variable.name: + known_variables = [v.name for v in self._function.variables] + while local_var_parser.underlying_variable.name in known_variables: + local_var_parser.underlying_variable.name += ( + f"_scope_{self._counter_scope_local_variables}" + ) + self._counter_scope_local_variables += 1 + known_variables = [v.name for v in self._function.variables] # TODO no reference ID # if local_var_parser.reference_id is not None: # self._variables_renamed[local_var_parser.reference_id] = local_var_parser @@ -207,12 +207,13 @@ class FunctionVyper: def _parse_cfg(self, cfg: Dict) -> None: - curr_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) - self._function.entry_point = curr_node.underlying_node + entry_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) + self._function.entry_point = entry_node.underlying_node scope = Scope(True, False, self.underlying_function) if cfg: self._function.is_empty = False + curr_node = entry_node for expr in cfg: def parse_statement(curr_node, expr): if isinstance(expr, AnnAssign): @@ -237,6 +238,9 @@ class FunctionVyper: new_node.add_unparsed_expression(expr) link_underlying_nodes(curr_node, new_node) + curr_node = new_node + + # elif isinstance(expr, Assign): # new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) # new_node.add_unparsed_expression(expr.target) @@ -246,6 +250,7 @@ class FunctionVyper: elif isinstance(expr, For): node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + link_underlying_nodes(curr_node, node_startLoop) local_var = LocalVariable() local_var.set_function(self._function) @@ -254,19 +259,22 @@ class FunctionVyper: counter_var = AnnAssign(expr.target.src, expr.target.node_id, target=Name("-1:-1:-1", -1, "counter_var"), annotation=Name("-1:-1:-1", -1, "uint256"), value=Int("-1:-1:-1", -1, 0)) local_var_parser = LocalVariableVyper(local_var, counter_var) self._add_local_variable(local_var_parser) - new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) local_var.initialized = True - new_node.add_unparsed_expression(counter_var.value) - new_node.underlying_node.add_variable_declaration(local_var) + counter_node.add_unparsed_expression(counter_var.value) + counter_node.underlying_node.add_variable_declaration(local_var) + link_underlying_nodes(node_startLoop, counter_node) + + node_condition = None if isinstance(expr.iter, (Attribute,Name)): # HACK # The loop variable is not annotated so we infer its type by looking at the type of the iterator - if isinstance(expr.iter, Attribute): # state + if isinstance(expr.iter, Attribute): # state variable iter_expr = expr.iter loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.attr, self._contract_parser._variables_parser))[0] - else: # local + else: # local variable iter_expr = expr.iter loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.id, self._local_variables_parser))[0] @@ -275,7 +283,7 @@ class FunctionVyper: node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) node_condition.add_unparsed_expression(cond_expr) - # TODO this should go in the body of the loop: expr.body.insert(0, ...) + if loop_iterator._elem_to_parse.value.id == "DynArray": loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] else: @@ -283,74 +291,99 @@ class FunctionVyper: value = Subscript("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, loop_iterator._variable.name), slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var"))) loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=loop_var_annotation, value=value) - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) - local_var_parser = LocalVariableVyper(local_var, loop_var) - self._add_local_variable(local_var_parser) - new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - local_var.initialized = True - new_node.add_unparsed_expression(loop_var.value) - new_node.underlying_node.add_variable_declaration(local_var) - elif isinstance(expr.iter, Call): + elif isinstance(expr.iter, Call): # range range_val = expr.iter.args[0] cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=range_val) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=Name("-1:-1:-1", -1, "uint256"), value=Name("-1:-1:-1", -1, "counter_var")) - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) - local_var_parser = LocalVariableVyper(local_var, loop_var) - self._add_local_variable(local_var_parser) - new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - local_var.initialized = True - new_node.add_unparsed_expression(loop_var.value) - new_node.underlying_node.add_variable_declaration(local_var) + else: - print(expr) raise NotImplementedError - # assert False - node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) - - - - # link_underlying_nodes(node_startLoop, node_condition) + + # link + link_underlying_nodes(counter_node, node_condition) + + + # We update the index variable or range variable in the loop body + expr.body.insert(0, loop_var) + body_node = None + new_node = node_condition for stmt in expr.body: - parse_statement(curr_node, stmt) - - # link_underlying_nodes(curr_node, new_node) + body_node = parse_statement(new_node, stmt) + new_node = body_node + + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + + loop_increment = AugAssign("-1:-1:-1", -1, target=Name("-1:-1:-1", -1, "counter_var"), op="+=", value=Int("-1:-1:-1", -1, 1)) + node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) + node_increment.add_unparsed_expression(loop_increment) + link_underlying_nodes(node_increment, node_condition) + + if body_node is not None: + link_underlying_nodes(body_node, node_increment) + + link_underlying_nodes(node_condition, node_endLoop) + + curr_node = node_endLoop elif isinstance(expr, Continue): pass elif isinstance(expr, Break): pass elif isinstance(expr, Return): - node_parser = self._new_node(NodeType.RETURN, expr.src, scope) + new_node = self._new_node(NodeType.RETURN, expr.src, scope) if expr.value is not None: - node_parser.add_unparsed_expression(expr.value) + new_node.add_unparsed_expression(expr.value) + + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - pass elif isinstance(expr, Assert): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) new_node.add_unparsed_expression(expr) - + link_underlying_nodes(curr_node, new_node) + curr_node = new_node elif isinstance(expr, Log): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) new_node.add_unparsed_expression(expr.value) - pass + + link_underlying_nodes(curr_node, new_node) + curr_node = new_node + elif isinstance(expr, If): - new_node = self._new_node(NodeType.IF, expr.test.src, scope) - new_node.add_unparsed_expression(expr.test) + condition_node = self._new_node(NodeType.IF, expr.test.src, scope) + condition_node.add_unparsed_expression(expr.test) + + endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) + true_node = None + new_node = condition_node for stmt in expr.body: - parse_statement(new_node, stmt) - + true_node = parse_statement(new_node, stmt) + new_node = true_node + # link_underlying_nodes(condition_node, true_node) + link_underlying_nodes(true_node, endIf_node) + + false_node = None + new_node = condition_node for stmt in expr.orelse: - parse_statement(new_node, stmt) + false_node = parse_statement(new_node, stmt) + new_node = false_node + + if false_node is not None: + # link_underlying_nodes(condition_node, false_node) + link_underlying_nodes(false_node, endIf_node) + + else: + link_underlying_nodes(condition_node, endIf_node) + + link_underlying_nodes(curr_node, condition_node) + curr_node = endIf_node - pass elif isinstance(expr, Expr): pass elif isinstance(expr, Pass): From 6bd52fac0edfa1fa406c563e3bb92335c14f13f6 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 15:34:25 -0500 Subject: [PATCH 181/338] more builtins --- slither/core/declarations/solidity_variables.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 85844508e..ec8321ee5 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -108,9 +108,10 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "max()":[], "shift()":[], "abs()":[], - "raw_call()":[], + "raw_call()":["bool", "bytes32"], "_abi_encode()":[], "slice()":[], + "uint2str()":["string"], } From 5443132c2b3151c39d0e602fa24af0a607cee38a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 16:20:21 -0500 Subject: [PATCH 182/338] fix source mapping, set source code and source unit --- slither/vyper_parsing/vyper_compilation_unit.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index f8a2ca216..f43d85d00 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -1,12 +1,12 @@ from typing import Dict +import os +import re from dataclasses import dataclass, field from slither.core.declarations import Contract from slither.core.compilation_unit import SlitherCompilationUnit from slither.vyper_parsing.declarations.contract import ContractVyper from slither.analyses.data_dependency.data_dependency import compute_dependency -from slither.vyper_parsing.declarations.struct import Structure -from slither.core.variables.state_variable import StateVariable - +from slither.vyper_parsing.ast.types import Module from slither.exceptions import SlitherException @@ -18,7 +18,16 @@ class VyperCompilationUnit: _underlying_contract_to_parser: Dict[Contract, ContractVyper] = field(default_factory=dict) _contracts_by_id: Dict[int, Contract] = field(default_factory=dict) - def parse_module(self, data: Dict, filename: str): + def parse_module(self, data: Module, filename: str): + + sourceUnit_candidates = re.findall("[0-9]*:[0-9]*:([0-9]*)", data.src) + assert len(sourceUnit_candidates) == 1, "Source unit not found" + sourceUnit = int(sourceUnit_candidates[0]) + + self._compilation_unit.source_units[sourceUnit] = filename + if os.path.isfile(filename) and not filename in self._compilation_unit.core.source_code: + self._compilation_unit.core.add_source_code(filename) + scope = self._compilation_unit.get_scope(filename) contract = Contract(self._compilation_unit, scope) contract_parser = ContractVyper(self, contract, data) From a61ca34226cc14148a6eb647283f818e02f26acd Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 16:45:01 -0500 Subject: [PATCH 183/338] parse bool op symbol --- slither/vyper_parsing/ast/ast.py | 4 +++- slither/vyper_parsing/expressions/expression_parsing.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index ca748954a..5c7eb2489 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -316,10 +316,12 @@ def parse_aug_assign(raw: Dict) -> AugAssign: def parse_unsupported(raw: Dict) -> ASTNode: raise ParsingError("unsupported Vyper node", raw["ast_type"], raw.keys(), raw) +bool_op_ast_type_to_op_symbol = {"And": "&&", "Or": "||"} def parse_bool_op(raw: Dict) -> BoolOp: + op_str = bool_op_ast_type_to_op_symbol[raw["op"]["ast_type"]] return BoolOp( - op=raw["op"], values=[parse(x) for x in raw["values"]], **_extract_base_props(raw) + op=op_str, values=[parse(x) for x in raw["values"]], **_extract_base_props(raw) ) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 8ce757732..a84eacb2f 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -583,8 +583,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": lhs = parse_expression(expression.values[0], caller_context) rhs = parse_expression(expression.values[1], caller_context) - # op = BinaryOperationType.get_type(expression.op) TODO update BoolOp AST - parsed_expr = BinaryOperation(lhs, rhs,BinaryOperationType.ANDAND) + op = BinaryOperationType.get_type(expression.op) + parsed_expr = BinaryOperation(lhs, op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr From 4b07cbbc56ce0483cd5047ef489b19a7897fff37 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 20:07:57 -0500 Subject: [PATCH 184/338] add support for self.balance --- slither/core/declarations/solidity_variables.py | 1 + slither/vyper_parsing/expressions/expression_parsing.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index ec8321ee5..03fd81f04 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -39,6 +39,7 @@ SOLIDITY_VARIABLES_COMPOSED = { # Vyper "chain.id": "uint256", "block.prevhash": "bytes32", + "self.balance": "uint256", } diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index a84eacb2f..441c078ee 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -368,7 +368,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": member_name = expression.attr if isinstance(expression.value, Name): - if expression.value.id == "self": + if expression.value.id == "self" and member_name != "balance": var, was_created = find_variable(member_name, caller_context) # TODO replace with self if was_created: From db88cd5855b1dd7e97b9ea6374be9942c4723403 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 20:15:17 -0500 Subject: [PATCH 185/338] fmt --- slither/vyper_parsing/ast/ast.py | 57 ++++- slither/vyper_parsing/ast/types.py | 2 - .../vyper_parsing/declarations/contract.py | 231 +++++++++++++++++- .../vyper_parsing/declarations/function.py | 130 +++++++--- .../expressions/expression_parsing.py | 174 +++++++++---- .../expressions/find_variable.py | 9 +- slither/vyper_parsing/type_parsing.py | 10 +- .../vyper_parsing/variables/local_variable.py | 1 - .../vyper_parsing/variables/state_variable.py | 5 +- .../vyper_parsing/vyper_compilation_unit.py | 6 +- 10 files changed, 511 insertions(+), 114 deletions(-) diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index 5c7eb2489..228805c89 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -197,26 +197,56 @@ def parse_raise(raw: Dict) -> Raise: def parse_expr(raw: Dict) -> Expr: return Expr(value=parse(raw["value"]), **_extract_base_props(raw)) + # This is done for convenience so we can call `UnaryOperationType.get_type` during expression parsing. unop_ast_type_to_op_symbol = {"Not": "!", "USub": "-"} + def parse_unary_op(raw: Dict) -> UnaryOp: unop_str = unop_ast_type_to_op_symbol[raw["op"]["ast_type"]] return UnaryOp(op=unop_str, operand=parse(raw["operand"]), **_extract_base_props(raw)) + # This is done for convenience so we can call `BinaryOperationType.get_type` during expression parsing. -binop_ast_type_to_op_symbol = {"Add": "+", "Mult": "*", "Sub": "-", "Div": "/", "Pow": "**", "Mod": "%", "BitAnd": "&", "BitOr": "|", "Shr": "<<", "Shl": ">>", "NotEq": "!=", "Eq": "==", "LtE": "<=", "GtE": ">=", "Lt": "<", "Gt": ">", "In": "In", "NotIn": "NotIn"} +binop_ast_type_to_op_symbol = { + "Add": "+", + "Mult": "*", + "Sub": "-", + "Div": "/", + "Pow": "**", + "Mod": "%", + "BitAnd": "&", + "BitOr": "|", + "Shr": "<<", + "Shl": ">>", + "NotEq": "!=", + "Eq": "==", + "LtE": "<=", + "GtE": ">=", + "Lt": "<", + "Gt": ">", + "In": "In", + "NotIn": "NotIn", +} + def parse_bin_op(raw: Dict) -> BinOp: arith_op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] return BinOp( - left=parse(raw["left"]), op=arith_op_str, right=parse(raw["right"]), **_extract_base_props(raw) + left=parse(raw["left"]), + op=arith_op_str, + right=parse(raw["right"]), + **_extract_base_props(raw), ) + def parse_compare(raw: Dict) -> Compare: logical_op_str = binop_ast_type_to_op_symbol[raw["op"]["ast_type"]] return Compare( - left=parse(raw["left"]), op=logical_op_str, right=parse(raw["right"]), **_extract_base_props(raw) + left=parse(raw["left"]), + op=logical_op_str, + right=parse(raw["right"]), + **_extract_base_props(raw), ) @@ -301,7 +331,20 @@ def parse_enum_def(raw: Dict) -> EnumDef: return EnumDef(name=raw["name"], body=nodes_parsed, **_extract_base_props(raw)) -aug_assign_ast_type_to_op_symbol = {"Add": "+=", "Mult": "*=", "Sub": "-=", "Div": "-=", "Pow": "**=", "Mod": "%=", "BitAnd": "&=", "BitOr": "|=", "Shr": "<<=", "Shl": ">>="} + +aug_assign_ast_type_to_op_symbol = { + "Add": "+=", + "Mult": "*=", + "Sub": "-=", + "Div": "-=", + "Pow": "**=", + "Mod": "%=", + "BitAnd": "&=", + "BitOr": "|=", + "Shr": "<<=", + "Shl": ">>=", +} + def parse_aug_assign(raw: Dict) -> AugAssign: op_str = aug_assign_ast_type_to_op_symbol[raw["op"]["ast_type"]] @@ -316,13 +359,13 @@ def parse_aug_assign(raw: Dict) -> AugAssign: def parse_unsupported(raw: Dict) -> ASTNode: raise ParsingError("unsupported Vyper node", raw["ast_type"], raw.keys(), raw) + bool_op_ast_type_to_op_symbol = {"And": "&&", "Or": "||"} + def parse_bool_op(raw: Dict) -> BoolOp: op_str = bool_op_ast_type_to_op_symbol[raw["op"]["ast_type"]] - return BoolOp( - op=op_str, values=[parse(x) for x in raw["values"]], **_extract_base_props(raw) - ) + return BoolOp(op=op_str, values=[parse(x) for x in raw["values"]], **_extract_base_props(raw)) def parse(raw: Dict) -> ASTNode: diff --git a/slither/vyper_parsing/ast/types.py b/slither/vyper_parsing/ast/types.py index 619df4f14..e07e6d213 100644 --- a/slither/vyper_parsing/ast/types.py +++ b/slither/vyper_parsing/ast/types.py @@ -184,8 +184,6 @@ class UnaryOp(ASTNode): operand: ASTNode - - @dataclass class BinOp(ASTNode): left: ASTNode diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index fde720340..ed61bda1b 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -180,7 +180,236 @@ class ContractVyper: ), ], ), - "ERC20": InterfaceDef(src="-1:-1:-1", node_id=1, name='ERC20', body=[FunctionDef(src="-1:-1:-1", node_id=2, doc_string=None, name='totalSupply', args=Arguments(src="-1:-1:-1", node_id=3, args=[], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=7, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=4, value=Name(src="-1:-1:-1", node_id=5, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=9, doc_string=None, name='balanceOf', args=Arguments(src="-1:-1:-1", node_id=10, args=[Arg(src="-1:-1:-1", node_id=11, arg='_owner', annotation=Name(src="-1:-1:-1", node_id=12, id='address'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=17, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=14, value=Name(src="-1:-1:-1", node_id=15, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=19, doc_string=None, name='allowance', args=Arguments(src="-1:-1:-1", node_id=20, args=[Arg(src="-1:-1:-1", node_id=21, arg='_owner', annotation=Name(src="-1:-1:-1", node_id=22, id='address')), Arg(src="-1:-1:-1", node_id=24, arg='_spender', annotation=Name(src="-1:-1:-1", node_id=25, id='address'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=30, id='uint256'), body=[Expr(src="-1:-1:-1", node_id=27, value=Name(src="-1:-1:-1", node_id=28, id='view'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=32, doc_string=None, name='transfer', args=Arguments(src="-1:-1:-1", node_id=33, args=[Arg(src="-1:-1:-1", node_id=34, arg='_to', annotation=Name(src="-1:-1:-1", node_id=35, id='address')), Arg(src="-1:-1:-1", node_id=37, arg='_value', annotation=Name(src="-1:-1:-1", node_id=38, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=43, id='bool'), body=[Expr(src="-1:-1:-1", node_id=40, value=Name(src="-1:-1:-1", node_id=41, id='nonpayable'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=45, doc_string=None, name='transferFrom', args=Arguments(src="-1:-1:-1", node_id=46, args=[Arg(src="-1:-1:-1", node_id=47, arg='_from', annotation=Name(src="-1:-1:-1", node_id=48, id='address')), Arg(src="-1:-1:-1", node_id=50, arg='_to', annotation=Name(src="-1:-1:-1", node_id=51, id='address')), Arg(src="-1:-1:-1", node_id=53, arg='_value', annotation=Name(src="-1:-1:-1", node_id=54, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=59, id='bool'), body=[Expr(src="-1:-1:-1", node_id=56, value=Name(src="-1:-1:-1", node_id=57, id='nonpayable'))], decorators=[], pos=None), FunctionDef(src="-1:-1:-1", node_id=61, doc_string=None, name='approve', args=Arguments(src="-1:-1:-1", node_id=62, args=[Arg(src="-1:-1:-1", node_id=63, arg='_spender', annotation=Name(src="-1:-1:-1", node_id=64, id='address')), Arg(src="-1:-1:-1", node_id=66, arg='_value', annotation=Name(src="-1:-1:-1", node_id=67, id='uint256'))], default=None, defaults=[]), returns=Name(src="-1:-1:-1", node_id=72, id='bool'), body=[Expr(src="-1:-1:-1", node_id=69, value=Name(src="-1:-1:-1", node_id=70, id='nonpayable'))], decorators=[], pos=None)]), + "ERC20": InterfaceDef( + src="-1:-1:-1", + node_id=1, + name="ERC20", + body=[ + FunctionDef( + src="-1:-1:-1", + node_id=2, + doc_string=None, + name="totalSupply", + args=Arguments( + src="-1:-1:-1", + node_id=3, + args=[], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=7, id="uint256"), + body=[ + Expr( + src="-1:-1:-1", + node_id=4, + value=Name(src="-1:-1:-1", node_id=5, id="view"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=9, + doc_string=None, + name="balanceOf", + args=Arguments( + src="-1:-1:-1", + node_id=10, + args=[ + Arg( + src="-1:-1:-1", + node_id=11, + arg="_owner", + annotation=Name( + src="-1:-1:-1", node_id=12, id="address" + ), + ) + ], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=17, id="uint256"), + body=[ + Expr( + src="-1:-1:-1", + node_id=14, + value=Name(src="-1:-1:-1", node_id=15, id="view"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=19, + doc_string=None, + name="allowance", + args=Arguments( + src="-1:-1:-1", + node_id=20, + args=[ + Arg( + src="-1:-1:-1", + node_id=21, + arg="_owner", + annotation=Name( + src="-1:-1:-1", node_id=22, id="address" + ), + ), + Arg( + src="-1:-1:-1", + node_id=24, + arg="_spender", + annotation=Name( + src="-1:-1:-1", node_id=25, id="address" + ), + ), + ], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=30, id="uint256"), + body=[ + Expr( + src="-1:-1:-1", + node_id=27, + value=Name(src="-1:-1:-1", node_id=28, id="view"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=32, + doc_string=None, + name="transfer", + args=Arguments( + src="-1:-1:-1", + node_id=33, + args=[ + Arg( + src="-1:-1:-1", + node_id=34, + arg="_to", + annotation=Name( + src="-1:-1:-1", node_id=35, id="address" + ), + ), + Arg( + src="-1:-1:-1", + node_id=37, + arg="_value", + annotation=Name( + src="-1:-1:-1", node_id=38, id="uint256" + ), + ), + ], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=43, id="bool"), + body=[ + Expr( + src="-1:-1:-1", + node_id=40, + value=Name(src="-1:-1:-1", node_id=41, id="nonpayable"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=45, + doc_string=None, + name="transferFrom", + args=Arguments( + src="-1:-1:-1", + node_id=46, + args=[ + Arg( + src="-1:-1:-1", + node_id=47, + arg="_from", + annotation=Name( + src="-1:-1:-1", node_id=48, id="address" + ), + ), + Arg( + src="-1:-1:-1", + node_id=50, + arg="_to", + annotation=Name( + src="-1:-1:-1", node_id=51, id="address" + ), + ), + Arg( + src="-1:-1:-1", + node_id=53, + arg="_value", + annotation=Name( + src="-1:-1:-1", node_id=54, id="uint256" + ), + ), + ], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=59, id="bool"), + body=[ + Expr( + src="-1:-1:-1", + node_id=56, + value=Name(src="-1:-1:-1", node_id=57, id="nonpayable"), + ) + ], + decorators=[], + pos=None, + ), + FunctionDef( + src="-1:-1:-1", + node_id=61, + doc_string=None, + name="approve", + args=Arguments( + src="-1:-1:-1", + node_id=62, + args=[ + Arg( + src="-1:-1:-1", + node_id=63, + arg="_spender", + annotation=Name( + src="-1:-1:-1", node_id=64, id="address" + ), + ), + Arg( + src="-1:-1:-1", + node_id=66, + arg="_value", + annotation=Name( + src="-1:-1:-1", node_id=67, id="uint256" + ), + ), + ], + default=None, + defaults=[], + ), + returns=Name(src="-1:-1:-1", node_id=72, id="bool"), + body=[ + Expr( + src="-1:-1:-1", + node_id=69, + value=Name(src="-1:-1:-1", node_id=70, id="nonpayable"), + ) + ], + decorators=[], + pos=None, + ), + ], + ), "ERC165": [], "ERC721": [], "ERC4626": [], diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index db32ac6ad..9e57b6c66 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -180,8 +180,6 @@ class FunctionVyper: for node_parser in self._node_to_NodeVyper.values(): node_parser.analyze_expressions(self._function) - - # endregion ################################################################################### ################################################################################### @@ -206,7 +204,6 @@ class FunctionVyper: def _parse_cfg(self, cfg: Dict) -> None: - entry_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) self._function.entry_point = entry_node.underlying_node scope = Scope(True, False, self.underlying_function) @@ -215,6 +212,7 @@ class FunctionVyper: self._function.is_empty = False curr_node = entry_node for expr in cfg: + def parse_statement(curr_node, expr): if isinstance(expr, AnnAssign): local_var = LocalVariable() @@ -240,7 +238,6 @@ class FunctionVyper: curr_node = new_node - # elif isinstance(expr, Assign): # new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) # new_node.add_unparsed_expression(expr.target) @@ -256,7 +253,13 @@ class FunctionVyper: local_var.set_function(self._function) local_var.set_offset(expr.src, self._function.compilation_unit) - counter_var = AnnAssign(expr.target.src, expr.target.node_id, target=Name("-1:-1:-1", -1, "counter_var"), annotation=Name("-1:-1:-1", -1, "uint256"), value=Int("-1:-1:-1", -1, 0)) + counter_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=Name("-1:-1:-1", -1, "counter_var"), + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Int("-1:-1:-1", -1, 0), + ) local_var_parser = LocalVariableVyper(local_var, counter_var) self._add_local_variable(local_var_parser) counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) @@ -267,45 +270,93 @@ class FunctionVyper: link_underlying_nodes(node_startLoop, counter_node) node_condition = None - if isinstance(expr.iter, (Attribute,Name)): - # HACK + if isinstance(expr.iter, (Attribute, Name)): + # HACK # The loop variable is not annotated so we infer its type by looking at the type of the iterator - if isinstance(expr.iter, Attribute): # state variable + if isinstance(expr.iter, Attribute): # state variable iter_expr = expr.iter - loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.attr, self._contract_parser._variables_parser))[0] - - else: # local variable + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.attr, + self._contract_parser._variables_parser, + ) + )[0] + + else: # local variable iter_expr = expr.iter - loop_iterator = list(filter(lambda x: x._variable.name == iter_expr.id, self._local_variables_parser))[0] + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.id, + self._local_variables_parser, + ) + )[0] # TODO use expr.src instead of -1:-1:1? - cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=Call("-1:-1:-1", -1, func=Name("-1:-1:-1", -1, "len"), args=[iter_expr], keywords=[], keyword=None)) + cond_expr = Compare( + "-1:-1:-1", + -1, + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=Call( + "-1:-1:-1", + -1, + func=Name("-1:-1:-1", -1, "len"), + args=[iter_expr], + keywords=[], + keyword=None, + ), + ) node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) node_condition.add_unparsed_expression(cond_expr) - if loop_iterator._elem_to_parse.value.id == "DynArray": - loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] + loop_var_annotation = ( + loop_iterator._elem_to_parse.slice.value.elements[0] + ) else: loop_var_annotation = loop_iterator._elem_to_parse.value - value = Subscript("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, loop_iterator._variable.name), slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var"))) - loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=loop_var_annotation, value=value) - - elif isinstance(expr.iter, Call): # range + value = Subscript( + "-1:-1:-1", + -1, + value=Name("-1:-1:-1", -1, loop_iterator._variable.name), + slice=Index( + "-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var") + ), + ) + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=loop_var_annotation, + value=value, + ) + + elif isinstance(expr.iter, Call): # range range_val = expr.iter.args[0] - cond_expr = Compare("-1:-1:-1", -1, left=Name("-1:-1:-1", -1, "counter_var"), op="<=", right=range_val) + cond_expr = Compare( + "-1:-1:-1", + -1, + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=range_val, + ) node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) node_condition.add_unparsed_expression(cond_expr) - loop_var = AnnAssign(expr.target.src, expr.target.node_id, target=expr.target, annotation=Name("-1:-1:-1", -1, "uint256"), value=Name("-1:-1:-1", -1, "counter_var")) - + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Name("-1:-1:-1", -1, "counter_var"), + ) + else: raise NotImplementedError - - # link + + # link link_underlying_nodes(counter_node, node_condition) - # We update the index variable or range variable in the loop body expr.body.insert(0, loop_var) body_node = None @@ -313,17 +364,23 @@ class FunctionVyper: for stmt in expr.body: body_node = parse_statement(new_node, stmt) new_node = body_node - + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) - - loop_increment = AugAssign("-1:-1:-1", -1, target=Name("-1:-1:-1", -1, "counter_var"), op="+=", value=Int("-1:-1:-1", -1, 1)) + + loop_increment = AugAssign( + "-1:-1:-1", + -1, + target=Name("-1:-1:-1", -1, "counter_var"), + op="+=", + value=Int("-1:-1:-1", -1, 1), + ) node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) node_increment.add_unparsed_expression(loop_increment) link_underlying_nodes(node_increment, node_condition) - + if body_node is not None: link_underlying_nodes(body_node, node_increment) - + link_underlying_nodes(node_condition, node_endLoop) curr_node = node_endLoop @@ -357,8 +414,8 @@ class FunctionVyper: elif isinstance(expr, If): condition_node = self._new_node(NodeType.IF, expr.test.src, scope) condition_node.add_unparsed_expression(expr.test) - - endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) + + endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) true_node = None new_node = condition_node @@ -367,20 +424,20 @@ class FunctionVyper: new_node = true_node # link_underlying_nodes(condition_node, true_node) link_underlying_nodes(true_node, endIf_node) - + false_node = None new_node = condition_node for stmt in expr.orelse: false_node = parse_statement(new_node, stmt) new_node = false_node - + if false_node is not None: # link_underlying_nodes(condition_node, false_node) link_underlying_nodes(false_node, endIf_node) else: link_underlying_nodes(condition_node, endIf_node) - + link_underlying_nodes(curr_node, condition_node) curr_node = endIf_node @@ -396,6 +453,7 @@ class FunctionVyper: print(f"isinstance(expr, {expr.__class__.__name__})") assert False return curr_node + curr_node = parse_statement(curr_node, expr) # self._parse_block(cfg, node, self.underlying_function) else: @@ -437,7 +495,7 @@ class FunctionVyper: print(returns) self._function.returns_src().set_offset(returns.src, self._function.compilation_unit) # Only the type of the arg is given, not a name. We create an an `Arg` with an empty name - # so that the function has the correct return type in its signature but doesn't clash with + # so that the function has the correct return type in its signature but doesn't clash with # other identifiers during name resolution (`find_variable`). if isinstance(returns, (Name, Subscript)): local_var = self._add_param(Arg(returns.src, returns.node_id, "", annotation=returns)) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 441c078ee..326fe2c75 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -254,7 +254,28 @@ def _user_defined_op_call( from collections import deque -from slither.vyper_parsing.ast.types import Int, Call, Attribute, Name, Tuple, Hex, BinOp, Str, Assert, Compare, UnaryOp, Subscript, NameConstant, VyDict, Bytes, BoolOp, Assign, AugAssign, VyList +from slither.vyper_parsing.ast.types import ( + Int, + Call, + Attribute, + Name, + Tuple, + Hex, + BinOp, + Str, + Assert, + Compare, + UnaryOp, + Subscript, + NameConstant, + VyDict, + Bytes, + BoolOp, + Assign, + AugAssign, + VyList, +) + def parse_expression(expression: Dict, caller_context) -> "Expression": print("parse_expression") @@ -265,18 +286,18 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": literal = Literal(str(expression.value), ElementaryType("uint256")) literal.set_offset(expression.src, caller_context.compilation_unit) return literal - + if isinstance(expression, Hex): # TODO this is an implicit conversion and could potentially be bytes20 or other? - literal = Literal(str(expression.value), ElementaryType("address")) + literal = Literal(str(expression.value), ElementaryType("address")) literal.set_offset(expression.src, caller_context.compilation_unit) return literal - + if isinstance(expression, Str): - literal = Literal(str(expression.value), ElementaryType("string")) + literal = Literal(str(expression.value), ElementaryType("string")) literal.set_offset(expression.src, caller_context.compilation_unit) return literal - + if isinstance(expression, Bytes): literal = Literal(str(expression.value), ElementaryType("bytes")) literal.set_offset(expression.src, caller_context.compilation_unit) @@ -287,7 +308,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": literal = Literal(str(expression.value), ElementaryType("bool")) literal.set_offset(expression.src, caller_context.compilation_unit) return literal - + if isinstance(expression, Call): called = parse_expression(expression.func, caller_context) @@ -297,29 +318,44 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = CallExpression(called, [], str(type_to)) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + elif called.value.name == "convert()": - arg = parse_expression(expression.args[0], caller_context) + arg = parse_expression(expression.args[0], caller_context) type_to = parse_type(expression.args[1], caller_context) parsed_expr = TypeConversion(arg, type_to) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - elif called.value.name== "min_value()": + elif called.value.name == "min_value()": type_to = parse_type(expression.args[0], caller_context) - member_type = str(type_to) + member_type = str(type_to) # TODO return Literal - parsed_expr = MemberAccess("min", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + parsed_expr = MemberAccess( + "min", + member_type, + CallExpression( + Identifier(SolidityFunction("type()")), + [ElementaryTypeNameExpression(type_to)], + member_type, + ), + ) return parsed_expr - - elif called.value.name== "max_value()": + + elif called.value.name == "max_value()": type_to = parse_type(expression.args[0], caller_context) - member_type = str(type_to) + member_type = str(type_to) # TODO return Literal - parsed_expr = MemberAccess("max", member_type, CallExpression(Identifier(SolidityFunction("type()")), [ElementaryTypeNameExpression(type_to)], member_type)) + parsed_expr = MemberAccess( + "max", + member_type, + CallExpression( + Identifier(SolidityFunction("type()")), + [ElementaryTypeNameExpression(type_to)], + member_type, + ), + ) return parsed_expr - if expression.args and isinstance(expression.args[0], VyDict): arguments = [] for val in expression.args[0].values: @@ -342,7 +378,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = TypeConversion(arguments[0], type_to) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + else: rets = ["tuple()"] @@ -352,23 +388,28 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": rets = [called.type] else: rets = ["tuple()"] - + def get_type_str(x): if isinstance(x, str): return x return str(x.type) + print(rets) - type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" + type_str = ( + get_type_str(rets[0]) + if len(rets) == 1 + else f"tuple({','.join(map(get_type_str, rets))})" + ) parsed_expr = CallExpression(called, arguments, type_str) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, Attribute): member_name = expression.attr if isinstance(expression.value, Name): - if expression.value.id == "self" and member_name != "balance": + if expression.value.id == "self" and member_name != "balance": var, was_created = find_variable(member_name, caller_context) # TODO replace with self if was_created: @@ -376,7 +417,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = SuperIdentifier(var) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + expr = parse_expression(expression.value, caller_context) # TODO this is ambiguous because it could be a type conversion of an interface or a member access if expression.attr == "address": @@ -385,7 +426,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return parsed_expr member_access = MemberAccess(member_name, None, expr) - + if str(member_access) in SOLIDITY_VARIABLES_COMPOSED: parsed_expr = Identifier(SolidityVariableComposed(str(member_access))) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) @@ -395,23 +436,28 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": expr = parse_expression(expression.value, caller_context) member_name_ret_type = None # (recover_type_1) This may be a call to an interface and we don't have the return types, - # so we see if there's a function identifier with `member_name` and propagate the type to + # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` # TODO this is using the wrong caller_context and needs to be interface instead of self namespace print(expr) print(expr.__class__.__name__) if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType): - # try: + # try: var, was_created = find_variable(member_name, expr.type.type) if isinstance(var, Function): rets = var.returns + def get_type_str(x): if isinstance(x, str): return x return str(x.type) - type_str = get_type_str(rets[0]) if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" + type_str = ( + get_type_str(rets[0]) + if len(rets) == 1 + else f"tuple({','.join(map(get_type_str, rets))})" + ) member_name_ret_type = type_str # except: # pass @@ -428,14 +474,14 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = Identifier(var) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, Assign): lhs = parse_expression(expression.target, caller_context) rhs = parse_expression(expression.value, caller_context) parsed_expr = AssignmentOperation(lhs, rhs, AssignmentOperationType.ASSIGN, None) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, AugAssign): lhs = parse_expression(expression.target, caller_context) rhs = parse_expression(expression.value, caller_context) @@ -450,10 +496,12 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = TupleExpression(tuple_vars) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, UnaryOp): operand = parse_expression(expression.operand, caller_context) - op = UnaryOperationType.get_type(expression.op, isprefix=True) #TODO does vyper have postfix? + op = UnaryOperationType.get_type( + expression.op, isprefix=True + ) # TODO does vyper have postfix? parsed_expr = UnaryOperation(operand, op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) @@ -476,9 +524,17 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # We assume left operand in membership comparison cannot be Array type conditions = deque() if isinstance(expression.right, VyList): - inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") - + inner_op = ( + BinaryOperationType.get_type("!=") + if expression.op == "NotIn" + else BinaryOperationType.get_type("==") + ) + outer_op = ( + BinaryOperationType.get_type("&&") + if expression.op == "NotIn" + else BinaryOperationType.get_type("||") + ) + for elem in expression.right.elements: elem_expr = parse_expression(elem, caller_context) print("elem", repr(elem_expr)) @@ -491,15 +547,27 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": print(rhs.__class__.__name__) if isinstance(rhs, Identifier): if isinstance(rhs.value.type, ArrayType): - inner_op = BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") - + inner_op = ( + BinaryOperationType.get_type("!=") + if expression.op == "NotIn" + else BinaryOperationType.get_type("==") + ) + outer_op = ( + BinaryOperationType.get_type("&&") + if expression.op == "NotIn" + else BinaryOperationType.get_type("||") + ) + enum_members = rhs.value.type.length_value.value for i in range(enum_members): elem_expr = IndexAccess(rhs, Literal(str(i), ElementaryType("uint256"))) - elem_expr.set_offset(rhs.source_mapping, caller_context.compilation_unit) + elem_expr.set_offset( + rhs.source_mapping, caller_context.compilation_unit + ) parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) - parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) + parsed_expr.set_offset( + lhs.source_mapping, caller_context.compilation_unit + ) conditions.append(parsed_expr) # elif isinstance(rhs.value.type, UserDefinedType): @@ -507,8 +575,12 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": assert False else: # This is an indexaccess like hashmap[address, Roles] - inner_op = BinaryOperationType.get_type("|") #if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type("&") #if expression.op == "NotIn" else BinaryOperationType.get_type("||") + inner_op = BinaryOperationType.get_type( + "|" + ) # if expression.op == "NotIn" else BinaryOperationType.get_type("==") + outer_op = BinaryOperationType.get_type( + "&" + ) # if expression.op == "NotIn" else BinaryOperationType.get_type("||") # x, _ = find_variable(expression.right.value.attr, caller_context) # print(x) @@ -520,7 +592,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": enum_members = rhs.expression_left.value.type.type_to.type.values # for each value, create a literal with value = 2 ^ n (0 indexed) # and then translate to bitmasking - enum_values = [Literal(str(2 ** n), ElementaryType("uint256")) for n in range(len(enum_members))] + enum_values = [ + Literal(str(2**n), ElementaryType("uint256")) + for n in range(len(enum_members)) + ] inner_lhs = enum_values[0] for expr in enum_values[1:]: inner_lhs = BinaryOperation(inner_lhs, expr, inner_op) @@ -530,8 +605,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) return parsed_expr - - while len(conditions) > 1: lhs = conditions.pop() rhs = conditions.pop() @@ -543,7 +616,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else: rhs = parse_expression(expression.right, caller_context) op = BinaryOperationType.get_type(expression.op) - + parsed_expr = BinaryOperation(lhs, rhs, op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -556,7 +629,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = BinaryOperation(lhs, rhs, op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, Assert): # Treat assert the same as a Solidity `require`. # TODO rename from `SolidityFunction` to `Builtin`? @@ -566,19 +639,22 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": args = [parse_expression(expression.test, caller_context)] else: func = SolidityFunction("require(bool,string)") - args = [parse_expression(expression.test, caller_context), parse_expression(expression.msg, caller_context)] + args = [ + parse_expression(expression.test, caller_context), + parse_expression(expression.msg, caller_context), + ] parsed_expr = CallExpression(Identifier(func), args, type_str) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, Subscript): left_expression = parse_expression(expression.value, caller_context) right_expression = parse_expression(expression.slice.value, caller_context) parsed_expr = IndexAccess(left_expression, right_expression) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - + if isinstance(expression, BoolOp): lhs = parse_expression(expression.values[0], caller_context) rhs = parse_expression(expression.values[1], caller_context) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index b75b688db..1c6058c1a 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -36,7 +36,6 @@ if TYPE_CHECKING: # CallerContext =Union["ContractSolc", "FunctionSolc", "CustomErrorSolc", "StructureTopLevelSolc"] - def _find_variable_in_function_parser( var_name: str, function_parser: Optional["FunctionSolc"], @@ -51,8 +50,6 @@ def _find_variable_in_function_parser( return None - - def _find_in_contract( var_name: str, contract: Optional[Contract], @@ -67,8 +64,6 @@ def _find_in_contract( if var_name in contract_variables: return contract_variables[var_name] - - functions = {f.name: f for f in contract.functions if not f.is_shadowed} # print(functions) if var_name in functions: @@ -106,7 +101,6 @@ def _find_in_contract( if var_name in enums: return enums[var_name] - return None @@ -157,6 +151,7 @@ def find_variable( # structure/enums cannot be shadowed from slither.vyper_parsing.declarations.contract import ContractVyper from slither.vyper_parsing.declarations.function import FunctionVyper + print("caller_context") print(caller_context) print(caller_context.__class__.__name__) @@ -208,5 +203,5 @@ def find_variable( print(next_context.events_as_dict) if f"{var_name}()" in next_context.events_as_dict: return next_context.events_as_dict[f"{var_name}()"], False - + raise VariableNotFound(f"Variable not found: {var_name} (context {caller_context})") diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index 15fc16df6..a7d83240e 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -11,11 +11,12 @@ from slither.core.solidity_types.user_defined_type import UserDefinedType from slither.core.declarations.function_contract import FunctionContract + def parse_type(annotation: Union[Name, Subscript, Call], caller_context): from slither.vyper_parsing.expressions.expression_parsing import parse_expression if isinstance(caller_context, FunctionContract): - contract = caller_context.contract + contract = caller_context.contract else: contract = caller_context @@ -41,17 +42,16 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): elif isinstance(annotation.value, Subscript): type_ = parse_type(annotation.value, caller_context) - + elif isinstance(annotation.value, Name): # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression, so we grab the value. # Subscript(src='13:10:0', node_id=7, value=Name(src='13:6:0', node_id=8, id='String'), slice=Index(src='13:10:0', node_id=12, value=Int(src='20:2:0', node_id=10, value=64))) type_ = parse_type(annotation.value, caller_context) if annotation.value.id == "String": return type_ - + length = parse_expression(annotation.slice.value, caller_context) return ArrayType(type_, length) - elif isinstance(annotation, Call): return parse_type(annotation.args[0], caller_context) @@ -63,8 +63,6 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): if lname in ElementaryTypeName: return ElementaryType(lname) - - if name in contract.structures_as_dict: return UserDefinedType(contract.structures_as_dict[name]) diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py index 3651b701f..d3bd0b055 100644 --- a/slither/vyper_parsing/variables/local_variable.py +++ b/slither/vyper_parsing/variables/local_variable.py @@ -27,7 +27,6 @@ class LocalVariableVyper: self._variable.set_location("default") - @property def underlying_variable(self) -> LocalVariable: return self._variable diff --git a/slither/vyper_parsing/variables/state_variable.py b/slither/vyper_parsing/variables/state_variable.py index f17a4132e..a2e925a6e 100644 --- a/slither/vyper_parsing/variables/state_variable.py +++ b/slither/vyper_parsing/variables/state_variable.py @@ -5,6 +5,7 @@ from slither.vyper_parsing.ast.types import VariableDecl from slither.vyper_parsing.type_parsing import parse_type from slither.vyper_parsing.expressions.expression_parsing import parse_expression + class StateVariableVyper: def __init__(self, variable: StateVariable, variable_data: VariableDecl) -> None: self._variable: StateVariable = variable @@ -16,7 +17,7 @@ class StateVariableVyper: if variable_data.value is not None: self._variable.initialized = True - self._initializedNotParsed = variable_data.value + self._initializedNotParsed = variable_data.value @property def underlying_variable(self) -> StateVariable: @@ -24,7 +25,7 @@ class StateVariableVyper: def analyze(self, contract) -> None: self._variable.type = parse_type(self._elem_to_parse, contract) - + if self._variable.initialized: self._variable.expression = parse_expression(self._initializedNotParsed, contract) self._initializedNotParsed = None diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index f43d85d00..88ff43d1e 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -51,9 +51,9 @@ class VyperCompilationUnit: def analyze_contracts(self) -> None: if not self._parsed: raise SlitherException("Parse the contract before running analyses") - + for contract, contract_parser in self._underlying_contract_to_parser.items(): - # State variables are analyzed for all contracts because interfaces may + # State variables are analyzed for all contracts because interfaces may # reference them, specifically, constants. contract_parser.analyze_state_variables() @@ -73,7 +73,7 @@ class VyperCompilationUnit: func.generate_slithir_and_analyze() contract.convert_expression_to_slithir_ssa() - + self._compilation_unit.propagate_function_calls() for contract in self._compilation_unit.contracts: contract.fix_phi() From 85e63c6ba5772a6c3aced61a5d95669c61edc320 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 20:21:40 -0500 Subject: [PATCH 186/338] rename fixture --- tests/conftest.py | 2 +- tests/unit/slithir/test_ssa_generation.py | 96 +++++++++++------------ 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 63fccfa12..1b9f44c52 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -59,7 +59,7 @@ def solc_binary_path(shared_directory): @pytest.fixture -def slither_from_source(solc_binary_path): +def slither_from_solidity_source(solc_binary_path): @contextmanager def inner(source_code: str, solc_version: str = "0.8.19"): """Yields a Slither instance using source_code string and solc_version. diff --git a/tests/unit/slithir/test_ssa_generation.py b/tests/unit/slithir/test_ssa_generation.py index 3c7e84973..6b1a1d102 100644 --- a/tests/unit/slithir/test_ssa_generation.py +++ b/tests/unit/slithir/test_ssa_generation.py @@ -283,7 +283,7 @@ def get_ssa_of_type(f: Union[Function, Node], ssatype) -> List[Operation]: return get_filtered_ssa(f, lambda ssanode: isinstance(ssanode, ssatype)) -def test_multi_write(slither_from_source) -> None: +def test_multi_write(slither_from_solidity_source) -> None: source = """ pragma solidity ^0.8.11; contract Test { @@ -293,11 +293,11 @@ def test_multi_write(slither_from_source) -> None: val = 3; } }""" - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) -def test_single_branch_phi(slither_from_source) -> None: +def test_single_branch_phi(slither_from_solidity_source) -> None: source = """ pragma solidity ^0.8.11; contract Test { @@ -309,11 +309,11 @@ def test_single_branch_phi(slither_from_source) -> None: } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) -def test_basic_phi(slither_from_source) -> None: +def test_basic_phi(slither_from_solidity_source) -> None: source = """ pragma solidity ^0.8.11; contract Test { @@ -327,11 +327,11 @@ def test_basic_phi(slither_from_source) -> None: } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) -def test_basic_loop_phi(slither_from_source) -> None: +def test_basic_loop_phi(slither_from_solidity_source) -> None: source = """ pragma solidity ^0.8.11; contract Test { @@ -343,12 +343,12 @@ def test_basic_loop_phi(slither_from_source) -> None: } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_phi_propagation_loop(slither_from_source): +def test_phi_propagation_loop(slither_from_solidity_source): source = """ pragma solidity ^0.8.11; contract Test { @@ -365,12 +365,12 @@ def test_phi_propagation_loop(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_free_function_properties(slither_from_source): +def test_free_function_properties(slither_from_solidity_source): source = """ pragma solidity ^0.8.11; @@ -388,11 +388,11 @@ def test_free_function_properties(slither_from_source): contract Test {} """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: verify_properties_hold(slither) -def test_ssa_inter_transactional(slither_from_source) -> None: +def test_ssa_inter_transactional(slither_from_solidity_source) -> None: source = """ pragma solidity ^0.8.11; contract A { @@ -412,7 +412,7 @@ def test_ssa_inter_transactional(slither_from_source) -> None: } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.contracts[0] variables = c.variables_as_dict funcs = c.available_functions_as_dict() @@ -435,7 +435,7 @@ def test_ssa_inter_transactional(slither_from_source) -> None: @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_ssa_phi_callbacks(slither_from_source): +def test_ssa_phi_callbacks(slither_from_solidity_source): source = """ pragma solidity ^0.8.11; contract A { @@ -463,7 +463,7 @@ def test_ssa_phi_callbacks(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("A")[0] _dump_functions(c) f = [x for x in c.functions if x.name == "use_a"][0] @@ -494,7 +494,7 @@ def test_ssa_phi_callbacks(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_storage_refers_to(slither_from_source): +def test_storage_refers_to(slither_from_solidity_source): """Test the storage aspects of the SSA IR When declaring a var as being storage, start tracking what storage it refers_to. @@ -523,7 +523,7 @@ def test_storage_refers_to(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.contracts[0] f = c.functions[0] @@ -563,7 +563,7 @@ def test_storage_refers_to(slither_from_source): @pytest.mark.skipif( not valid_version("0.4.0"), reason="Solidity version 0.4.0 not available on this platform" ) -def test_initial_version_exists_for_locals(slither_from_source): +def test_initial_version_exists_for_locals(slither_from_solidity_source): """ In solidity you can write statements such as uint a = a + 1, this test ensures that can be handled for local variables. @@ -575,7 +575,7 @@ def test_initial_version_exists_for_locals(slither_from_source): } } """ - with slither_from_source(src, "0.4.0") as slither: + with slither_from_solidity_source(src, "0.4.0") as slither: verify_properties_hold(slither) c = slither.contracts[0] f = c.functions[0] @@ -600,7 +600,7 @@ def test_initial_version_exists_for_locals(slither_from_source): @pytest.mark.skipif( not valid_version("0.4.0"), reason="Solidity version 0.4.0 not available on this platform" ) -def test_initial_version_exists_for_state_variables(slither_from_source): +def test_initial_version_exists_for_state_variables(slither_from_solidity_source): """ In solidity you can write statements such as uint a = a + 1, this test ensures that can be handled for state variables. @@ -610,7 +610,7 @@ def test_initial_version_exists_for_state_variables(slither_from_source): uint a = a + 1; } """ - with slither_from_source(src, "0.4.0") as slither: + with slither_from_solidity_source(src, "0.4.0") as slither: verify_properties_hold(slither) c = slither.contracts[0] f = c.functions[0] # There will be one artificial ctor function for the state vars @@ -637,7 +637,7 @@ def test_initial_version_exists_for_state_variables(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_initial_version_exists_for_state_variables_function_assign(slither_from_source): +def test_initial_version_exists_for_state_variables_function_assign(slither_from_solidity_source): """ In solidity you can write statements such as uint a = a + 1, this test ensures that can be handled for local variables. @@ -652,7 +652,7 @@ def test_initial_version_exists_for_state_variables_function_assign(slither_from } } """ - with slither_from_source(src) as slither: + with slither_from_solidity_source(src) as slither: verify_properties_hold(slither) c = slither.contracts[0] f, ctor = c.functions @@ -679,7 +679,7 @@ def test_initial_version_exists_for_state_variables_function_assign(slither_from @pytest.mark.skipif( not valid_version("0.4.0"), reason="Solidity version 0.4.0 not available on this platform" ) -def test_return_local_before_assign(slither_from_source): +def test_return_local_before_assign(slither_from_solidity_source): src = """ // this require solidity < 0.5 // a variable can be returned before declared. Ensure it can be @@ -694,7 +694,7 @@ def test_return_local_before_assign(slither_from_source): } } """ - with slither_from_source(src, "0.4.0") as slither: + with slither_from_solidity_source(src, "0.4.0") as slither: f = slither.contracts[0].functions[0] ret = get_ssa_of_type(f, Return)[0] @@ -709,7 +709,7 @@ def test_return_local_before_assign(slither_from_source): @pytest.mark.skipif( not valid_version("0.5.0"), reason="Solidity version 0.5.0 not available on this platform" ) -def test_shadow_local(slither_from_source): +def test_shadow_local(slither_from_solidity_source): src = """ contract A { // this require solidity 0.5 @@ -724,7 +724,7 @@ def test_shadow_local(slither_from_source): } } """ - with slither_from_source(src, "0.5.0") as slither: + with slither_from_solidity_source(src, "0.5.0") as slither: _dump_functions(slither.contracts[0]) f = slither.contracts[0].functions[0] @@ -734,7 +734,7 @@ def test_shadow_local(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_multiple_named_args_returns(slither_from_source): +def test_multiple_named_args_returns(slither_from_solidity_source): """Verifies that named arguments and return values have correct versions Each arg/ret have an initial version, version 0, and is written once and should @@ -749,7 +749,7 @@ def test_multiple_named_args_returns(slither_from_source): ret2 = arg2 + 4; } }""" - with slither_from_source(src) as slither: + with slither_from_solidity_source(src) as slither: verify_properties_hold(slither) f = slither.contracts[0].functions[0] @@ -763,7 +763,7 @@ def test_multiple_named_args_returns(slither_from_source): @pytest.mark.xfail(reason="Tests for wanted state of SSA IR, not current.", strict=True) -def test_memory_array(slither_from_source): +def test_memory_array(slither_from_solidity_source): src = """ contract MemArray { struct A { @@ -798,7 +798,7 @@ def test_memory_array(slither_from_source): return arg + 1; } }""" - with slither_from_source(src) as slither: + with slither_from_solidity_source(src) as slither: c = slither.contracts[0] ftest_array, faccept, fb = c.functions @@ -829,7 +829,7 @@ def test_memory_array(slither_from_source): @pytest.mark.xfail(reason="Tests for wanted state of SSA IR, not current.", strict=True) -def test_storage_array(slither_from_source): +def test_storage_array(slither_from_solidity_source): src = """ contract StorageArray { struct A { @@ -865,7 +865,7 @@ def test_storage_array(slither_from_source): return value + 1; } }""" - with slither_from_source(src) as slither: + with slither_from_solidity_source(src) as slither: c = slither.contracts[0] _dump_functions(c) ftest, faccept, fb = c.functions @@ -884,7 +884,7 @@ def test_storage_array(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_issue_468(slither_from_source): +def test_issue_468(slither_from_solidity_source): """ Ensure issue 468 is corrected as per https://github.com/crytic/slither/issues/468#issuecomment-620974151 @@ -905,7 +905,7 @@ def test_issue_468(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("State")[0] f = [x for x in c.functions if x.name == "f"][0] @@ -938,7 +938,7 @@ def test_issue_468(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_issue_434(slither_from_source): +def test_issue_434(slither_from_solidity_source): source = """ contract Contract { int public a; @@ -956,7 +956,7 @@ def test_issue_434(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] e = [x for x in c.functions if x.name == "e"][0] @@ -992,7 +992,7 @@ def test_issue_434(slither_from_source): @pytest.mark.xfail(strict=True, reason="Fails in current slither version. Fix in #1102.") -def test_issue_473(slither_from_source): +def test_issue_473(slither_from_solidity_source): source = """ contract Contract { function f() public returns (int) { @@ -1007,7 +1007,7 @@ def test_issue_473(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] @@ -1035,7 +1035,7 @@ def test_issue_473(slither_from_source): assert second_phi.lvalue in return_value.values -def test_issue_1748(slither_from_source): +def test_issue_1748(slither_from_solidity_source): source = """ contract Contract { uint[] arr; @@ -1044,7 +1044,7 @@ def test_issue_1748(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] operations = f.slithir_operations @@ -1052,7 +1052,7 @@ def test_issue_1748(slither_from_source): assert isinstance(assign_op, InitArray) -def test_issue_1776(slither_from_source): +def test_issue_1776(slither_from_solidity_source): source = """ contract Contract { function foo() public returns (uint) { @@ -1061,7 +1061,7 @@ def test_issue_1776(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] operations = f.slithir_operations @@ -1080,7 +1080,7 @@ def test_issue_1776(slither_from_source): assert lvalue_type2.length_value.value == "5" -def test_issue_1846_ternary_in_if(slither_from_source): +def test_issue_1846_ternary_in_if(slither_from_solidity_source): source = """ contract Contract { function foo(uint x) public returns (uint y) { @@ -1092,7 +1092,7 @@ def test_issue_1846_ternary_in_if(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] node = f.nodes[1] @@ -1101,7 +1101,7 @@ def test_issue_1846_ternary_in_if(slither_from_source): assert node.son_false.type == NodeType.EXPRESSION -def test_issue_1846_ternary_in_ternary(slither_from_source): +def test_issue_1846_ternary_in_ternary(slither_from_solidity_source): source = """ contract Contract { function foo(uint x) public returns (uint y) { @@ -1109,7 +1109,7 @@ def test_issue_1846_ternary_in_ternary(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] node = f.nodes[1] From 55ab580a758ddcf73f137e4dbf14591a8a7d69fa Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 22:23:34 -0500 Subject: [PATCH 187/338] convert raw_call to LowLevelCall --- slither/slithir/convert.py | 7 +++++-- .../expressions/expression_parsing.py | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index d40715c4f..d1eaafdfa 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1131,6 +1131,7 @@ def can_be_low_level(ir: HighLevelCall) -> bool: "delegatecall", "callcode", "staticcall", + "raw_call", ] @@ -1159,13 +1160,14 @@ def convert_to_low_level( ir.set_node(prev_ir.node) ir.lvalue.set_type(ElementaryType("bool")) return ir - if ir.function_name in ["call", "delegatecall", "callcode", "staticcall"]: + if ir.function_name in ["call", "delegatecall", "callcode", "staticcall", "raw_call"]: new_ir = LowLevelCall( ir.destination, ir.function_name, ir.nbr_arguments, ir.lvalue, ir.type_call ) new_ir.call_gas = ir.call_gas new_ir.call_value = ir.call_value new_ir.arguments = ir.arguments + # TODO fix this for Vyper if ir.node.compilation_unit.solc_version >= "0.5": new_ir.lvalue.set_type([ElementaryType("bool"), ElementaryType("bytes")]) else: @@ -1916,7 +1918,8 @@ def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Operation]: irs = propagate_type_and_convert_call(irs, node) irs = remove_unused(irs) find_references_origin(irs) - convert_constant_types(irs) + # TODO refine only for Solidity + # convert_constant_types(irs) convert_delete(irs) _find_source_mapping_references(irs) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 326fe2c75..c5da11fbe 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -311,10 +311,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Call): called = parse_expression(expression.func, caller_context) - if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): if called.value.name == "empty()": type_to = parse_type(expression.args[0], caller_context) + # TODO figure out how to represent this type argument parsed_expr = CallExpression(called, [], str(type_to)) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -355,7 +355,19 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": ), ) return parsed_expr - + + elif called.value.name == "raw_call()": + args = [parse_expression(a, caller_context) for a in expression.args] + # This is treated specially in order to force `extract_tmp_call` to treat this as a `HighLevelCall` which will be converted + # to a `LowLevelCall` by `convert_to_low_level`. This is an artifact of the late conversion of Solidity... + call = CallExpression(MemberAccess("raw_call", "tuple(bool,bytes32)", args[0]), args[1:], "tuple(bool,bytes32)") + call.set_offset(expression.src, caller_context.compilation_unit) + call.call_value = next(iter(parse_expression(x.value, caller_context) for x in expression.keywords if x.arg == "value"), None) + call.call_gas = next(iter(parse_expression(x.value, caller_context) for x in expression.keywords if x.arg == "gas"), None) + # TODO handle `max_outsize` keyword + + return call + if expression.args and isinstance(expression.args[0], VyDict): arguments = [] for val in expression.args[0].values: From 4c1ad519d037374705fbda32eefcb6f8648bdb50 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 22:30:01 -0500 Subject: [PATCH 188/338] handle edge case for vyper Expr nodes --- slither/vyper_parsing/declarations/function.py | 15 ++++++++------- .../expressions/expression_parsing.py | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 9e57b6c66..98c372808 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -238,11 +238,14 @@ class FunctionVyper: curr_node = new_node - # elif isinstance(expr, Assign): - # new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - # new_node.add_unparsed_expression(expr.target) - # new_node.add_unparsed_expression(expr.value) - # link_underlying_nodes(curr_node, new_node) + elif isinstance(expr, Expr): + # TODO This is a workaround to handle Vyper putting payable/view in the function body... + if not isinstance(expr.value, Name): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) + link_underlying_nodes(curr_node, new_node) + + curr_node = new_node elif isinstance(expr, For): @@ -441,8 +444,6 @@ class FunctionVyper: link_underlying_nodes(curr_node, condition_node) curr_node = endIf_node - elif isinstance(expr, Expr): - pass elif isinstance(expr, Pass): pass elif isinstance(expr, Raise): diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index c5da11fbe..09154d6b9 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -672,7 +672,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": rhs = parse_expression(expression.values[1], caller_context) op = BinaryOperationType.get_type(expression.op) - parsed_expr = BinaryOperation(lhs, op) + parsed_expr = BinaryOperation(lhs, rhs, op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr From 2bfe8290b9cd5f88002a8821a9292e9590455201 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 23:05:19 -0500 Subject: [PATCH 189/338] add ability to perform filtering by language to AbstractDetector --- slither/detectors/abstract_detector.py | 24 +++++++++++++++---- .../naming_convention/naming_convention.py | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index 7bb8eb93f..b6fe49d30 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -3,7 +3,7 @@ import re from logging import Logger from typing import Optional, List, TYPE_CHECKING, Dict, Union, Callable -from slither.core.compilation_unit import SlitherCompilationUnit +from slither.core.compilation_unit import SlitherCompilationUnit, Language from slither.core.declarations import Contract from slither.formatters.exceptions import FormatImpossible from slither.formatters.utils.patches import apply_patch, create_diff @@ -80,6 +80,9 @@ class AbstractDetector(metaclass=abc.ABCMeta): # list of vulnerable solc versions as strings (e.g. ["0.4.25", "0.5.0"]) # If the detector is meant to run on all versions, use None VULNERABLE_SOLC_VERSIONS: Optional[List[str]] = None + # If the detector is meant to run on all languages, use None + # Otherwise, use `solidity` or `vyper` + LANGUAGE: Optional[str] = None def __init__( self, compilation_unit: SlitherCompilationUnit, slither: "Slither", logger: Logger @@ -133,6 +136,14 @@ class AbstractDetector(metaclass=abc.ABCMeta): f"VULNERABLE_SOLC_VERSIONS should not be an empty list {self.__class__.__name__}" ) + if self.LANGUAGE is not None and self.LANGUAGE not in [ + Language.SOLIDITY.value, + Language.VYPER.value, + ]: + raise IncorrectDetectorInitialization( + f"LANGUAGE should not be either 'solidity' or 'vyper' {self.__class__.__name__}" + ) + if re.match("^[a-zA-Z0-9_-]*$", self.ARGUMENT) is None: raise IncorrectDetectorInitialization( f"ARGUMENT has illegal character {self.__class__.__name__}" @@ -164,9 +175,14 @@ class AbstractDetector(metaclass=abc.ABCMeta): if self.logger: self.logger.info(self.color(info)) - def _uses_vulnerable_solc_version(self) -> bool: + def _is_applicable_detector(self) -> bool: if self.VULNERABLE_SOLC_VERSIONS: - return self.compilation_unit.solc_version in self.VULNERABLE_SOLC_VERSIONS + return ( + self.compilation_unit.is_solidity + and self.compilation_unit.solc_version in self.VULNERABLE_SOLC_VERSIONS + ) + if self.LANGUAGE: + return self.compilation_unit._language == self.LANGUAGE return True @abc.abstractmethod @@ -179,7 +195,7 @@ class AbstractDetector(metaclass=abc.ABCMeta): results: List[Dict] = [] # check solc version - if not self._uses_vulnerable_solc_version(): + if not self._is_applicable_detector(): return results # only keep valid result, and remove duplicate diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 02deb719e..c456f62a3 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -24,7 +24,7 @@ class NamingConvention(AbstractDetector): HELP = "Conformity to Solidity naming conventions" IMPACT = DetectorClassification.INFORMATIONAL CONFIDENCE = DetectorClassification.HIGH - + LANGUAGE = "solidity" WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions" WIKI_TITLE = "Conformance to Solidity naming conventions" From 77637d90f0132433bc9daa13168b9797aa53ac64 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 23:13:36 -0500 Subject: [PATCH 190/338] delete unused code, misc. notes --- slither/vyper_parsing/declarations/event.py | 3 - .../expressions/expression_parsing.py | 233 ++---------------- .../vyper_parsing/vyper_compilation_unit.py | 36 --- 3 files changed, 24 insertions(+), 248 deletions(-) diff --git a/slither/vyper_parsing/declarations/event.py b/slither/vyper_parsing/declarations/event.py index a0152ec0e..e6ed5a12e 100644 --- a/slither/vyper_parsing/declarations/event.py +++ b/slither/vyper_parsing/declarations/event.py @@ -22,9 +22,6 @@ class EventVyper: self._event = event self._event.name = event_def.name self._elemsNotParsed = event_def.body - print(event_def) - # assert False - # self.analyze() # TODO create `VariableDecl` from `AnnAssign` from `event_def.body` (also for `StructDef`) def analyze(self, contract) -> None: for elem_to_parse in self._elemsNotParsed: diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 09154d6b9..36c7c3ee5 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -49,209 +49,6 @@ from slither.vyper_parsing.type_parsing import parse_type if TYPE_CHECKING: from slither.core.expressions.expression import Expression -logger = logging.getLogger("ExpressionParsing") - -# pylint: disable=anomalous-backslash-in-string,import-outside-toplevel,too-many-branches,too-many-locals - -# region Filtering -################################################################################### -################################################################################### - - -def filter_name(value: str) -> str: - value = value.replace(" memory", "") - value = value.replace(" storage", "") - value = value.replace(" external", "") - value = value.replace(" internal", "") - value = value.replace("struct ", "") - value = value.replace("contract ", "") - value = value.replace("enum ", "") - value = value.replace(" ref", "") - value = value.replace(" pointer", "") - value = value.replace(" pure", "") - value = value.replace(" view", "") - value = value.replace(" constant", "") - value = value.replace(" payable", "") - value = value.replace("function (", "function(") - value = value.replace("returns (", "returns(") - value = value.replace(" calldata", "") - - # remove the text remaining after functio(...) - # which should only be ..returns(...) - # nested parenthesis so we use a system of counter on parenthesis - idx = value.find("(") - if idx: - counter = 1 - max_idx = len(value) - while counter: - assert idx < max_idx - idx = idx + 1 - if value[idx] == "(": - counter += 1 - elif value[idx] == ")": - counter -= 1 - value = value[: idx + 1] - return value - - -# endregion - -################################################################################### -################################################################################### -# region Parsing -################################################################################### -################################################################################### - -# pylint: disable=too-many-statements -def parse_call( - expression: Dict, caller_context -) -> Union[ - slither.core.expressions.call_expression.CallExpression, - slither.core.expressions.type_conversion.TypeConversion, -]: - src = expression["src"] - if caller_context.is_compact_ast: - attributes = expression - type_conversion = expression["kind"] == "typeConversion" - type_return = attributes["typeDescriptions"]["typeString"] - - else: - attributes = expression["attributes"] - type_conversion = attributes["type_conversion"] - type_return = attributes["type"] - - if type_conversion: - type_call = parse_type(UnknownType(type_return), caller_context) - if caller_context.is_compact_ast: - assert len(expression["arguments"]) == 1 - expression_to_parse = expression["arguments"][0] - else: - children = expression["children"] - assert len(children) == 2 - type_info = children[0] - expression_to_parse = children[1] - assert type_info["name"] in [ - "ElementaryTypenameExpression", - "ElementaryTypeNameExpression", - "Identifier", - "TupleExpression", - "IndexAccess", - "MemberAccess", - ] - - expression = parse_expression(expression_to_parse, caller_context) - t = TypeConversion(expression, type_call) - t.set_offset(src, caller_context.compilation_unit) - if isinstance(type_call, UserDefinedType): - type_call.type.references.append(t.source_mapping) - return t - - call_gas = None - call_value = None - call_salt = None - if caller_context.is_compact_ast: - called = parse_expression(expression["expression"], caller_context) - # If the next expression is a FunctionCallOptions - # We can here the gas/value information - # This is only available if the syntax is {gas: , value: } - # For the .gas().value(), the member are considered as function call - # And converted later to the correct info (convert.py) - if expression["expression"][caller_context.get_key()] == "FunctionCallOptions": - call_with_options = expression["expression"] - for idx, name in enumerate(call_with_options.get("names", [])): - option = parse_expression(call_with_options["options"][idx], caller_context) - if name == "value": - call_value = option - if name == "gas": - call_gas = option - if name == "salt": - call_salt = option - arguments = [] - if expression["arguments"]: - arguments = [parse_expression(a, caller_context) for a in expression["arguments"]] - else: - children = expression["children"] - called = parse_expression(children[0], caller_context) - arguments = [parse_expression(a, caller_context) for a in children[1::]] - - if isinstance(called, SuperCallExpression): - sp = SuperCallExpression(called, arguments, type_return) - sp.set_offset(expression["src"], caller_context.compilation_unit) - return sp - call_expression = CallExpression(called, arguments, type_return) - call_expression.set_offset(src, caller_context.compilation_unit) - - # Only available if the syntax {gas:, value:} was used - call_expression.call_gas = call_gas - call_expression.call_value = call_value - call_expression.call_salt = call_salt - return call_expression - - -def parse_super_name(expression: Dict, is_compact_ast: bool) -> str: - if is_compact_ast: - assert expression["nodeType"] == "MemberAccess" - base_name = expression["memberName"] - arguments = expression["typeDescriptions"]["typeString"] - else: - assert expression["name"] == "MemberAccess" - attributes = expression["attributes"] - base_name = attributes["member_name"] - arguments = attributes["type"] - - assert arguments.startswith("function ") - # remove function (...() - arguments = arguments[len("function ") :] - - arguments = filter_name(arguments) - if " " in arguments: - arguments = arguments[: arguments.find(" ")] - - return base_name + arguments - - -def _parse_elementary_type_name_expression( - expression: Dict, is_compact_ast: bool, caller_context: CallerContextExpression -) -> ElementaryTypeNameExpression: - # nop exression - # uint; - if is_compact_ast: - value = expression["typeName"] - else: - if "children" in expression: - value = expression["children"][0]["attributes"]["name"] - else: - value = expression["attributes"]["value"] - if isinstance(value, dict): - t = parse_type(value, caller_context) - else: - t = parse_type(UnknownType(value), caller_context) - e = ElementaryTypeNameExpression(t) - e.set_offset(expression["src"], caller_context.compilation_unit) - return e - - -if TYPE_CHECKING: - pass - - -def _user_defined_op_call( - caller_context: CallerContextExpression, src, function_id: int, args: List[Any], type_call: str -) -> CallExpression: - var, was_created = find_variable(None, caller_context, function_id) - - if was_created: - var.set_offset(src, caller_context.compilation_unit) - - identifier = Identifier(var) - identifier.set_offset(src, caller_context.compilation_unit) - - var.references.append(identifier.source_mapping) - - call = CallExpression(identifier, args, type_call) - call.set_offset(src, caller_context.compilation_unit) - return call - from collections import deque from slither.vyper_parsing.ast.types import ( @@ -355,19 +152,37 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": ), ) return parsed_expr - + elif called.value.name == "raw_call()": args = [parse_expression(a, caller_context) for a in expression.args] # This is treated specially in order to force `extract_tmp_call` to treat this as a `HighLevelCall` which will be converted # to a `LowLevelCall` by `convert_to_low_level`. This is an artifact of the late conversion of Solidity... - call = CallExpression(MemberAccess("raw_call", "tuple(bool,bytes32)", args[0]), args[1:], "tuple(bool,bytes32)") + call = CallExpression( + MemberAccess("raw_call", "tuple(bool,bytes32)", args[0]), + args[1:], + "tuple(bool,bytes32)", + ) call.set_offset(expression.src, caller_context.compilation_unit) - call.call_value = next(iter(parse_expression(x.value, caller_context) for x in expression.keywords if x.arg == "value"), None) - call.call_gas = next(iter(parse_expression(x.value, caller_context) for x in expression.keywords if x.arg == "gas"), None) + call.call_value = next( + iter( + parse_expression(x.value, caller_context) + for x in expression.keywords + if x.arg == "value" + ), + None, + ) + call.call_gas = next( + iter( + parse_expression(x.value, caller_context) + for x in expression.keywords + if x.arg == "gas" + ), + None, + ) # TODO handle `max_outsize` keyword - return call - + return call + if expression.args and isinstance(expression.args[0], VyDict): arguments = [] for val in expression.args[0].values: diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index 88ff43d1e..2650ffe8e 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -78,39 +78,3 @@ class VyperCompilationUnit: for contract in self._compilation_unit.contracts: contract.fix_phi() contract.update_read_write_using_ssa() - - # def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: - - # self._contracts_by_id: Dict[int, ContractSolc] = {} - # self._parsed = False - # self._analyzed = False - - # self._underlying_contract_to_parser: Dict[Contract, ContractSolc] = {} - # self._structures_top_level_parser: List[StructureTopLevelSolc] = [] - # self._custom_error_parser: List[CustomErrorSolc] = [] - # self._variables_top_level_parser: List[TopLevelVariableSolc] = [] - # self._functions_top_level_parser: List[FunctionSolc] = [] - # self._using_for_top_level_parser: List[UsingForTopLevelSolc] = [] - - # self._all_functions_and_modifier_parser: List[FunctionSolc] = [] - - # self._top_level_contracts_counter = 0 - - # @property - # def compilation_unit(self) -> SlitherCompilationUnit: - # return self._compilation_unit - - # @property - # def all_functions_and_modifiers_parser(self) -> List[FunctionSolc]: - # return self._all_functions_and_modifier_parser - - # def add_function_or_modifier_parser(self, f: FunctionSolc) -> None: - # self._all_functions_and_modifier_parser.append(f) - - # @property - # def underlying_contract_to_parser(self) -> Dict[Contract, ContractSolc]: - # return self._underlying_contract_to_parser - - # @property - # def slither_parser(self) -> "SlitherCompilationUnitSolc": - # return self From 372579221d01580a45e7ff7babf307f1ae2afc58 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 23:16:02 -0500 Subject: [PATCH 191/338] delete more unused code --- .../expressions/find_variable.py | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 1c6058c1a..5b84570ce 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -30,11 +30,6 @@ if TYPE_CHECKING: from slither.solc_parsing.declarations.function import FunctionSolc from slither.solc_parsing.declarations.contract import ContractSolc -# pylint: disable=import-outside-toplevel,too-many-branches,too-many-locals - - -# CallerContext =Union["ContractSolc", "FunctionSolc", "CustomErrorSolc", "StructureTopLevelSolc"] - def _find_variable_in_function_parser( var_name: str, @@ -82,20 +77,6 @@ def _find_in_contract( if var_name in enums: return enums[var_name] - # Note: contract.custom_errors_as_dict uses the name (not the sol sig) as key - # This is because when the dic is populated the underlying object is not yet parsed - # As a result, we need to iterate over all the custom errors here instead of using the dict - custom_errors = contract.custom_errors - try: - for custom_error in custom_errors: - if var_name in [custom_error.solidity_signature, custom_error.full_name]: - return custom_error - except ValueError: - # This can happen as custom error sol signature might not have been built - # when find_variable was called - # TODO refactor find_variable to prevent this from happening - pass - # If the enum is refered as its name rather than its canonicalName enums = {e.name: e for e in contract.enums} if var_name in enums: @@ -130,25 +111,10 @@ def find_variable( :type var_name: :param caller_context: :type caller_context: - :param referenced_declaration: :return: :rtype: """ - # variable are looked from the contract declarer - # functions can be shadowed, but are looked from the contract instance, rather than the contract declarer - # the difference between function and variable come from the fact that an internal call, or an variable access - # in a function does not behave similariy, for example in: - # contract C{ - # function f(){ - # state_var = 1 - # f2() - # } - # state_var will refer to C.state_var, no mater if C is inherited - # while f2() will refer to the function definition of the inherited contract (C.f2() in the context of C, or - # the contract inheriting from C) - # for events it's unclear what should be the behavior, as they can be shadowed, but there is not impact - # structure/enums cannot be shadowed from slither.vyper_parsing.declarations.contract import ContractVyper from slither.vyper_parsing.declarations.function import FunctionVyper From 917c5d6cd6c28719ff8813b89e9c466a3a6b14a6 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 29 Aug 2023 23:21:35 -0500 Subject: [PATCH 192/338] add IncorrectSolc detector to solidity-only detectors --- 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 eaf40bf21..ad38b1784 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -33,7 +33,7 @@ class IncorrectSolc(AbstractDetector): HELP = "Incorrect Solidity version" IMPACT = DetectorClassification.INFORMATIONAL CONFIDENCE = DetectorClassification.HIGH - + LANGUAGE = "solidity" WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity" WIKI_TITLE = "Incorrect versions of Solidity" From 5197b157a84190a8575d982276bda0aea50cb289 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 08:36:04 -0500 Subject: [PATCH 193/338] fix filtering to use string value of enum --- slither/detectors/abstract_detector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index b6fe49d30..c3f661a11 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -182,7 +182,7 @@ class AbstractDetector(metaclass=abc.ABCMeta): and self.compilation_unit.solc_version in self.VULNERABLE_SOLC_VERSIONS ) if self.LANGUAGE: - return self.compilation_unit._language == self.LANGUAGE + return self.compilation_unit._language.value == self.LANGUAGE return True @abc.abstractmethod From baa3c980c29a77c688d5c8bd0f293e00f48069b7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 11:07:37 -0500 Subject: [PATCH 194/338] install vyper in CI --- .github/workflows/test.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3754bfd7..51ea634f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,7 +57,23 @@ jobs: npm install hardhat popd || exit fi - + - name: Install Vyper + run: | + INSTALLDIR="$RUNNER_TEMP/vyper-install" + if [[ "$RUNNER_OS" = "Windows" ]]; then + URL="https://github.com/vyperlang/vyper/releases/download/v0.3.7/vyper.0.3.7+commit.6020b8bb.windows.exe" + FILENAME="vyper.exe" + elif [[ "$RUNNER_OS" = "Linux" ]]; then + URL="https://github.com/vyperlang/vyper/releases/download/v0.3.7/vyper.0.3.7+commit.6020b8bb.linux" + FILENAME="vyper" + else + echo "Unknown OS" + exit 1 + fi + mkdir -p "$INSTALLDIR" + wget "$URL" -q -O "$INSTALLDIR/$FILENAME" + chmod 755 "$INSTALLDIR/$FILENAME" + echo "$INSTALLDIR" >> "$GITHUB_PATH" - name: Run ${{ matrix.type }} tests env: TEST_TYPE: ${{ matrix.type }} From ae45f461e32e72bc64af793d4fb3a1da8ccb9fab Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 11:13:15 -0500 Subject: [PATCH 195/338] initial tests --- slither/core/declarations/function.py | 23 ++--- tests/conftest.py | 20 +++++ tests/unit/core/test_function_declaration.py | 85 +++++++++++++++++++ tests/unit/slithir/vyper/__init__.py | 0 .../unit/slithir/vyper/test_ir_generation.py | 65 ++++++++++++++ 5 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 tests/unit/slithir/vyper/__init__.py create mode 100644 tests/unit/slithir/vyper/test_ir_generation.py diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index d549c9615..0f1955a92 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -106,7 +106,8 @@ def _filter_state_variables_written(expressions: List["Expression"]): ret.append(expression.expression_left) return ret -#TODO replace + +# TODO replace class FunctionLanguage(Enum): Solidity = 0 Yul = 1 @@ -238,7 +239,7 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu """ if self._name == "" and self._function_type == FunctionType.CONSTRUCTOR: return "constructor" - if self._function_type == FunctionType.FALLBACK: + if self._name == "" and self._function_type == FunctionType.FALLBACK: return "fallback" if self._function_type == FunctionType.RECEIVE: return "receive" @@ -985,14 +986,15 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu (str, list(str), list(str)): Function signature as (name, list parameters type, list return values type) """ - if self._signature is None: - signature = ( - self.name, - [str(x.type) for x in self.parameters], - [str(x.type) for x in self.returns], - ) - self._signature = signature - return self._signature + # FIXME memoizing this function is not working properly for vyper + # if self._signature is None: + return ( + self.name, + [str(x.type) for x in self.parameters], + [str(x.type) for x in self.returns], + ) + # self._signature = signature + # return self._signature @property def signature_str(self) -> str: @@ -1758,7 +1760,6 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu def generate_slithir_and_analyze(self) -> None: print("generate_slithir_and_analyze") - print(self.nodes) for node in self.nodes: node.slithir_generation() diff --git a/tests/conftest.py b/tests/conftest.py index 1b9f44c52..5c77dceca 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -77,3 +77,23 @@ def slither_from_solidity_source(solc_binary_path): Path(fname).unlink() return inner + + +@pytest.fixture +def slither_from_vyper_source(): + @contextmanager + def inner(source_code: str): + """Yields a Slither instance using source_code string. + Creates a temporary file and compiles with vyper. + """ + + fname = "" + try: + with tempfile.NamedTemporaryFile(mode="w", suffix=".vy", delete=False) as f: + fname = f.name + f.write(source_code) + yield Slither(fname) + finally: + Path(fname).unlink() + + return inner diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index 651f449de..739a113bc 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -9,6 +9,7 @@ from pathlib import Path from slither import Slither from slither.core.declarations.function import FunctionType from slither.core.solidity_types.elementary_type import ElementaryType +from slither.core.solidity_types.mapping_type import MappingType TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" FUNC_DELC_TEST_ROOT = Path(TEST_DATA_DIR, "function_declaration") @@ -302,3 +303,87 @@ def test_public_variable(solc_binary_path) -> None: assert var.signature_str == "info() returns(bytes32)" assert var.visibility == "public" assert var.type == ElementaryType("bytes32") + + +def test_vyper_functions(slither_from_vyper_source) -> None: + with slither_from_vyper_source( + """ +balances: public(HashMap[address, uint256]) +allowances: HashMap[address, HashMap[address, uint256]] +@pure +@internal +def add(x: int128, y: int128) -> int128: + return x + y +@external +def __init__(): + pass +@external +def withdraw(): + raw_call(msg.sender, b"", value= self.balances[msg.sender]) +@external +@nonreentrant("lock") +def withdraw_locked(): + raw_call(msg.sender, b"", value= self.balances[msg.sender]) +@payable +@external +def __default__(): + pass + """ + ) as sl: + contract = sl.contracts[0] + functions = contract.available_functions_as_dict() + + f = functions["add(int128,int128)"] + assert f.function_type == FunctionType.NORMAL + assert f.visibility == "internal" + assert not f.payable + assert f.view is False + assert f.pure is True + assert f.parameters[0].name == "x" + assert f.parameters[0].type == ElementaryType("int128") + assert f.parameters[1].name == "y" + assert f.parameters[1].type == ElementaryType("int128") + assert f.return_type[0] == ElementaryType("int128") + + f = functions["__init__()"] + assert f.function_type == FunctionType.CONSTRUCTOR + assert f.visibility == "external" + assert not f.payable + assert not f.view + assert not f.pure + + f = functions["__default__()"] + assert f.function_type == FunctionType.FALLBACK + assert f.visibility == "external" + assert f.payable + assert not f.view + assert not f.pure + + f = functions["withdraw()"] + assert f.function_type == FunctionType.NORMAL + assert f.visibility == "external" + assert not f.payable + assert not f.view + assert not f.pure + assert f.can_send_eth() + assert f.can_reenter() + + # f = functions["withdraw_locked()"] + # assert not f.can_reenter() + + var = contract.get_state_variable_from_name("balances") + assert var + assert var.solidity_signature == "balances(address)" + assert var.signature_str == "balances(address) returns(uint256)" + assert var.visibility == "public" + assert var.type == MappingType(ElementaryType("address"), ElementaryType("uint256")) + + var = contract.get_state_variable_from_name("allowances") + assert var + assert var.solidity_signature == "allowances(address,address)" + assert var.signature_str == "allowances(address,address) returns(uint256)" + assert var.visibility == "internal" + assert var.type == MappingType( + ElementaryType("address"), + MappingType(ElementaryType("address"), ElementaryType("uint256")), + ) diff --git a/tests/unit/slithir/vyper/__init__.py b/tests/unit/slithir/vyper/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/slithir/vyper/test_ir_generation.py b/tests/unit/slithir/vyper/test_ir_generation.py new file mode 100644 index 000000000..3ea5ea9fc --- /dev/null +++ b/tests/unit/slithir/vyper/test_ir_generation.py @@ -0,0 +1,65 @@ +# # pylint: disable=too-many-lines +import pathlib +from argparse import ArgumentTypeError +from collections import defaultdict +from inspect import getsourcefile +from typing import Union, List, Dict, Callable + +import pytest + +from slither import Slither +from slither.core.cfg.node import Node, NodeType +from slither.core.declarations import Function, Contract +from slither.core.solidity_types import ArrayType +from slither.core.variables.local_variable import LocalVariable +from slither.core.variables.state_variable import StateVariable +from slither.slithir.operations import ( + OperationWithLValue, + Phi, + Assignment, + HighLevelCall, + Return, + Operation, + Binary, + BinaryType, + InternalCall, + Index, + InitArray, +) +from slither.slithir.utils.ssa import is_used_later +from slither.slithir.variables import ( + Constant, + ReferenceVariable, + LocalIRVariable, + StateIRVariable, + TemporaryVariableSSA, +) + + +def test_interface_conversion_and_call_resolution(slither_from_vyper_source): + with slither_from_vyper_source( + """ +interface Test: + def foo() -> (int128, uint256): nonpayable + +@internal +def foo() -> (int128, int128): + return 2, 3 + +@external +def bar(): + a: int128 = 0 + b: int128 = 0 + (a, b) = self.foo() + + x: address = 0x0000000000000000000000000000000000000000 + c: uint256 = 0 + a, c = Test(x).foo() +""" + ) as sl: + interface = next(iter(x for x in sl.contracts if x.is_interface)) + contract = next(iter(x for x in sl.contracts if not x.is_interface)) + func = contract.get_function_from_signature("bar()") + (contract, function) = func.high_level_calls[0] + assert contract == interface + assert function.signature_str == "foo() returns(int128,uint256)" From b5778ce5df4b5e4a65e8bbc38e730773f432be39 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 11:22:36 -0500 Subject: [PATCH 196/338] use curl to support windows --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 51ea634f1..ef10a19a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: exit 1 fi mkdir -p "$INSTALLDIR" - wget "$URL" -q -O "$INSTALLDIR/$FILENAME" + curl "$URL" -o "$INSTALLDIR/$FILENAME" chmod 755 "$INSTALLDIR/$FILENAME" echo "$INSTALLDIR" >> "$GITHUB_PATH" - name: Run ${{ matrix.type }} tests From 0fd1ed73088714ba824e1dc4258951d347df7fb0 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 13:21:48 -0500 Subject: [PATCH 197/338] follow redirects --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef10a19a5..533940328 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: exit 1 fi mkdir -p "$INSTALLDIR" - curl "$URL" -o "$INSTALLDIR/$FILENAME" + curl "$URL" -o "$INSTALLDIR/$FILENAME" -L chmod 755 "$INSTALLDIR/$FILENAME" echo "$INSTALLDIR" >> "$GITHUB_PATH" - name: Run ${{ matrix.type }} tests From ce6d3c91c8c6bdca8b05a635d9111cfb9520948f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 13:27:35 -0500 Subject: [PATCH 198/338] point at vyper crytic-compile branch --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 70d4f71fd..4d3a15c8f 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( "prettytable>=3.3.0", "pycryptodome>=3.4.6", # "crytic-compile>=0.3.1,<0.4.0", - "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile", + "crytic-compile@git+https://github.com/crytic/crytic-compile.git@feat/vyper-standard-json#egg=crytic-compile", "web3>=6.0.0", "eth-abi>=4.0.0", "eth-typing>=3.0.0", From 929c2af08842c13d3011f31140515a595d94f927 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 14:53:58 -0500 Subject: [PATCH 199/338] add deprecated calls to solidity only detectors --- slither/detectors/statements/deprecated_calls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/statements/deprecated_calls.py b/slither/detectors/statements/deprecated_calls.py index e59d254bb..5e066c751 100644 --- a/slither/detectors/statements/deprecated_calls.py +++ b/slither/detectors/statements/deprecated_calls.py @@ -31,7 +31,7 @@ class DeprecatedStandards(AbstractDetector): HELP = "Deprecated Solidity Standards" IMPACT = DetectorClassification.INFORMATIONAL CONFIDENCE = DetectorClassification.HIGH - + LANGUAGE = "solidity" WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards" WIKI_TITLE = "Deprecated standards" From eadcd462c39923b2e7618f2f6da3cac1d32d9d43 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 30 Aug 2023 15:57:43 -0500 Subject: [PATCH 200/338] remove solc imports from vyper parsing --- .../vyper_parsing/expressions/expression_parsing.py | 8 ++++---- slither/vyper_parsing/expressions/find_variable.py | 10 ++++------ .../variables/function_type_variable.py | 13 ------------- 3 files changed, 8 insertions(+), 23 deletions(-) delete mode 100644 slither/vyper_parsing/variables/function_type_variable.py diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 36c7c3ee5..60d5fe246 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -40,8 +40,6 @@ from slither.core.solidity_types import ( UserDefinedType, ) from slither.core.declarations.contract import Contract -from slither.solc_parsing.declarations.caller_context import CallerContextExpression -from slither.solc_parsing.exceptions import ParsingError, VariableNotFound from slither.vyper_parsing.expressions.find_variable import find_variable from slither.vyper_parsing.type_parsing import parse_type @@ -107,6 +105,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return literal if isinstance(expression, Call): + print("Call") + print(expression) called = parse_expression(expression.func, caller_context) if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): if called.value.name == "empty()": @@ -227,7 +227,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" ) - + print(arguments) parsed_expr = CallExpression(called, arguments, type_str) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -235,7 +235,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Attribute): member_name = expression.attr if isinstance(expression.value, Name): - + print(expression) if expression.value.id == "self" and member_name != "balance": var, was_created = find_variable(member_name, caller_context) # TODO replace with self diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 5b84570ce..1b9f0de87 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -20,20 +20,18 @@ from slither.core.solidity_types import ( MappingType, TypeAlias, ) -from slither.core.variables.top_level_variable import TopLevelVariable from slither.core.variables.variable import Variable from slither.exceptions import SlitherError -from slither.solc_parsing.declarations.caller_context import CallerContextExpression from slither.solc_parsing.exceptions import VariableNotFound if TYPE_CHECKING: - from slither.solc_parsing.declarations.function import FunctionSolc - from slither.solc_parsing.declarations.contract import ContractSolc + from slither.vyper_parsing.declarations.function import FunctionVyper + def _find_variable_in_function_parser( var_name: str, - function_parser: Optional["FunctionSolc"], + function_parser: Optional["FunctionVyper"], ) -> Optional[Variable]: if function_parser is None: return None @@ -87,7 +85,7 @@ def _find_in_contract( def find_variable( var_name: str, - caller_context: CallerContextExpression, + caller_context, ) -> Tuple[ Union[ Variable, diff --git a/slither/vyper_parsing/variables/function_type_variable.py b/slither/vyper_parsing/variables/function_type_variable.py deleted file mode 100644 index 309f4d8b7..000000000 --- a/slither/vyper_parsing/variables/function_type_variable.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Dict - -from slither.solc_parsing.variables.variable_declaration import VariableDeclarationSolc -from slither.core.variables.function_type_variable import FunctionTypeVariable - - -class FunctionTypeVariableSolc(VariableDeclarationSolc): - def __init__(self, variable: FunctionTypeVariable, variable_data: Dict): - super().__init__(variable, variable_data) - - @property - def underlying_variable(self) -> FunctionTypeVariable: - return self._variable From d3686764b83931a734b60fbd8f7ac8200248d0c5 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 07:41:22 -0500 Subject: [PATCH 201/338] fix missing call to set_offset --- slither/vyper_parsing/expressions/expression_parsing.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 60d5fe246..bebbf3b9e 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -136,6 +136,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": member_type, ), ) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr elif called.value.name == "max_value()": @@ -151,6 +152,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": member_type, ), ) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr elif called.value.name == "raw_call()": From 36c60a93b0de84afa68e8ce71b3563c96545500d Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 10:30:00 -0500 Subject: [PATCH 202/338] add failing phi test --- tests/unit/slithir/vyper/test_ir_generation.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/slithir/vyper/test_ir_generation.py b/tests/unit/slithir/vyper/test_ir_generation.py index 3ea5ea9fc..704e0d27a 100644 --- a/tests/unit/slithir/vyper/test_ir_generation.py +++ b/tests/unit/slithir/vyper/test_ir_generation.py @@ -63,3 +63,20 @@ def bar(): (contract, function) = func.high_level_calls[0] assert contract == interface assert function.signature_str == "foo() returns(int128,uint256)" + +def test_phi_entry_point_internal_call(slither_from_vyper_source): + with slither_from_vyper_source( + """ +counter: uint256 +@internal +def b(y: uint256): + self.counter = y # tainted by x, 1 + +@external +def a(x: uint256): + self.b(x) + self.b(1) +""" + ) as sl: + b = sl.contracts[0].get_function_from_signature("b(uint256)") + assert len(list(filter(lambda x: isinstance(x, Phi), b.all_slithir_operations()))) == 1 From 0efef8babf8be6169f62ad20d73c3bd4377e126c Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 12:30:21 -0500 Subject: [PATCH 203/338] add test for parsing and cfgir --- tests/e2e/vyper_parsing/__init__.py | 0 ..._vyper_cfgir_builtins_test_builtins__0.txt | 117 ++++++++++++ ...ast_parsing__vyper_cfgir_chain_test__0.txt | 13 ++ ..._parsing__vyper_cfgir_for2_for_loop__0.txt | 63 +++++++ ...slitherConstructorConstantVariables__0.txt | 19 ++ ...ast_parsing__vyper_cfgir_for3_get_D__0.txt | 62 +++++++ ...t_parsing__vyper_cfgir_for_for_loop__0.txt | 56 ++++++ ...slitherConstructorConstantVariables__0.txt | 19 ++ ...t_parsing__vyper_cfgir_if_limit_p_o__0.txt | 172 ++++++++++++++++++ .../ast_parsing__vyper_cfgir_in_bar__0.txt | 50 +++++ .../ast_parsing__vyper_cfgir_in_foo__0.txt | 51 ++++++ ...arsing__vyper_cfgir_initarry___init__0.txt | 22 +++ ...parsing__vyper_cfgir_initarry_coins__0.txt | 16 ++ ...slitherConstructorConstantVariables__0.txt | 9 + ..._parsing__vyper_cfgir_precedence_fa__0.txt | 12 ++ ..._parsing__vyper_cfgir_precedence_fb__0.txt | 4 + ...parsing__vyper_cfgir_precedence_foo__0.txt | 17 ++ ...st_parsing__vyper_cfgir_struct_test__0.txt | 13 ++ ...slitherConstructorConstantVariables__0.txt | 9 + .../ast_parsing__vyper_cfgir_tuple_bar__0.txt | 57 ++++++ .../ast_parsing__vyper_cfgir_tuple_foo__0.txt | 12 ++ tests/e2e/vyper_parsing/test_ast_parsing.py | 26 +++ tests/e2e/vyper_parsing/test_data/ERC20.vy | 22 +++ tests/e2e/vyper_parsing/test_data/builtins.vy | 31 ++++ tests/e2e/vyper_parsing/test_data/chain.vy | 4 + tests/e2e/vyper_parsing/test_data/for.vy | 32 ++++ tests/e2e/vyper_parsing/test_data/for2.vy | 26 +++ tests/e2e/vyper_parsing/test_data/for3.vy | 6 + tests/e2e/vyper_parsing/test_data/if.vy | 25 +++ tests/e2e/vyper_parsing/test_data/in.vy | 23 +++ tests/e2e/vyper_parsing/test_data/initarry.vy | 17 ++ tests/e2e/vyper_parsing/test_data/literal.vy | 20 ++ .../e2e/vyper_parsing/test_data/precedence.vy | 13 ++ tests/e2e/vyper_parsing/test_data/struct.vy | 7 + tests/e2e/vyper_parsing/test_data/tricky.vy | 15 ++ tests/e2e/vyper_parsing/test_data/tuple.vy | 19 ++ 36 files changed, 1079 insertions(+) create mode 100644 tests/e2e/vyper_parsing/__init__.py create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_slitherConstructorConstantVariables__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_slitherConstructorConstantVariables__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry___init__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fa__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_struct_test__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt create mode 100644 tests/e2e/vyper_parsing/test_ast_parsing.py create mode 100644 tests/e2e/vyper_parsing/test_data/ERC20.vy create mode 100644 tests/e2e/vyper_parsing/test_data/builtins.vy create mode 100644 tests/e2e/vyper_parsing/test_data/chain.vy create mode 100644 tests/e2e/vyper_parsing/test_data/for.vy create mode 100644 tests/e2e/vyper_parsing/test_data/for2.vy create mode 100644 tests/e2e/vyper_parsing/test_data/for3.vy create mode 100644 tests/e2e/vyper_parsing/test_data/if.vy create mode 100644 tests/e2e/vyper_parsing/test_data/in.vy create mode 100644 tests/e2e/vyper_parsing/test_data/initarry.vy create mode 100644 tests/e2e/vyper_parsing/test_data/literal.vy create mode 100644 tests/e2e/vyper_parsing/test_data/precedence.vy create mode 100644 tests/e2e/vyper_parsing/test_data/struct.vy create mode 100644 tests/e2e/vyper_parsing/test_data/tricky.vy create mode 100644 tests/e2e/vyper_parsing/test_data/tuple.vy diff --git a/tests/e2e/vyper_parsing/__init__.py b/tests/e2e/vyper_parsing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt new file mode 100644 index 000000000..07141a2b1 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt @@ -0,0 +1,117 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = block.coinbase + +IRs: +a(address) := block.coinbase(address)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = block.difficulty + +IRs: +b(uint256) := block.difficulty(uint256)"]; +2->3; +3[label="Node Type: NEW VARIABLE 3 + +EXPRESSION: +c = block.prevrandao + +IRs: +c(uint256) := block.prevrandao(uint256)"]; +3->4; +4[label="Node Type: NEW VARIABLE 4 + +EXPRESSION: +d = block.number + +IRs: +d(uint256) := block.number(uint256)"]; +4->5; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +e = block.prevhash + +IRs: +e(bytes32) := block.prevhash(bytes32)"]; +5->6; +6[label="Node Type: NEW VARIABLE 6 + +EXPRESSION: +f = block.timestamp + +IRs: +f(uint256) := block.timestamp(uint256)"]; +6->7; +7[label="Node Type: NEW VARIABLE 7 + +EXPRESSION: +h = chain.id + +IRs: +h(uint256) := chain.id(uint256)"]; +7->8; +8[label="Node Type: NEW VARIABLE 8 + +EXPRESSION: +i = slice()(msg.data,0,32) + +IRs: +TMP_0(None) = SOLIDITY_CALL slice()(msg.data,0,32) +i(bytes[32]) = ['TMP_0(None)']"]; +8->9; +9[label="Node Type: NEW VARIABLE 9 + +EXPRESSION: +j = msg.gas + +IRs: +j(uint256) := msg.gas(uint256)"]; +9->10; +10[label="Node Type: NEW VARIABLE 10 + +EXPRESSION: +k = msg.sender + +IRs: +k(address) := msg.sender(address)"]; +10->11; +11[label="Node Type: NEW VARIABLE 11 + +EXPRESSION: +l = msg.value + +IRs: +l(uint256) := msg.value(uint256)"]; +11->12; +12[label="Node Type: NEW VARIABLE 12 + +EXPRESSION: +m = tx.origin + +IRs: +m(address) := tx.origin(address)"]; +12->13; +13[label="Node Type: NEW VARIABLE 13 + +EXPRESSION: +n = tx.gasprice + +IRs: +n(uint256) := tx.gasprice(uint256)"]; +13->14; +14[label="Node Type: NEW VARIABLE 14 + +EXPRESSION: +x = self.balance + +IRs: +x(uint256) := self.balance(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt new file mode 100644 index 000000000..6f12cb530 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt @@ -0,0 +1,13 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +x = bytes32(chain.id) + +IRs: +TMP_0 = CONVERT chain.id to bytes32 +x(bytes32) := TMP_0(bytes32)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt new file mode 100644 index 000000000..949e814ff --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt @@ -0,0 +1,63 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +_strategies = strategies + +IRs: +_strategies(address[3]) = ['strategies(address[3])']"]; +1->2; +2[label="Node Type: BEGIN_LOOP 2 +"]; +2->3; +3[label="Node Type: NEW VARIABLE 3 + +EXPRESSION: +counter_var = 0 + +IRs: +counter_var(uint256) := 0(uint256)"]; +3->4; +4[label="Node Type: IF_LOOP 4 + +EXPRESSION: +counter_var <= 10 + +IRs: +TMP_0(bool) = counter_var <= 10 +CONDITION TMP_0"]; +4->5[label="True"]; +4->7[label="False"]; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +i = counter_var + +IRs: +i(uint256) := counter_var(uint256)"]; +5->6; +6[label="Node Type: NEW VARIABLE 6 + +EXPRESSION: +max_withdraw = IStrategy(_strategies[i]).maxWithdraw(self) + +IRs: +REF_0(address) -> _strategies[i] +TMP_1 = CONVERT REF_0 to IStrategy +TMP_2(uint256) = HIGH_LEVEL_CALL, dest:TMP_1(IStrategy), function:maxWithdraw, arguments:['self'] +max_withdraw(uint256) := TMP_2(uint256)"]; +6->8; +7[label="Node Type: END_LOOP 7 +"]; +8[label="Node Type: EXPRESSION 8 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +8->4; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..781b8e485 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,19 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +x = 1 + 1 + +IRs: +TMP_3(uint256) = 1 + 1 +x(uint256) := TMP_3(uint256)"]; +0->1; +1[label="Node Type: OTHER_ENTRYPOINT 1 + +EXPRESSION: +MAX_QUEUE = 1 + x + +IRs: +TMP_4(uint256) = 1 + x +MAX_QUEUE(uint256) := TMP_4(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt new file mode 100644 index 000000000..ae6d397b0 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt @@ -0,0 +1,62 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +S = 0 + +IRs: +S(uint256) := 0(uint256)"]; +1->2; +2[label="Node Type: BEGIN_LOOP 2 +"]; +2->3; +3[label="Node Type: NEW VARIABLE 3 + +EXPRESSION: +counter_var = 0 + +IRs: +counter_var(uint256) := 0(uint256)"]; +3->4; +4[label="Node Type: IF_LOOP 4 + +EXPRESSION: +counter_var <= len()(_xp) + +IRs: +TMP_0(uint256) = SOLIDITY_CALL len()(_xp) +TMP_1(bool) = counter_var <= TMP_0 +CONDITION TMP_1"]; +4->5[label="True"]; +4->7[label="False"]; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +x = _xp[counter_var] + +IRs: +REF_0(uint256) -> _xp[counter_var] +x(uint256) := REF_0(uint256)"]; +5->6; +6[label="Node Type: EXPRESSION 6 + +EXPRESSION: +S += x + +IRs: +S(uint256) = S (c)+ x"]; +6->8; +7[label="Node Type: END_LOOP 7 +"]; +8[label="Node Type: EXPRESSION 8 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +8->4; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt new file mode 100644 index 000000000..210c5cec5 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt @@ -0,0 +1,56 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: BEGIN_LOOP 1 +"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +counter_var = 0 + +IRs: +counter_var(uint256) := 0(uint256)"]; +2->3; +3[label="Node Type: IF_LOOP 3 + +EXPRESSION: +counter_var <= len()(super.strategies) + +IRs: +TMP_0(uint256) = SOLIDITY_CALL len()(strategies) +TMP_1(bool) = counter_var <= TMP_0 +CONDITION TMP_1"]; +3->4[label="True"]; +3->6[label="False"]; +4[label="Node Type: NEW VARIABLE 4 + +EXPRESSION: +strategy = strategies[counter_var] + +IRs: +REF_0(address) -> strategies[counter_var] +strategy(address) := REF_0(address)"]; +4->5; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +z = IStrategy(strategy).asset() + +IRs: +TMP_2 = CONVERT strategy to IStrategy +TMP_3(address) = HIGH_LEVEL_CALL, dest:TMP_2(IStrategy), function:asset, arguments:[] +z(address) := TMP_3(address)"]; +5->7; +6[label="Node Type: END_LOOP 6 +"]; +7[label="Node Type: EXPRESSION 7 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +7->3; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..a5e0a06f7 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,19 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +x = 1 + 1 + +IRs: +TMP_4(uint256) = 1 + 1 +x(uint256) := TMP_4(uint256)"]; +0->1; +1[label="Node Type: OTHER_ENTRYPOINT 1 + +EXPRESSION: +MAX_QUEUE = 1 + x + +IRs: +TMP_5(uint256) = 1 + x +MAX_QUEUE(uint256) := TMP_5(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt new file mode 100644 index 000000000..0c7ae7d7a --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt @@ -0,0 +1,172 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +p_new = p + +IRs: +p_new(uint256) := p(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +dt = 1 + +IRs: +dt(uint256) := 1(uint256)"]; +2->3; +3[label="Node Type: NEW VARIABLE 3 + +EXPRESSION: +ratio = 0 + +IRs: +ratio(uint256) := 0(uint256)"]; +3->4; +4[label="Node Type: IF 4 + +EXPRESSION: +dt > 0 + +IRs: +TMP_0(bool) = dt > 0 +CONDITION TMP_0"]; +4->6[label="True"]; +4->5[label="False"]; +5[label="Node Type: END_IF 5 +"]; +6[label="Node Type: NEW VARIABLE 6 + +EXPRESSION: +old_p_o = 1 + +IRs: +old_p_o(uint256) := 1(uint256)"]; +6->7; +7[label="Node Type: NEW VARIABLE 7 + +EXPRESSION: +old_ratio = 2 + +IRs: +old_ratio(uint256) := 2(uint256)"]; +7->8; +8[label="Node Type: IF 8 + +EXPRESSION: +p > old_p_o + +IRs: +TMP_1(bool) = p > old_p_o +CONDITION TMP_1"]; +8->10[label="True"]; +8->15[label="False"]; +9[label="Node Type: END_IF 9 +"]; +9->20; +10[label="Node Type: EXPRESSION 10 + +EXPRESSION: +ratio = unsafe_div()(old_p_o * 10 ** 18,p) + +IRs: +TMP_2(uint256) = 10 (c)** 18 +TMP_3(uint256) = old_p_o (c)* TMP_2 +TMP_4(None) = SOLIDITY_CALL unsafe_div()(TMP_3,p) +ratio(uint256) := TMP_4(None)"]; +10->11; +11[label="Node Type: IF 11 + +EXPRESSION: +ratio < 10 ** 36 / 1 + +IRs: +TMP_5(uint256) = 10 (c)** 36 +TMP_6(uint256) = TMP_5 (c)/ 1 +TMP_7(bool) = ratio < TMP_6 +CONDITION TMP_7"]; +11->13[label="True"]; +11->12[label="False"]; +12[label="Node Type: END_IF 12 +"]; +12->9; +13[label="Node Type: EXPRESSION 13 + +EXPRESSION: +p_new = unsafe_div()(old_p_o * 1,10 ** 18) + +IRs: +TMP_8(uint256) = old_p_o (c)* 1 +TMP_9(uint256) = 10 (c)** 18 +TMP_10(None) = SOLIDITY_CALL unsafe_div()(TMP_8,TMP_9) +p_new(uint256) := TMP_10(None)"]; +13->14; +14[label="Node Type: EXPRESSION 14 + +EXPRESSION: +ratio = 10 ** 36 / 1 + +IRs: +TMP_11(uint256) = 10 (c)** 36 +TMP_12(uint256) = TMP_11 (c)/ 1 +ratio(uint256) := TMP_12(uint256)"]; +14->12; +15[label="Node Type: EXPRESSION 15 + +EXPRESSION: +ratio = unsafe_div()(p * 10 ** 18,old_p_o) + +IRs: +TMP_13(uint256) = 10 (c)** 18 +TMP_14(uint256) = p (c)* TMP_13 +TMP_15(None) = SOLIDITY_CALL unsafe_div()(TMP_14,old_p_o) +ratio(uint256) := TMP_15(None)"]; +15->16; +16[label="Node Type: IF 16 + +EXPRESSION: +ratio < 10 ** 36 / 1 + +IRs: +TMP_16(uint256) = 10 (c)** 36 +TMP_17(uint256) = TMP_16 (c)/ 1 +TMP_18(bool) = ratio < TMP_17 +CONDITION TMP_18"]; +16->18[label="True"]; +16->17[label="False"]; +17[label="Node Type: END_IF 17 +"]; +17->9; +18[label="Node Type: EXPRESSION 18 + +EXPRESSION: +p_new = unsafe_div()(old_p_o * 10 ** 18,1) + +IRs: +TMP_19(uint256) = 10 (c)** 18 +TMP_20(uint256) = old_p_o (c)* TMP_19 +TMP_21(None) = SOLIDITY_CALL unsafe_div()(TMP_20,1) +p_new(uint256) := TMP_21(None)"]; +18->19; +19[label="Node Type: EXPRESSION 19 + +EXPRESSION: +ratio = 10 ** 36 / 1 + +IRs: +TMP_22(uint256) = 10 (c)** 36 +TMP_23(uint256) = TMP_22 (c)/ 1 +ratio(uint256) := TMP_23(uint256)"]; +19->17; +20[label="Node Type: EXPRESSION 20 + +EXPRESSION: +ratio = 1 + +IRs: +ratio(uint256) := 1(uint256)"]; +20->5; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt new file mode 100644 index 000000000..7bf9052b8 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt @@ -0,0 +1,50 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = 0 + +IRs: +a(int128) := 0(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = 0 + +IRs: +b(int128) := 0(uint256)"]; +2->3; +3[label="Node Type: IF 3 + +EXPRESSION: +x & 1 | 2 + +IRs: +TMP_0(uint256) = 1 | 2 +TMP_1(in.Roles) = x & TMP_0 +CONDITION TMP_1"]; +3->5[label="True"]; +3->4[label="False"]; +4[label="Node Type: END_IF 4 +"]; +4->6; +5[label="Node Type: RETURN 5 + +EXPRESSION: +True + +IRs: +RETURN True"]; +5->4; +6[label="Node Type: RETURN 6 + +EXPRESSION: +False + +IRs: +RETURN False"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt new file mode 100644 index 000000000..b9d3da07e --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt @@ -0,0 +1,51 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = 0 + +IRs: +a(int128) := 0(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = 0 + +IRs: +b(int128) := 0(uint256)"]; +2->3; +3[label="Node Type: IF 3 + +EXPRESSION: +x == b || x == a + +IRs: +TMP_2(bool) = x == b +TMP_3(bool) = x == a +TMP_4(bool) = TMP_2 || TMP_3 +CONDITION TMP_4"]; +3->5[label="True"]; +3->4[label="False"]; +4[label="Node Type: END_IF 4 +"]; +4->6; +5[label="Node Type: RETURN 5 + +EXPRESSION: +True + +IRs: +RETURN True"]; +5->4; +6[label="Node Type: RETURN 6 + +EXPRESSION: +False + +IRs: +RETURN False"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry___init__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry___init__0.txt new file mode 100644 index 000000000..e3417a894 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry___init__0.txt @@ -0,0 +1,22 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: EXPRESSION 1 + +EXPRESSION: +BORROWED_TOKEN = ERC20(x) + +IRs: +TMP_0 = CONVERT x to ERC20 +BORROWED_TOKEN(ERC20) := TMP_0(ERC20)"]; +1->2; +2[label="Node Type: EXPRESSION 2 + +EXPRESSION: +COLLATERAL_TOKEN = ERC20(y) + +IRs: +TMP_1 = CONVERT y to ERC20 +COLLATERAL_TOKEN(ERC20) := TMP_1(ERC20)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt new file mode 100644 index 000000000..15a091f26 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt @@ -0,0 +1,16 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +(address(BORROWED_TOKEN),address(COLLATERAL_TOKEN))[i] + +IRs: +TMP_2 = CONVERT BORROWED_TOKEN to address +TMP_3 = CONVERT COLLATERAL_TOKEN to address +TMP_4(address[2]) = ['TMP_2(address)', 'TMP_3(address)'] +REF_0(address) -> TMP_4[i] +RETURN REF_0"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..b53263a8d --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,9 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +MAX_BANDS = 10 + +IRs: +MAX_BANDS(uint256) := 10(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fa__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fa__0.txt new file mode 100644 index 000000000..9d3526f54 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fa__0.txt @@ -0,0 +1,12 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +1 + +IRs: +RETURN 1"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt new file mode 100644 index 000000000..b799f07d4 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt @@ -0,0 +1,4 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt new file mode 100644 index 000000000..802e03ad1 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt @@ -0,0 +1,17 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +x != super.fb() && x != super.fa() + +IRs: +TMP_0(uint256) = INTERNAL_CALL, precedence.fb()() +TMP_1(bool) = x != TMP_0 +TMP_2(uint256) = INTERNAL_CALL, precedence.fa()() +TMP_3(bool) = x != TMP_2 +TMP_4(bool) = TMP_1 && TMP_3 +RETURN TMP_4"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_struct_test__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_struct_test__0.txt new file mode 100644 index 000000000..d8c540f21 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_struct_test__0.txt @@ -0,0 +1,13 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +X(1) + +IRs: +TMP_0(struct.X) = new X(1) +RETURN TMP_0"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..753f5a938 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,9 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +MAX_TICKS_UINT = 50 + +IRs: +MAX_TICKS_UINT(uint256) := 50(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt new file mode 100644 index 000000000..35b37282c --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt @@ -0,0 +1,57 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = 0 + +IRs: +a(int128) := 0(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = 0 + +IRs: +b(int128) := 0(uint256)"]; +2->3; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +(a,b) = super.foo() + +IRs: +TUPLE_0(int128,int128) = INTERNAL_CALL, tuple.foo()() +a(int128)= UNPACK TUPLE_0 index: 0 +b(int128)= UNPACK TUPLE_0 index: 1 "]; +3->4; +4[label="Node Type: NEW VARIABLE 4 + +EXPRESSION: +x = 0x0000000000000000000000000000000000000000 + +IRs: +x(address) := 0(address)"]; +4->5; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +c = 0 + +IRs: +c(uint256) := 0(uint256)"]; +5->6; +6[label="Node Type: EXPRESSION 6 + +EXPRESSION: +(a,c) = Test(x).foo() + +IRs: +TMP_0 = CONVERT x to Test +TUPLE_1(int128,uint256) = HIGH_LEVEL_CALL, dest:TMP_0(Test), function:foo, arguments:[] +a(int128)= UNPACK TUPLE_1 index: 0 +c(uint256)= UNPACK TUPLE_1 index: 1 "]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt new file mode 100644 index 000000000..8d1c1166b --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt @@ -0,0 +1,12 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +(2,3) + +IRs: +RETURN 2,3"]; +} diff --git a/tests/e2e/vyper_parsing/test_ast_parsing.py b/tests/e2e/vyper_parsing/test_ast_parsing.py new file mode 100644 index 000000000..8529f3e1c --- /dev/null +++ b/tests/e2e/vyper_parsing/test_ast_parsing.py @@ -0,0 +1,26 @@ +from typing import Dict +from pathlib import Path +from slither import Slither + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" + +ALL_TESTS = list(Path(TEST_DATA_DIR).glob("*.vy")) + + +def pytest_generate_tests(metafunc): + test_cases = [] + for test_file in ALL_TESTS: + sl = Slither(test_file.as_posix()) + for contract in sl.contracts: + if contract.is_interface: + continue + for func_or_modifier in contract.functions: + test_cases.append( + (func_or_modifier.canonical_name, func_or_modifier.slithir_cfg_to_dot_str()) + ) + + metafunc.parametrize("test_case", test_cases, ids=lambda x: x[0]) + + +def test_vyper_cfgir(test_case, snapshot): + assert snapshot() == test_case[1] diff --git a/tests/e2e/vyper_parsing/test_data/ERC20.vy b/tests/e2e/vyper_parsing/test_data/ERC20.vy new file mode 100644 index 000000000..682b8cf26 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/ERC20.vy @@ -0,0 +1,22 @@ + + +interface ERC20: + + def totalSupply() -> uint256: view + + + + def balanceOf(_owner: address) -> uint256: view + + + + def allowance(_owner: address, _spender: address) -> uint256: view + + + def transfer(_to: address, _value: uint256) -> bool: nonpayable + + + def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable + + + def approve(_spender: address, _value: uint256) -> bool: nonpayable diff --git a/tests/e2e/vyper_parsing/test_data/builtins.vy b/tests/e2e/vyper_parsing/test_data/builtins.vy new file mode 100644 index 000000000..4fb908a09 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/builtins.vy @@ -0,0 +1,31 @@ + +@payable +@external +def test_builtins(): + a: address = block.coinbase + + b: uint256 = block.difficulty + + c: uint256 = block.prevrandao + + d: uint256 = block.number + + e: bytes32 = block.prevhash + + f: uint256 = block.timestamp + + h: uint256 = chain.id + + i: Bytes[32] = slice(msg.data, 0, 32) + + j: uint256 = msg.gas + + k: address = msg.sender + + l: uint256 = msg.value + + m: address = tx.origin + + n: uint256 = tx.gasprice + + x: uint256 = self.balance diff --git a/tests/e2e/vyper_parsing/test_data/chain.vy b/tests/e2e/vyper_parsing/test_data/chain.vy new file mode 100644 index 000000000..81a770479 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/chain.vy @@ -0,0 +1,4 @@ + +@external +def test(): + x: bytes32 = convert(chain.id, bytes32) \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/for.vy b/tests/e2e/vyper_parsing/test_data/for.vy new file mode 100644 index 000000000..b9f09bf6f --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/for.vy @@ -0,0 +1,32 @@ + + +x: constant(uint256) = 1 + 1 +MAX_QUEUE: constant(uint256) = 1 + x + +interface IStrategy: + def asset() -> address: view + def balanceOf(owner: address) -> uint256: view + def maxDeposit(receiver: address) -> uint256: view + def maxWithdraw(owner: address) -> uint256: view + def withdraw(amount: uint256, receiver: address, owner: address) -> uint256: nonpayable + def redeem(shares: uint256, receiver: address, owner: address) -> uint256: nonpayable + def deposit(assets: uint256, receiver: address) -> uint256: nonpayable + def totalAssets() -> (uint256): view + def convertToAssets(shares: uint256) -> uint256: view + def convertToShares(assets: uint256) -> uint256: view + def previewWithdraw(assets: uint256) -> uint256: view + + + + +struct X: + y: int8 + +strategies: public(DynArray[address, MAX_QUEUE]) + +@external +def for_loop(): + + for strategy in self.strategies: + z: address = IStrategy(strategy).asset() + diff --git a/tests/e2e/vyper_parsing/test_data/for2.vy b/tests/e2e/vyper_parsing/test_data/for2.vy new file mode 100644 index 000000000..f129e56b7 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/for2.vy @@ -0,0 +1,26 @@ + + +x: constant(uint256) = 1 + 1 +MAX_QUEUE: constant(uint256) = 1 + x + +interface IStrategy: + def asset() -> address: view + def balanceOf(owner: address) -> uint256: view + def maxDeposit(receiver: address) -> uint256: view + def maxWithdraw(owner: address) -> uint256: view + def withdraw(amount: uint256, receiver: address, owner: address) -> uint256: nonpayable + def redeem(shares: uint256, receiver: address, owner: address) -> uint256: nonpayable + def deposit(assets: uint256, receiver: address) -> uint256: nonpayable + def totalAssets() -> (uint256): view + def convertToAssets(shares: uint256) -> uint256: view + def convertToShares(assets: uint256) -> uint256: view + def previewWithdraw(assets: uint256) -> uint256: view + +@external +def for_loop(strategies: DynArray[address, MAX_QUEUE]): + _strategies: DynArray[address, MAX_QUEUE] = strategies + + for i in range(10): + + max_withdraw: uint256 = IStrategy(_strategies[i]).maxWithdraw(self) + diff --git a/tests/e2e/vyper_parsing/test_data/for3.vy b/tests/e2e/vyper_parsing/test_data/for3.vy new file mode 100644 index 000000000..4b55b6970 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/for3.vy @@ -0,0 +1,6 @@ + +@external +def get_D(_xp: uint256[3], _amp: uint256): + S: uint256 = 0 + for x in _xp: + S += x \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/if.vy b/tests/e2e/vyper_parsing/test_data/if.vy new file mode 100644 index 000000000..23483ca45 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/if.vy @@ -0,0 +1,25 @@ +@external +@view +def limit_p_o(p: uint256): + p_new: uint256 = p + dt: uint256 = 1 + ratio: uint256 = 0 + + if dt > 0: + old_p_o: uint256 = 1 + old_ratio: uint256 = 2 + # ratio = p_o_min / p_o_max + if p > old_p_o: + ratio = unsafe_div(old_p_o * 10**18, p) + if ratio < 10**36 / 1: + p_new = unsafe_div(old_p_o * 1, 10**18) + ratio = 10**36 / 1 + else: + ratio = unsafe_div(p * 10**18, old_p_o) + if ratio < 10**36 / 1: + p_new = unsafe_div(old_p_o * 10**18, 1) + ratio = 10**36 / 1 + + # ratio is guaranteed to be less than 1e18 + # Also guaranteed to be limited, therefore can have all ops unsafe + ratio = 1 diff --git a/tests/e2e/vyper_parsing/test_data/in.vy b/tests/e2e/vyper_parsing/test_data/in.vy new file mode 100644 index 000000000..e08f71a74 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/in.vy @@ -0,0 +1,23 @@ +enum Roles: + A + B + +roles: public(HashMap[address, Roles]) + +@external +def bar(x: Roles) -> bool: + a: int128 = 0 + b: int128 = 0 + + if x in self.roles[self]: + return True + return False + +@external +def foo(x: int128) -> bool: + a: int128 = 0 + b: int128 = 0 + + if x in [a, b]: + return True + return False \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/initarry.vy b/tests/e2e/vyper_parsing/test_data/initarry.vy new file mode 100644 index 000000000..bfbd29a27 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/initarry.vy @@ -0,0 +1,17 @@ +interface ERC20: + def transfer(_to: address, _value: uint256) -> bool: nonpayable + def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable + def approve(_spender: address, _value: uint256) -> bool: nonpayable + +BORROWED_TOKEN: immutable(ERC20) # x +COLLATERAL_TOKEN: immutable(ERC20) # x + +@external +def __init__(x: address, y: address): + BORROWED_TOKEN = ERC20(x) + COLLATERAL_TOKEN = ERC20(y) + +@external +@pure +def coins(i: uint256) -> address: + return [BORROWED_TOKEN.address, COLLATERAL_TOKEN.address][i] \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/literal.vy b/tests/e2e/vyper_parsing/test_data/literal.vy new file mode 100644 index 000000000..e0686301e --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/literal.vy @@ -0,0 +1,20 @@ +name: public(String[64]) +symbol: public(String[32]) +decimals: public(uint256) +totalSupply: public(uint256) + + + + +balances: HashMap[address, uint256] +allowances: HashMap[address, HashMap[address, uint256]] + + +MAX_BANDS: constant(uint256) = 10 + +x: public(uint256[3][4]) +y: public(uint256[2]) + +struct Loan: + liquidation_range: DynArray[uint256, MAX_BANDS] + deposit_amounts: DynArray[uint256, MAX_BANDS] \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/precedence.vy b/tests/e2e/vyper_parsing/test_data/precedence.vy new file mode 100644 index 000000000..ec8618663 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/precedence.vy @@ -0,0 +1,13 @@ +@internal +def fa() -> uint256: + return 1 + +@internal +def fb() -> uint256: + raise + +@external +def foo(x: uint256) -> bool: + return x not in [self.fa(), self.fb()] + + diff --git a/tests/e2e/vyper_parsing/test_data/struct.vy b/tests/e2e/vyper_parsing/test_data/struct.vy new file mode 100644 index 000000000..97c6f5589 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/struct.vy @@ -0,0 +1,7 @@ +struct X: + y: int8 + + +@external +def test() -> X: + return X({y: 1}) diff --git a/tests/e2e/vyper_parsing/test_data/tricky.vy b/tests/e2e/vyper_parsing/test_data/tricky.vy new file mode 100644 index 000000000..83b19cb89 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/tricky.vy @@ -0,0 +1,15 @@ +interface LMGauge: + def callback_collateral_shares(n: int256, collateral_per_share: DynArray[uint256, MAX_TICKS_UINT]): nonpayable + def callback_user_shares(user: address, n: int256, user_shares: DynArray[uint256, MAX_TICKS_UINT]): nonpayable + + +MAX_TICKS_UINT: constant(uint256) = 50 + + +struct Loan: + liquidation_range: LMGauge + +x: public(Loan) + + +# TODO Will this overly complicate analyzing AST https://github.com/vyperlang/vyper/pull/3411 \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/tuple.vy b/tests/e2e/vyper_parsing/test_data/tuple.vy new file mode 100644 index 000000000..f0c7e66fe --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/tuple.vy @@ -0,0 +1,19 @@ + + +interface Test: + def foo() -> (int128, uint256): nonpayable + +@internal +def foo() -> (int128, int128): + return 2, 3 + +@external +def bar(): + a: int128 = 0 + b: int128 = 0 + (a, b) = self.foo() + + x: address = 0x0000000000000000000000000000000000000000 + c: uint256 = 0 + a, c = Test(x).foo() + From 08af1ee9e5edf1ccb8392bc415626b9dc8a9c762 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 12:42:02 -0500 Subject: [PATCH 204/338] cleanup FunctionVyper --- .../vyper_parsing/declarations/function.py | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 98c372808..17bbf6910 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -19,6 +19,7 @@ from slither.vyper_parsing.ast.types import * if TYPE_CHECKING: from slither.core.compilation_unit import SlitherCompilationUnit + from slither.vyper_parsing.declarations.contract import ContractVyper def link_underlying_nodes(node1: NodeVyper, node2: NodeVyper): @@ -40,8 +41,9 @@ class FunctionVyper: self._function.name = function_data.name self._function.id = function_data.node_id - self._local_variables_parser: List = [] + self._local_variables_parser: List[LocalVariableVyper] = [] self._contract_parser = contract_parser + self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} for decorator in function_data.decorators: if not hasattr(decorator, "id"): @@ -54,6 +56,8 @@ class FunctionVyper: self._function.pure = True elif decorator.id == "payable": self._function.payable = True + elif decorator.id == "nonpayable": + self._function.payable = False else: raise ValueError(f"Unknown decorator {decorator.id}") # Interfaces do not have decorators and are external @@ -64,24 +68,9 @@ class FunctionVyper: self._content_was_analyzed = False self._counter_scope_local_variables = 0 - # # variable renamed will map the solc id - # # to the variable. It only works for compact format - # # Later if an expression provides the referencedDeclaration attr - # # we can retrieve the variable - # # It only matters if two variables have the same name in the function - # # which is only possible with solc > 0.5 - # self._variables_renamed: Dict[ - # int, Union[LocalVariableVyper, LocalVariableInitFromTupleSolc] - # ] = {} self._analyze_function_type() - # self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} - # self._node_to_yulobject: Dict[Node, YulBlock] = {} - - # self._local_variables_parser: List[ - # Union[LocalVariableVyper, LocalVariableInitFromTupleSolc] - # ] = [] if function_data.doc_string is not None: function.has_documentation = True @@ -107,12 +96,9 @@ class FunctionVyper: return self._variables_renamed def _add_local_variable(self, local_var_parser: LocalVariableVyper) -> None: - # If two local variables have the same name - # We add a suffix to the new variable - # This is done to prevent collision during SSA translation - # Use of while in case of collision - # In the worst case, the name will be really long - # TODO no shadowing? + # Ensure variables name are unique for SSA conversion + # This should not apply to actual Vyper variables currently + # but is necessary if we have nested loops where we've created artificial variables e.g. counter_var if local_var_parser.underlying_variable.name: known_variables = [v.name for v in self._function.variables] while local_var_parser.underlying_variable.name in known_variables: From f9633ca67a25a0b5850a66fdbc3330b91babb271 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 13:34:16 -0500 Subject: [PATCH 205/338] fix name resolution for shadowed state variable --- slither/core/expressions/__init__.py | 1 + slither/core/expressions/self_identifier.py | 6 ++++++ .../expressions/expression_parsing.py | 17 +++++++---------- .../vyper_parsing/expressions/find_variable.py | 13 +++++++------ ...ast_parsing__vyper_cfgir_for_for_loop__0.txt | 2 +- ...t_parsing__vyper_cfgir_precedence_foo__0.txt | 2 +- .../ast_parsing__vyper_cfgir_tuple_bar__0.txt | 2 +- .../test_data/src_mapping/SelfIdentifier.vy | 4 ++++ tests/unit/core/test_source_mapping.py | 13 +++++++++++++ 9 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 slither/core/expressions/self_identifier.py create mode 100644 tests/unit/core/test_data/src_mapping/SelfIdentifier.vy diff --git a/slither/core/expressions/__init__.py b/slither/core/expressions/__init__.py index 42554bf0b..b162481ba 100644 --- a/slither/core/expressions/__init__.py +++ b/slither/core/expressions/__init__.py @@ -12,6 +12,7 @@ from .new_contract import NewContract from .new_elementary_type import NewElementaryType from .super_call_expression import SuperCallExpression from .super_identifier import SuperIdentifier +from .self_identifier import SelfIdentifier from .tuple_expression import TupleExpression from .type_conversion import TypeConversion from .unary_operation import UnaryOperation, UnaryOperationType diff --git a/slither/core/expressions/self_identifier.py b/slither/core/expressions/self_identifier.py new file mode 100644 index 000000000..b86d70baf --- /dev/null +++ b/slither/core/expressions/self_identifier.py @@ -0,0 +1,6 @@ +from slither.core.expressions.identifier import Identifier + + +class SelfIdentifier(Identifier): + def __str__(self): + return "self." + str(self._value) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index bebbf3b9e..9996df8a8 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -20,7 +20,7 @@ from slither.core.expressions import ( NewContract, NewElementaryType, SuperCallExpression, - SuperIdentifier, + SelfIdentifier, TupleExpression, TypeConversion, UnaryOperation, @@ -42,7 +42,7 @@ from slither.core.solidity_types import ( from slither.core.declarations.contract import Contract from slither.vyper_parsing.expressions.find_variable import find_variable from slither.vyper_parsing.type_parsing import parse_type - +from slither.all_exceptions import ParsingError if TYPE_CHECKING: from slither.core.expressions.expression import Expression @@ -237,14 +237,14 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Attribute): member_name = expression.attr if isinstance(expression.value, Name): - print(expression) + # TODO this is ambiguous because it could be a state variable or a call to balance if expression.value.id == "self" and member_name != "balance": - var, was_created = find_variable(member_name, caller_context) - # TODO replace with self + var, was_created = find_variable(member_name, caller_context, is_self=True) if was_created: var.set_offset(expression.src, caller_context.compilation_unit) - parsed_expr = SuperIdentifier(var) + parsed_expr = SelfIdentifier(var) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + var.references.append(parsed_expr.source_mapping) return parsed_expr expr = parse_expression(expression.value, caller_context) @@ -267,12 +267,11 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` - # TODO this is using the wrong caller_context and needs to be interface instead of self namespace print(expr) print(expr.__class__.__name__) if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType): - # try: + # If we access a member of an interface, needs to be interface instead of self namespace var, was_created = find_variable(member_name, expr.type.type) if isinstance(var, Function): rets = var.returns @@ -288,8 +287,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else f"tuple({','.join(map(get_type_str, rets))})" ) member_name_ret_type = type_str - # except: - # pass member_access = MemberAccess(member_name, member_name_ret_type, expr) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 1b9f0de87..e888aa014 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -28,7 +28,6 @@ if TYPE_CHECKING: from slither.vyper_parsing.declarations.function import FunctionVyper - def _find_variable_in_function_parser( var_name: str, function_parser: Optional["FunctionVyper"], @@ -86,6 +85,7 @@ def _find_in_contract( def find_variable( var_name: str, caller_context, + is_self: bool = False, ) -> Tuple[ Union[ Variable, @@ -96,8 +96,6 @@ def find_variable( Event, Enum, Structure, - CustomError, - TypeAlias, ], bool, ]: @@ -136,9 +134,12 @@ def find_variable( caller_context if isinstance(caller_context, FunctionContract) else None ) # print("function_parser", function_parser) - ret1 = _find_variable_in_function_parser(var_name, function_parser) - if ret1: - return ret1, False + # If a local shadows a state variable but the attribute is `self`, we want to + # return the state variable and not the local. + if not is_self: + ret1 = _find_variable_in_function_parser(var_name, function_parser) + if ret1: + return ret1, False ret = _find_in_contract(var_name, next_context, caller_context) if ret: diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt index 210c5cec5..5c4123662 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt @@ -16,7 +16,7 @@ counter_var(uint256) := 0(uint256)"]; 3[label="Node Type: IF_LOOP 3 EXPRESSION: -counter_var <= len()(super.strategies) +counter_var <= len()(self.strategies) IRs: TMP_0(uint256) = SOLIDITY_CALL len()(strategies) diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt index 802e03ad1..2355fd513 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt @@ -5,7 +5,7 @@ digraph{ 1[label="Node Type: RETURN 1 EXPRESSION: -x != super.fb() && x != super.fa() +x != self.fb() && x != self.fa() IRs: TMP_0(uint256) = INTERNAL_CALL, precedence.fb()() diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt index 35b37282c..0d2540498 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt @@ -21,7 +21,7 @@ b(int128) := 0(uint256)"]; 3[label="Node Type: EXPRESSION 3 EXPRESSION: -(a,b) = super.foo() +(a,b) = self.foo() IRs: TUPLE_0(int128,int128) = INTERNAL_CALL, tuple.foo()() diff --git a/tests/unit/core/test_data/src_mapping/SelfIdentifier.vy b/tests/unit/core/test_data/src_mapping/SelfIdentifier.vy new file mode 100644 index 000000000..5607fb943 --- /dev/null +++ b/tests/unit/core/test_data/src_mapping/SelfIdentifier.vy @@ -0,0 +1,4 @@ +name: public(String[64]) +@external +def __init__(name: String[64]): + self.name = name diff --git a/tests/unit/core/test_source_mapping.py b/tests/unit/core/test_source_mapping.py index fe5335977..16a26215b 100644 --- a/tests/unit/core/test_source_mapping.py +++ b/tests/unit/core/test_source_mapping.py @@ -113,3 +113,16 @@ def test_references_user_defined_types_when_casting(solc_binary_path): assert len(a.references) == 2 lines = _sort_references_lines(a.references) assert lines == [12, 18] + +def test_references_self_identifier(): + """ + Tests that shadowing state variables with local variables does not affect references. + """ + file = Path(SRC_MAPPING_TEST_ROOT, "SelfIdentifier.vy").as_posix() + slither = Slither(file) + + contracts = slither.compilation_units[0].contracts + a = contracts[0].state_variables[0] + assert len(a.references) == 1 + lines = _sort_references_lines(a.references) + assert lines == [4] \ No newline at end of file From 2dbb912bb72278c5e15047f95bccfb219e310396 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 13:46:26 -0500 Subject: [PATCH 206/338] correctly set indexed attribute for event variables --- slither/vyper_parsing/variables/event_variable.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/slither/vyper_parsing/variables/event_variable.py b/slither/vyper_parsing/variables/event_variable.py index 10b8aa06c..2dc5db544 100644 --- a/slither/vyper_parsing/variables/event_variable.py +++ b/slither/vyper_parsing/variables/event_variable.py @@ -2,7 +2,7 @@ from typing import Dict from slither.core.variables.event_variable import EventVariable from slither.vyper_parsing.type_parsing import parse_type -from slither.vyper_parsing.ast.types import AnnAssign +from slither.vyper_parsing.ast.types import AnnAssign, Call class EventVariableVyper: @@ -10,7 +10,10 @@ class EventVariableVyper: print(variable_data) self._variable = variable self._variable.name = variable_data.target.id - # TODO self._variable.indexed + if isinstance(variable_data.annotation, Call) and variable_data.annotation.func.id == "indexed": + self._variable.indexed = True + else: + self._variable.indexed = False self._elem_to_parse = variable_data.annotation @property From f7ef48401ed8d8c51956dcaaa1842c953b511a8a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 15:53:03 -0500 Subject: [PATCH 207/338] very simplistic support for reentrancy lock --- slither/core/declarations/function.py | 4 +- .../vyper_parsing/declarations/function.py | 72 +++++++++++++------ tests/unit/core/test_function_declaration.py | 4 +- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index 0f1955a92..e9f9552e9 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -1499,7 +1499,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu Determine if the function can be re-entered """ # TODO: compare with hash of known nonReentrant modifier instead of the name - if "nonReentrant" in [m.name for m in self.modifiers]: + if "nonReentrant" in [m.name for m in self.modifiers] or "nonreentrant(lock)" in [ + m.name for m in self.modifiers + ]: return False if self.visibility in ["public", "external"]: diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 17bbf6910..850ff08b6 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -8,7 +8,8 @@ from slither.core.declarations.function import ( Function, FunctionType, ) -from slither.core.declarations.function_contract import FunctionContract +from slither.core.declarations.function import ModifierStatements +from slither.core.declarations.modifier import Modifier from slither.core.expressions import AssignmentOperation from slither.core.source_mapping.source_mapping import Source from slither.core.variables.local_variable import LocalVariable @@ -33,48 +34,47 @@ class FunctionVyper: function_data: Dict, contract_parser: "ContractVyper", ) -> None: - self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} self._function = function - print(function_data.name) - print(function_data) self._function.name = function_data.name self._function.id = function_data.node_id - + self._functionNotParsed = function_data + self._decoratorNotParsed = None self._local_variables_parser: List[LocalVariableVyper] = [] self._contract_parser = contract_parser self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} for decorator in function_data.decorators: - if not hasattr(decorator, "id"): - continue # TODO isinstance Name - if decorator.id in ["external", "public", "internal"]: - self._function.visibility = decorator.id - elif decorator.id == "view": - self._function.view = True - elif decorator.id == "pure": - self._function.pure = True - elif decorator.id == "payable": - self._function.payable = True - elif decorator.id == "nonpayable": - self._function.payable = False + if isinstance(decorator, Call): + # TODO handle multiple + self._decoratorNotParsed = decorator + elif isinstance(decorator, Name): + if decorator.id in ["external", "public", "internal"]: + self._function.visibility = decorator.id + elif decorator.id == "view": + self._function.view = True + elif decorator.id == "pure": + self._function.pure = True + elif decorator.id == "payable": + self._function.payable = True + elif decorator.id == "nonpayable": + self._function.payable = False else: raise ValueError(f"Unknown decorator {decorator.id}") + # Interfaces do not have decorators and are external if self._function._visibility is None: self._function.visibility = "external" - self._functionNotParsed = function_data + self._params_was_analyzed = False self._content_was_analyzed = False - self._counter_scope_local_variables = 0 - self._analyze_function_type() - - if function_data.doc_string is not None: function.has_documentation = True + self._analyze_function_type() + @property def underlying_function(self) -> Function: return self._function @@ -166,6 +166,34 @@ class FunctionVyper: for node_parser in self._node_to_NodeVyper.values(): node_parser.analyze_expressions(self._function) + self._analyze_decorator() + + def _analyze_decorator(self) -> None: + if not self._decoratorNotParsed: + return + + decorator = self._decoratorNotParsed + if decorator.args: + name = f"{decorator.func.id}({decorator.args[0].value})" + else: + name = decorator.func.id + + contract = self._contract_parser.underlying_contract + compilation_unit = self._contract_parser.underlying_contract.compilation_unit + modifier = Modifier(compilation_unit) + modifier._name = name + modifier.set_offset(decorator.src, compilation_unit) + modifier.set_contract(contract) + modifier.set_contract_declarer(contract) + latest_entry_point = self._function.entry_point + self._function.add_modifier( + ModifierStatements( + modifier=modifier, + entry_point=latest_entry_point, + nodes=[latest_entry_point], + ) + ) + # endregion ################################################################################### ################################################################################### diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index 739a113bc..2dc8192a1 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -368,8 +368,8 @@ def __default__(): assert f.can_send_eth() assert f.can_reenter() - # f = functions["withdraw_locked()"] - # assert not f.can_reenter() + f = functions["withdraw_locked()"] + assert not f.is_reentrant var = contract.get_state_variable_from_name("balances") assert var From 4b10a0fa18e7604aed6a5e8076a056e4977caafc Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 15:54:26 -0500 Subject: [PATCH 208/338] delete commented out code --- slither/__main__.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index e68f0b67f..ab15c72d8 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -870,12 +870,6 @@ def main_impl( logging.error(red(output_error)) logging.error("Please report an issue to https://github.com/crytic/slither/issues") - # except Exception: # pylint: disable=broad-except - # output_error = traceback.format_exc() - # traceback.print_exc() - # logging.error(f"Error in {args.filename}") # pylint: disable=logging-fstring-interpolation - # logging.error(output_error) - # If we are outputting JSON, capture the redirected output and disable the redirect to output the final JSON. if outputting_json: if "console" in args.json_types: From e561d33eb18e086fe4da751cd86cfa1c1e1ebf7b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 31 Aug 2023 17:37:30 -0500 Subject: [PATCH 209/338] try removing trailing comment --- tests/e2e/vyper_parsing/test_data/tricky.vy | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/e2e/vyper_parsing/test_data/tricky.vy b/tests/e2e/vyper_parsing/test_data/tricky.vy index 83b19cb89..4a5b71851 100644 --- a/tests/e2e/vyper_parsing/test_data/tricky.vy +++ b/tests/e2e/vyper_parsing/test_data/tricky.vy @@ -9,7 +9,4 @@ MAX_TICKS_UINT: constant(uint256) = 50 struct Loan: liquidation_range: LMGauge -x: public(Loan) - - -# TODO Will this overly complicate analyzing AST https://github.com/vyperlang/vyper/pull/3411 \ No newline at end of file +x: public(Loan) \ No newline at end of file From 3ca9d0f2287742bc8f57afbbaa1f6977966710dd Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 1 Sep 2023 19:50:56 -0500 Subject: [PATCH 210/338] convert tuple on lhs and index access to struct and field access --- .../visitors/slithir/expression_to_slithir.py | 46 +++++++++++++++++++ slither/vyper_parsing/type_parsing.py | 28 ++++++++++- .../vyper_parsing/variables/local_variable.py | 4 +- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 5a6c7de59..fa8cef8e3 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -11,6 +11,7 @@ from slither.core.declarations import ( EnumContract, EnumTopLevel, Enum, + Structure, ) from slither.core.expressions import ( AssignmentOperation, @@ -233,6 +234,35 @@ class ExpressionToSlithIR(ExpressionVisitor): operation.set_expression(expression) self._result.append(operation) set_val(expression, left) + + elif ( + isinstance(left.type, UserDefinedType) + and isinstance(left.type.type, Structure) + and isinstance(right, TupleVariable) + ): + # This will result in a `NewStructure` operation where + # each field is assigned the value unpacked from the tuple + # (see `slither.vyper_parsing.type_parsing.parse_type`) + args = [] + for idx, elem in enumerate(left.type.type.elems.values()): + temp = TemporaryVariable(self._node) + temp.type = elem.type + args.append(temp) + operation = Unpack(temp, right, idx) + operation.set_expression(expression) + self._result.append(operation) + + for arg in args: + op = Argument(arg) + op.set_expression(expression) + self._result.append(op) + + operation = TmpCall( + left.type.type, len(left.type.type.elems), left, left.type.type.name + ) + operation.set_expression(expression) + self._result.append(operation) + else: operation = convert_assignment( left, right, expression.type, expression.expression_return_type @@ -417,6 +447,21 @@ class ExpressionToSlithIR(ExpressionVisitor): set_val(expression, t) return val = ReferenceVariable(self._node) + + if ( + isinstance(left, LocalVariable) + and isinstance(left.type, UserDefinedType) + and isinstance(left.type.type, Structure) + ): + # We rewrite the index access to a tuple variable as + # an access to its field i.e. the 0th element is the field "_0" + # (see `slither.vyper_parsing.type_parsing.parse_type`) + operation = Member(left, Constant("_" + str(right)), val) + operation.set_expression(expression) + self._result.append(operation) + set_val(expression, val) + return + # access to anonymous array # such as [0,1][x] if isinstance(left, list): @@ -426,6 +471,7 @@ class ExpressionToSlithIR(ExpressionVisitor): operation = InitArray(init_array_right, init_array_val) operation.set_expression(expression) self._result.append(operation) + operation = Index(val, left, right) operation.set_expression(expression) self._result.append(operation) diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index a7d83240e..fc45a144c 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -20,7 +20,7 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): else: contract = caller_context - assert isinstance(annotation, (Name, Subscript, Call)) + assert isinstance(annotation, (Name, Subscript, Call, Tuple)) print(annotation) if isinstance(annotation, Name): name = annotation.id @@ -54,12 +54,36 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): return ArrayType(type_, length) elif isinstance(annotation, Call): + # TODO event variable represented as Call return parse_type(annotation.args[0], caller_context) + elif isinstance(annotation, Tuple): + # Vyper has tuple types like python x = f() where f() -> (y,z) + # and tuple elements can be unpacked like x[0]: y and x[1]: z. + # We model these as a struct and unpack each index into a field + # e.g. accessing the 0th element is translated as x._0 + from slither.core.declarations.structure import Structure + from slither.core.variables.structure_variable import StructureVariable + + st = Structure(caller_context.compilation_unit) + st.set_offset("-1:-1:-1", caller_context.compilation_unit) + st.name = "FAKE_TUPLE" + for idx, elem_info in enumerate(annotation.elements): + elem = StructureVariable() + elem.type = parse_type(elem_info, caller_context) + elem.name = f"_{idx}" + elem.set_structure(st) + elem.set_offset("-1:-1:-1", caller_context.compilation_unit) + st.elems[elem.name] = elem + st.add_elem_in_order(elem.name) + st.name += elem.name + + return UserDefinedType(st) + else: assert False - lname = name.lower() # todo map String to string + lname = name.lower() # TODO map String to string if lname in ElementaryTypeName: return ElementaryType(lname) diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py index d3bd0b055..918ec344c 100644 --- a/slither/vyper_parsing/variables/local_variable.py +++ b/slither/vyper_parsing/variables/local_variable.py @@ -1,7 +1,7 @@ from typing import Union from slither.core.variables.local_variable import LocalVariable -from slither.vyper_parsing.ast.types import Arg, Name, AnnAssign, Subscript, Call +from slither.vyper_parsing.ast.types import Arg, Name, AnnAssign, Subscript, Call, Tuple from slither.vyper_parsing.type_parsing import parse_type @@ -23,7 +23,7 @@ class LocalVariableVyper: self._variable.name = "" self._elem_to_parse = variable_data - assert isinstance(self._elem_to_parse, (Name, Subscript, Call)) + assert isinstance(self._elem_to_parse, (Name, Subscript, Call, Tuple)) self._variable.set_location("default") From 47e274c907bf5dfcb174b9caf01f6e169a972b5b Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 1 Sep 2023 19:57:11 -0500 Subject: [PATCH 211/338] consider function unimplemented if body is only pass --- slither/vyper_parsing/declarations/function.py | 5 ++++- tests/unit/core/test_function_declaration.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 850ff08b6..c79b7a9e4 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -156,9 +156,11 @@ class FunctionVyper: body = self._functionNotParsed.body - if body: + if body and not isinstance(body[0], Pass): self._function.is_implemented = True self._parse_cfg(body) + else: + self._function.is_implemented = False for local_var_parser in self._local_variables_parser: local_var_parser.analyze(self._function) @@ -462,6 +464,7 @@ class FunctionVyper: pass elif isinstance(expr, Raise): print(expr) + # TODO # assert False pass else: diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index 2dc8192a1..c4844074e 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -351,6 +351,7 @@ def __default__(): assert not f.payable assert not f.view assert not f.pure + assert not f.is_implemented f = functions["__default__()"] assert f.function_type == FunctionType.FALLBACK @@ -358,6 +359,7 @@ def __default__(): assert f.payable assert not f.view assert not f.pure + assert not f.is_implemented f = functions["withdraw()"] assert f.function_type == FunctionType.NORMAL @@ -367,9 +369,11 @@ def __default__(): assert not f.pure assert f.can_send_eth() assert f.can_reenter() + assert f.is_implemented f = functions["withdraw_locked()"] assert not f.is_reentrant + assert f.is_implemented var = contract.get_state_variable_from_name("balances") assert var From 66def310e7717a3c665fd9b13aa9fe5ee0e42b68 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 1 Sep 2023 22:15:29 -0500 Subject: [PATCH 212/338] do not considered local variable that are reference types as `in_storage` --- slither/slithir/convert.py | 4 +++- slither/vyper_parsing/variables/local_variable.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index d1eaafdfa..8bb20412b 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -576,7 +576,9 @@ def propagate_types(ir: Operation, node: "Node"): # pylint: disable=too-many-lo if isinstance(t, ArrayType) or ( isinstance(t, ElementaryType) and t.type == "bytes" ): - if ir.function_name == "push" and len(ir.arguments) <= 1: + # Solidity uses push + # Vyper uses append + if ir.function_name in ["push", "append"] and len(ir.arguments) <= 1: return convert_to_push(ir, node) if ir.function_name == "pop" and len(ir.arguments) == 0: return convert_to_pop(ir, node) diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py index 918ec344c..b50dea44b 100644 --- a/slither/vyper_parsing/variables/local_variable.py +++ b/slither/vyper_parsing/variables/local_variable.py @@ -25,7 +25,9 @@ class LocalVariableVyper: assert isinstance(self._elem_to_parse, (Name, Subscript, Call, Tuple)) - self._variable.set_location("default") + # Vyper does not have data locations or storage pointers. + # If this was left as default, reference types would be considered storage by `LocalVariable.is_storage` + self._variable.set_location("memory") @property def underlying_variable(self) -> LocalVariable: From e287b2f905b2b3abb536e93e8ea79f9b030f145c Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 1 Sep 2023 23:10:13 -0500 Subject: [PATCH 213/338] fix phi placement by calling SlitherCompilationUnit.add_function --- slither/core/compilation_unit.py | 4 ++++ slither/vyper_parsing/declarations/contract.py | 6 +++++- tests/unit/slithir/vyper/test_ir_generation.py | 15 +++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 8e801ea95..556c6c7da 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -189,6 +189,10 @@ class SlitherCompilationUnit(Context): return self.functions + list(self.modifiers) def propagate_function_calls(self) -> None: + """This info is used to compute the rvalues of Phi operations in `fix_phi` and ultimately + is responsible for the `read` property of Phi operations which is vital to + propagating taints inter-procedurally + """ for f in self.functions_and_modifiers: for node in f.nodes: for ir in node.irs_ssa: diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index ed61bda1b..0e2140fa1 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -1,4 +1,5 @@ import logging +from pathlib import Path from typing import List, TYPE_CHECKING from slither.vyper_parsing.ast.types import ( Module, @@ -40,7 +41,9 @@ class ContractVyper: self._contract: Contract = contract self._slither_parser: "VyperCompilationUnit" = slither_parser self._data = module - self._contract.name = module.name + # Vyper models only have one contract (aside from interfaces) and the name is the file path + # We use the stem to make it a more user friendly name that is easy to query via canonical name + self._contract.name = Path(module.name).stem self._contract.id = module.node_id self._is_analyzed: bool = False @@ -492,6 +495,7 @@ class ContractVyper: func_parser = FunctionVyper(func, function, self) self._contract.add_function(func) + self._contract.compilation_unit.add_function(func) self._functions_parser.append(func_parser) self._functionsNotParsed = [] diff --git a/tests/unit/slithir/vyper/test_ir_generation.py b/tests/unit/slithir/vyper/test_ir_generation.py index 704e0d27a..2f7c59fd3 100644 --- a/tests/unit/slithir/vyper/test_ir_generation.py +++ b/tests/unit/slithir/vyper/test_ir_generation.py @@ -64,6 +64,7 @@ def bar(): assert contract == interface assert function.signature_str == "foo() returns(int128,uint256)" + def test_phi_entry_point_internal_call(slither_from_vyper_source): with slither_from_vyper_source( """ @@ -78,5 +79,15 @@ def a(x: uint256): self.b(1) """ ) as sl: - b = sl.contracts[0].get_function_from_signature("b(uint256)") - assert len(list(filter(lambda x: isinstance(x, Phi), b.all_slithir_operations()))) == 1 + f = sl.contracts[0].get_function_from_signature("b(uint256)") + assert ( + len( + [ + ssanode + for node in f.nodes + for ssanode in node.irs_ssa + if isinstance(ssanode, Phi) + ] + ) + == 1 + ) From 81cb124e2dad5e0397209835186d7614901eb8ff Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 4 Sep 2023 13:04:52 -0500 Subject: [PATCH 214/338] support default args in calls --- slither/core/declarations/function.py | 2 ++ .../vyper_parsing/declarations/function.py | 5 +-- .../expressions/expression_parsing.py | 11 ++++++ .../unit/slithir/vyper/test_ir_generation.py | 35 +++++++++++++++++-- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index e9f9552e9..a4a172b97 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -138,6 +138,8 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu self._parameters: List["LocalVariable"] = [] self._parameters_ssa: List["LocalIRVariable"] = [] self._parameters_src: SourceMapping = SourceMapping() + # This is used for vyper calls with default arguments + self._default_args_as_expressions: List["Expression"] = [] self._returns: List["LocalVariable"] = [] self._returns_ssa: List["LocalIRVariable"] = [] self._returns_src: SourceMapping = SourceMapping() diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index c79b7a9e4..9ef3a547a 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -31,7 +31,7 @@ class FunctionVyper: def __init__( self, function: Function, - function_data: Dict, + function_data: FunctionDef, contract_parser: "ContractVyper", ) -> None: @@ -503,7 +503,8 @@ class FunctionVyper: print(params) self._function.parameters_src().set_offset(params.src, self._function.compilation_unit) - + if params.defaults: + self._function._default_args_as_expressions = params.defaults for param in params.args: local_var = self._add_param(param) self._function.add_parameters(local_var.underlying_variable) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 9996df8a8..3d3d3e4f5 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -198,6 +198,17 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # Since the AST lacks the type of the return values, we recover it. if isinstance(called.value, Function): rets = called.value.returns + # Default arguments are not represented in the AST, so we recover them as well. + if called.value._default_args_as_expressions and len(arguments) < len( + called.value.parameters + ): + arguments.extend( + [ + parse_expression(x, caller_context) + for x in called.value._default_args_as_expressions + ] + ) + elif isinstance(called.value, SolidityFunction): rets = called.value.return_type elif isinstance(called.value, Contract): diff --git a/tests/unit/slithir/vyper/test_ir_generation.py b/tests/unit/slithir/vyper/test_ir_generation.py index 2f7c59fd3..6bcdaab10 100644 --- a/tests/unit/slithir/vyper/test_ir_generation.py +++ b/tests/unit/slithir/vyper/test_ir_generation.py @@ -10,7 +10,7 @@ import pytest from slither import Slither from slither.core.cfg.node import Node, NodeType from slither.core.declarations import Function, Contract -from slither.core.solidity_types import ArrayType +from slither.core.solidity_types import ArrayType, ElementaryType from slither.core.variables.local_variable import LocalVariable from slither.core.variables.state_variable import StateVariable from slither.slithir.operations import ( @@ -71,7 +71,7 @@ def test_phi_entry_point_internal_call(slither_from_vyper_source): counter: uint256 @internal def b(y: uint256): - self.counter = y # tainted by x, 1 + self.counter = y @external def a(x: uint256): @@ -91,3 +91,34 @@ def a(x: uint256): ) == 1 ) + + +def test_call_with_default_args(slither_from_vyper_source): + with slither_from_vyper_source( + """ +counter: uint256 +@internal +def c(y: uint256, config: bool = True): + self.counter = y +@external +def a(x: uint256): + self.c(x) + self.c(1) +@external +def b(x: uint256): + self.c(x, False) + self.c(1, False) +""" + ) as sl: + a = sl.contracts[0].get_function_from_signature("a(uint256)") + for node in a.nodes: + for op in node.irs_ssa: + if isinstance(op, InternalCall) and op.function.name == "c": + assert len(op.arguments) == 2 + assert op.arguments[1] == Constant("True", ElementaryType("bool")) + b = sl.contracts[0].get_function_from_signature("b(uint256)") + for node in b.nodes: + for op in node.irs_ssa: + if isinstance(op, InternalCall) and op.function.name == "c": + assert len(op.arguments) == 2 + assert op.arguments[1] == Constant("False", ElementaryType("bool")) From 4845a3bd261db99c77aacdbdbc6845fab9f120a8 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 4 Sep 2023 13:49:05 -0500 Subject: [PATCH 215/338] fix and refactor comparison operator, add support for raise --- .../vyper_parsing/declarations/function.py | 429 +++++++++--------- .../expressions/expression_parsing.py | 167 ++++--- .../ast_parsing__vyper_cfgir_in_bar__0.txt | 56 ++- .../ast_parsing__vyper_cfgir_in_baz__0.txt | 66 +++ .../ast_parsing__vyper_cfgir_in_foo__0.txt | 33 +- ..._parsing__vyper_cfgir_precedence_fb__0.txt | 8 + ...parsing__vyper_cfgir_precedence_foo__0.txt | 12 +- tests/e2e/vyper_parsing/test_data/in.vy | 17 +- 8 files changed, 448 insertions(+), 340 deletions(-) create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_baz__0.txt diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 9ef3a547a..f023953fa 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -158,9 +158,11 @@ class FunctionVyper: if body and not isinstance(body[0], Pass): self._function.is_implemented = True + self._function.is_empty = False self._parse_cfg(body) else: self._function.is_implemented = False + self._function.is_empty = True for local_var_parser in self._local_variables_parser: local_var_parser.analyze(self._function) @@ -218,264 +220,257 @@ class FunctionVyper: ################################################################################### ################################################################################### - def _parse_cfg(self, cfg: Dict) -> None: + def _parse_cfg(self, cfg: List[ASTNode]) -> None: entry_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) self._function.entry_point = entry_node.underlying_node scope = Scope(True, False, self.underlying_function) - if cfg: - self._function.is_empty = False - curr_node = entry_node - for expr in cfg: - - def parse_statement(curr_node, expr): - if isinstance(expr, AnnAssign): - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) - - local_var_parser = LocalVariableVyper(local_var, expr) - self._add_local_variable(local_var_parser) - - new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - if expr.value is not None: - local_var.initialized = True - new_node.add_unparsed_expression(expr.value) - new_node.underlying_node.add_variable_declaration(local_var) - link_underlying_nodes(curr_node, new_node) + curr_node = entry_node + for expr in cfg: - curr_node = new_node + def parse_statement(curr_node, expr): + if isinstance(expr, AnnAssign): + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) - elif isinstance(expr, (AugAssign, Assign)): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr) - link_underlying_nodes(curr_node, new_node) + local_var_parser = LocalVariableVyper(local_var, expr) + self._add_local_variable(local_var_parser) - curr_node = new_node + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + if expr.value is not None: + local_var.initialized = True + new_node.add_unparsed_expression(expr.value) + new_node.underlying_node.add_variable_declaration(local_var) + link_underlying_nodes(curr_node, new_node) - elif isinstance(expr, Expr): - # TODO This is a workaround to handle Vyper putting payable/view in the function body... - if not isinstance(expr.value, Name): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr.value) - link_underlying_nodes(curr_node, new_node) + curr_node = new_node - curr_node = new_node + elif isinstance(expr, (AugAssign, Assign)): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) + link_underlying_nodes(curr_node, new_node) - elif isinstance(expr, For): + curr_node = new_node - node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) - link_underlying_nodes(curr_node, node_startLoop) + elif isinstance(expr, Expr): + # TODO This is a workaround to handle Vyper putting payable/view in the function body... + if not isinstance(expr.value, Name): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) + link_underlying_nodes(curr_node, new_node) - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) + curr_node = new_node - counter_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=Name("-1:-1:-1", -1, "counter_var"), - annotation=Name("-1:-1:-1", -1, "uint256"), - value=Int("-1:-1:-1", -1, 0), - ) - local_var_parser = LocalVariableVyper(local_var, counter_var) - self._add_local_variable(local_var_parser) - counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - local_var.initialized = True - counter_node.add_unparsed_expression(counter_var.value) - counter_node.underlying_node.add_variable_declaration(local_var) - - link_underlying_nodes(node_startLoop, counter_node) - - node_condition = None - if isinstance(expr.iter, (Attribute, Name)): - # HACK - # The loop variable is not annotated so we infer its type by looking at the type of the iterator - if isinstance(expr.iter, Attribute): # state variable - iter_expr = expr.iter - loop_iterator = list( - filter( - lambda x: x._variable.name == iter_expr.attr, - self._contract_parser._variables_parser, - ) - )[0] - - else: # local variable - iter_expr = expr.iter - loop_iterator = list( - filter( - lambda x: x._variable.name == iter_expr.id, - self._local_variables_parser, - ) - )[0] - - # TODO use expr.src instead of -1:-1:1? - cond_expr = Compare( - "-1:-1:-1", - -1, - left=Name("-1:-1:-1", -1, "counter_var"), - op="<=", - right=Call( - "-1:-1:-1", - -1, - func=Name("-1:-1:-1", -1, "len"), - args=[iter_expr], - keywords=[], - keyword=None, - ), - ) - node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) - node_condition.add_unparsed_expression(cond_expr) - - if loop_iterator._elem_to_parse.value.id == "DynArray": - loop_var_annotation = ( - loop_iterator._elem_to_parse.slice.value.elements[0] + elif isinstance(expr, For): + + node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + link_underlying_nodes(curr_node, node_startLoop) + + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + + counter_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=Name("-1:-1:-1", -1, "counter_var"), + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Int("-1:-1:-1", -1, 0), + ) + local_var_parser = LocalVariableVyper(local_var, counter_var) + self._add_local_variable(local_var_parser) + counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + local_var.initialized = True + counter_node.add_unparsed_expression(counter_var.value) + counter_node.underlying_node.add_variable_declaration(local_var) + + link_underlying_nodes(node_startLoop, counter_node) + + node_condition = None + if isinstance(expr.iter, (Attribute, Name)): + # HACK + # The loop variable is not annotated so we infer its type by looking at the type of the iterator + if isinstance(expr.iter, Attribute): # state variable + iter_expr = expr.iter + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.attr, + self._contract_parser._variables_parser, ) - else: - loop_var_annotation = loop_iterator._elem_to_parse.value + )[0] + + else: # local variable + iter_expr = expr.iter + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.id, + self._local_variables_parser, + ) + )[0] - value = Subscript( - "-1:-1:-1", - -1, - value=Name("-1:-1:-1", -1, loop_iterator._variable.name), - slice=Index( - "-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var") - ), - ) - loop_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=expr.target, - annotation=loop_var_annotation, - value=value, - ) - - elif isinstance(expr.iter, Call): # range - range_val = expr.iter.args[0] - cond_expr = Compare( + # TODO use expr.src instead of -1:-1:1? + cond_expr = Compare( + "-1:-1:-1", + -1, + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=Call( "-1:-1:-1", -1, - left=Name("-1:-1:-1", -1, "counter_var"), - op="<=", - right=range_val, - ) - node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) - node_condition.add_unparsed_expression(cond_expr) - loop_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=expr.target, - annotation=Name("-1:-1:-1", -1, "uint256"), - value=Name("-1:-1:-1", -1, "counter_var"), - ) + func=Name("-1:-1:-1", -1, "len"), + args=[iter_expr], + keywords=[], + keyword=None, + ), + ) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) + if loop_iterator._elem_to_parse.value.id == "DynArray": + loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[ + 0 + ] else: - raise NotImplementedError - - # link - link_underlying_nodes(counter_node, node_condition) + loop_var_annotation = loop_iterator._elem_to_parse.value - # We update the index variable or range variable in the loop body - expr.body.insert(0, loop_var) - body_node = None - new_node = node_condition - for stmt in expr.body: - body_node = parse_statement(new_node, stmt) - new_node = body_node - - node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + value = Subscript( + "-1:-1:-1", + -1, + value=Name("-1:-1:-1", -1, loop_iterator._variable.name), + slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var")), + ) + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=loop_var_annotation, + value=value, + ) - loop_increment = AugAssign( + elif isinstance(expr.iter, Call): # range + range_val = expr.iter.args[0] + cond_expr = Compare( "-1:-1:-1", -1, - target=Name("-1:-1:-1", -1, "counter_var"), - op="+=", - value=Int("-1:-1:-1", -1, 1), + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=range_val, + ) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Name("-1:-1:-1", -1, "counter_var"), ) - node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) - node_increment.add_unparsed_expression(loop_increment) - link_underlying_nodes(node_increment, node_condition) - if body_node is not None: - link_underlying_nodes(body_node, node_increment) + else: + raise NotImplementedError + + link_underlying_nodes(counter_node, node_condition) + + # We update the index variable or range variable in the loop body + expr.body.insert(0, loop_var) + body_node = None + new_node = node_condition + for stmt in expr.body: + body_node = parse_statement(new_node, stmt) + new_node = body_node + + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + + loop_increment = AugAssign( + "-1:-1:-1", + -1, + target=Name("-1:-1:-1", -1, "counter_var"), + op="+=", + value=Int("-1:-1:-1", -1, 1), + ) + node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) + node_increment.add_unparsed_expression(loop_increment) + link_underlying_nodes(node_increment, node_condition) + + if body_node is not None: + link_underlying_nodes(body_node, node_increment) + + link_underlying_nodes(node_condition, node_endLoop) + + curr_node = node_endLoop + + elif isinstance(expr, Continue): + pass + elif isinstance(expr, Break): + pass + elif isinstance(expr, Return): + new_node = self._new_node(NodeType.RETURN, expr.src, scope) + if expr.value is not None: + new_node.add_unparsed_expression(expr.value) - link_underlying_nodes(node_condition, node_endLoop) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - curr_node = node_endLoop + elif isinstance(expr, Assert): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) - elif isinstance(expr, Continue): - pass - elif isinstance(expr, Break): - pass - elif isinstance(expr, Return): - new_node = self._new_node(NodeType.RETURN, expr.src, scope) - if expr.value is not None: - new_node.add_unparsed_expression(expr.value) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + elif isinstance(expr, Log): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) - elif isinstance(expr, Assert): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + elif isinstance(expr, If): + condition_node = self._new_node(NodeType.IF, expr.test.src, scope) + condition_node.add_unparsed_expression(expr.test) - elif isinstance(expr, Log): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr.value) + endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + true_node = None + new_node = condition_node + for stmt in expr.body: + true_node = parse_statement(new_node, stmt) + new_node = true_node + # link_underlying_nodes(condition_node, true_node) + link_underlying_nodes(true_node, endIf_node) - elif isinstance(expr, If): - condition_node = self._new_node(NodeType.IF, expr.test.src, scope) - condition_node.add_unparsed_expression(expr.test) + false_node = None + new_node = condition_node + for stmt in expr.orelse: + false_node = parse_statement(new_node, stmt) + new_node = false_node - endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) + if false_node is not None: + # link_underlying_nodes(condition_node, false_node) + link_underlying_nodes(false_node, endIf_node) - true_node = None - new_node = condition_node - for stmt in expr.body: - true_node = parse_statement(new_node, stmt) - new_node = true_node - # link_underlying_nodes(condition_node, true_node) - link_underlying_nodes(true_node, endIf_node) + else: + link_underlying_nodes(condition_node, endIf_node) - false_node = None - new_node = condition_node - for stmt in expr.orelse: - false_node = parse_statement(new_node, stmt) - new_node = false_node + link_underlying_nodes(curr_node, condition_node) + curr_node = endIf_node - if false_node is not None: - # link_underlying_nodes(condition_node, false_node) - link_underlying_nodes(false_node, endIf_node) + elif isinstance(expr, Pass): + pass + elif isinstance(expr, Raise): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - else: - link_underlying_nodes(condition_node, endIf_node) - - link_underlying_nodes(curr_node, condition_node) - curr_node = endIf_node - - elif isinstance(expr, Pass): - pass - elif isinstance(expr, Raise): - print(expr) - # TODO - # assert False - pass - else: - print(f"isinstance(expr, {expr.__class__.__name__})") - assert False - return curr_node + else: + raise ParsingError(f"Statement not parsed {expr.__class__.__name__} {expr}") - curr_node = parse_statement(curr_node, expr) - # self._parse_block(cfg, node, self.underlying_function) - else: - self._function.is_empty = True + return curr_node + + curr_node = parse_statement(curr_node, expr) # endregion ################################################################################### diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 3d3d3e4f5..3f76ea281 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -69,6 +69,7 @@ from slither.vyper_parsing.ast.types import ( Assign, AugAssign, VyList, + Raise, ) @@ -192,6 +193,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": else: arguments = [parse_expression(a, caller_context) for a in expression.args] + rets = None if isinstance(called, Identifier): print("called", called) print("called.value", called.value.__class__.__name__) @@ -211,6 +213,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": elif isinstance(called.value, SolidityFunction): rets = called.value.return_type + elif isinstance(called.value, Contract): # Type conversions are not explicitly represented in the AST e.g. converting address to contract/ interface, # so we infer that a type conversion is occurring if `called` is a `Contract` type. @@ -219,14 +222,12 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - else: - rets = ["tuple()"] - elif isinstance(called, MemberAccess) and called.type is not None: # (recover_type_2) Propagate the type collected to the `CallExpression` # see recover_type_1 rets = [called.type] - else: + + if rets is None: rets = ["tuple()"] def get_type_str(x): @@ -235,6 +236,13 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return str(x.type) print(rets) + # def vars_to_typestr(rets: List[Expression]) -> str: + # if len(rets) == 0: + # return "" + # if len(rets) == 1: + # return str(rets[0].type) + # return f"tuple({','.join(str(ret.type) for ret in rets)})" + type_str = ( get_type_str(rets[0]) if len(rets) == 1 @@ -347,30 +355,48 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression, Compare): lhs = parse_expression(expression.left, caller_context) + # We assume left operand in membership comparison cannot be Array type if expression.op in ["In", "NotIn"]: - # If we see a membership operator e.g. x in [foo(), bar()] we rewrite it as if-else: - # if (x == foo()) { - # return true - # } else { - # if (x == bar()) { - # return true - # } else { - # return false - # } - # } - # We assume left operand in membership comparison cannot be Array type + # If we see a membership operator e.g. x in [foo(), bar()], we convert it to logical operations + # like (x == foo() || x == bar()) or (x != foo() && x != bar()) for "not in" + # TODO consider rewriting as if-else to accurately represent the precedence of potential side-effects + conditions = deque() - if isinstance(expression.right, VyList): + rhs = parse_expression(expression.right, caller_context) + is_tuple = isinstance(rhs, TupleExpression) + is_array = isinstance(rhs, Identifier) and isinstance(rhs.value.type, ArrayType) + if is_array: + assert rhs.value.type.is_fixed_array + if is_tuple or is_array: + length = len(rhs.expressions) if is_tuple else rhs.value.type.length_value.value inner_op = ( BinaryOperationType.get_type("!=") if expression.op == "NotIn" else BinaryOperationType.get_type("==") ) + for i in range(length): + elem_expr = ( + rhs.expressions[i] + if is_tuple + else IndexAccess(rhs, Literal(str(i), ElementaryType("uint256"))) + ) + elem_expr.set_offset(rhs.source_mapping, caller_context.compilation_unit) + parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) + parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) + conditions.append(parsed_expr) + outer_op = ( BinaryOperationType.get_type("&&") if expression.op == "NotIn" else BinaryOperationType.get_type("||") ) + while len(conditions) > 1: + lhs = conditions.pop() + rhs = conditions.pop() + + conditions.appendleft(BinaryOperation(lhs, rhs, outer_op)) + + return conditions.pop() for elem in expression.right.elements: elem_expr = parse_expression(elem, caller_context) @@ -378,79 +404,31 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) conditions.append(parsed_expr) - else: - rhs = parse_expression(expression.right, caller_context) - print(rhs) - print(rhs.__class__.__name__) - if isinstance(rhs, Identifier): - if isinstance(rhs.value.type, ArrayType): - inner_op = ( - BinaryOperationType.get_type("!=") - if expression.op == "NotIn" - else BinaryOperationType.get_type("==") - ) - outer_op = ( - BinaryOperationType.get_type("&&") - if expression.op == "NotIn" - else BinaryOperationType.get_type("||") - ) - - enum_members = rhs.value.type.length_value.value - for i in range(enum_members): - elem_expr = IndexAccess(rhs, Literal(str(i), ElementaryType("uint256"))) - elem_expr.set_offset( - rhs.source_mapping, caller_context.compilation_unit - ) - parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) - parsed_expr.set_offset( - lhs.source_mapping, caller_context.compilation_unit - ) - conditions.append(parsed_expr) - # elif isinstance(rhs.value.type, UserDefinedType): - - else: - assert False - else: - # This is an indexaccess like hashmap[address, Roles] - inner_op = BinaryOperationType.get_type( - "|" - ) # if expression.op == "NotIn" else BinaryOperationType.get_type("==") - outer_op = BinaryOperationType.get_type( - "&" - ) # if expression.op == "NotIn" else BinaryOperationType.get_type("||") - - # x, _ = find_variable(expression.right.value.attr, caller_context) - # print(x) - # print(x.type.type_to) - # print(x.type.type_to.__class__) - print(repr(rhs)) - print(rhs) - - enum_members = rhs.expression_left.value.type.type_to.type.values - # for each value, create a literal with value = 2 ^ n (0 indexed) - # and then translate to bitmasking - enum_values = [ - Literal(str(2**n), ElementaryType("uint256")) - for n in range(len(enum_members)) - ] - inner_lhs = enum_values[0] - for expr in enum_values[1:]: - inner_lhs = BinaryOperation(inner_lhs, expr, inner_op) - conditions.append(inner_lhs) - - parsed_expr = BinaryOperation(lhs, conditions[0], outer_op) - parsed_expr.set_offset(lhs.source_mapping, caller_context.compilation_unit) - return parsed_expr - - while len(conditions) > 1: - lhs = conditions.pop() - rhs = conditions.pop() - - conditions.appendleft(BinaryOperation(lhs, rhs, outer_op)) - - return conditions.pop() + else: # enum type membership check https://docs.vyperlang.org/en/stable/types.html?h#id18 + is_member_op = ( + BinaryOperationType.get_type("==") + if expression.op == "NotIn" + else BinaryOperationType.get_type("!=") + ) + # If all bits are cleared, then the lhs is not a member of the enum + # This allows representing membership in multiple enum members + # For example, if enum Foo has members A (1), B (2), and C (4), then + # (x in [Foo.A, Foo.B]) is equivalent to (x & (Foo.A | Foo.B) != 0), + # where (Foo.A | Foo.B) evaluates to 3. + # Thus, when x is 3, (x & (Foo.A | Foo.B) != 0) is true. + + enum_bit_mask = BinaryOperation( + TypeConversion(lhs, ElementaryType("uint256")), + TypeConversion(rhs, ElementaryType("uint256")), + BinaryOperationType.get_type("&"), + ) + membership_check = BinaryOperation( + enum_bit_mask, Literal("0", ElementaryType("uint256")), is_member_op + ) + membership_check.set_offset(lhs.source_mapping, caller_context.compilation_unit) + return membership_check - else: + else: # a regular logical operator rhs = parse_expression(expression.right, caller_context) op = BinaryOperationType.get_type(expression.op) @@ -501,4 +479,17 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr + if isinstance(expression, Raise): + type_str = "tuple()" + func = ( + SolidityFunction("revert()") + if expression.exc is None + else SolidityFunction("revert(string)") + ) + args = [] if expression.exc is None else [parse_expression(expression.exc, caller_context)] + + parsed_expr = CallExpression(Identifier(func), args, type_str) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr + raise ParsingError(f"Expression not parsed {expression}") diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt index 7bf9052b8..49552d27f 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_bar__0.txt @@ -2,45 +2,57 @@ digraph{ 0[label="Node Type: ENTRY_POINT 0 "]; 0->1; -1[label="Node Type: NEW VARIABLE 1 +1[label="Node Type: IF 1 EXPRESSION: -a = 0 +uint256(x) & uint256(self.roles[self]) != 0 IRs: -a(int128) := 0(uint256)"]; -1->2; -2[label="Node Type: NEW VARIABLE 2 +TMP_10 = CONVERT x to uint256 +REF_4(in.Roles) -> roles[self] +TMP_11 = CONVERT REF_4 to uint256 +TMP_12(uint256) = TMP_10 & TMP_11 +TMP_13(bool) = TMP_12 != 0 +CONDITION TMP_13"]; +1->3[label="True"]; +1->2[label="False"]; +2[label="Node Type: END_IF 2 +"]; +2->4; +3[label="Node Type: RETURN 3 EXPRESSION: -b = 0 +True IRs: -b(int128) := 0(uint256)"]; -2->3; -3[label="Node Type: IF 3 +RETURN True"]; +3->2; +4[label="Node Type: IF 4 EXPRESSION: -x & 1 | 2 +uint256(x) & uint256(self.roles[self]) == 0 IRs: -TMP_0(uint256) = 1 | 2 -TMP_1(in.Roles) = x & TMP_0 -CONDITION TMP_1"]; -3->5[label="True"]; -3->4[label="False"]; -4[label="Node Type: END_IF 4 +TMP_14 = CONVERT x to uint256 +REF_5(in.Roles) -> roles[self] +TMP_15 = CONVERT REF_5 to uint256 +TMP_16(uint256) = TMP_14 & TMP_15 +TMP_17(bool) = TMP_16 == 0 +CONDITION TMP_17"]; +4->6[label="True"]; +4->5[label="False"]; +5[label="Node Type: END_IF 5 "]; -4->6; -5[label="Node Type: RETURN 5 +5->7; +6[label="Node Type: RETURN 6 EXPRESSION: -True +False IRs: -RETURN True"]; -5->4; -6[label="Node Type: RETURN 6 +RETURN False"]; +6->5; +7[label="Node Type: RETURN 7 EXPRESSION: False diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_baz__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_baz__0.txt new file mode 100644 index 000000000..95328dad9 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_baz__0.txt @@ -0,0 +1,66 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: IF 1 + +EXPRESSION: +uint256(x) & uint256(Roles.A | Roles.B) != 0 + +IRs: +TMP_0 = CONVERT x to uint256 +REF_0(in.Roles) -> Roles.A +REF_1(in.Roles) -> Roles.B +TMP_1(in.Roles) = REF_0 | REF_1 +TMP_2 = CONVERT TMP_1 to uint256 +TMP_3(uint256) = TMP_0 & TMP_2 +TMP_4(bool) = TMP_3 != 0 +CONDITION TMP_4"]; +1->3[label="True"]; +1->2[label="False"]; +2[label="Node Type: END_IF 2 +"]; +2->4; +3[label="Node Type: RETURN 3 + +EXPRESSION: +True + +IRs: +RETURN True"]; +3->2; +4[label="Node Type: IF 4 + +EXPRESSION: +uint256(x) & uint256(Roles.A | Roles.B) == 0 + +IRs: +TMP_5 = CONVERT x to uint256 +REF_2(in.Roles) -> Roles.A +REF_3(in.Roles) -> Roles.B +TMP_6(in.Roles) = REF_2 | REF_3 +TMP_7 = CONVERT TMP_6 to uint256 +TMP_8(uint256) = TMP_5 & TMP_7 +TMP_9(bool) = TMP_8 == 0 +CONDITION TMP_9"]; +4->6[label="True"]; +4->5[label="False"]; +5[label="Node Type: END_IF 5 +"]; +5->7; +6[label="Node Type: RETURN 6 + +EXPRESSION: +False + +IRs: +RETURN False"]; +6->5; +7[label="Node Type: RETURN 7 + +EXPRESSION: +False + +IRs: +RETURN False"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt index b9d3da07e..cd1e34bf1 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_in_foo__0.txt @@ -24,10 +24,10 @@ EXPRESSION: x == b || x == a IRs: -TMP_2(bool) = x == b -TMP_3(bool) = x == a -TMP_4(bool) = TMP_2 || TMP_3 -CONDITION TMP_4"]; +TMP_18(bool) = x == b +TMP_19(bool) = x == a +TMP_20(bool) = TMP_18 || TMP_19 +CONDITION TMP_20"]; 3->5[label="True"]; 3->4[label="False"]; 4[label="Node Type: END_IF 4 @@ -41,7 +41,30 @@ True IRs: RETURN True"]; 5->4; -6[label="Node Type: RETURN 6 +6[label="Node Type: IF 6 + +EXPRESSION: +x != b && x != a + +IRs: +TMP_21(bool) = x != b +TMP_22(bool) = x != a +TMP_23(bool) = TMP_21 && TMP_22 +CONDITION TMP_23"]; +6->8[label="True"]; +6->7[label="False"]; +7[label="Node Type: END_IF 7 +"]; +7->9; +8[label="Node Type: EXPRESSION 8 + +EXPRESSION: +revert(string)(nope) + +IRs: +TMP_24(None) = SOLIDITY_CALL revert(string)(nope)"]; +8->7; +9[label="Node Type: RETURN 9 EXPRESSION: False diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt index b799f07d4..0c204c9fa 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_fb__0.txt @@ -1,4 +1,12 @@ digraph{ 0[label="Node Type: ENTRY_POINT 0 "]; +0->1; +1[label="Node Type: EXPRESSION 1 + +EXPRESSION: +revert()() + +IRs: +TMP_0(None) = SOLIDITY_CALL revert()()"]; } diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt index 2355fd513..2180c6eb1 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_precedence_foo__0.txt @@ -8,10 +8,10 @@ EXPRESSION: x != self.fb() && x != self.fa() IRs: -TMP_0(uint256) = INTERNAL_CALL, precedence.fb()() -TMP_1(bool) = x != TMP_0 -TMP_2(uint256) = INTERNAL_CALL, precedence.fa()() -TMP_3(bool) = x != TMP_2 -TMP_4(bool) = TMP_1 && TMP_3 -RETURN TMP_4"]; +TMP_1(uint256) = INTERNAL_CALL, precedence.fb()() +TMP_2(bool) = x != TMP_1 +TMP_3(uint256) = INTERNAL_CALL, precedence.fa()() +TMP_4(bool) = x != TMP_3 +TMP_5(bool) = TMP_2 && TMP_4 +RETURN TMP_5"]; } diff --git a/tests/e2e/vyper_parsing/test_data/in.vy b/tests/e2e/vyper_parsing/test_data/in.vy index e08f71a74..5d4827ca1 100644 --- a/tests/e2e/vyper_parsing/test_data/in.vy +++ b/tests/e2e/vyper_parsing/test_data/in.vy @@ -4,13 +4,23 @@ enum Roles: roles: public(HashMap[address, Roles]) +@external +def baz(x: Roles) -> bool: + if x in (Roles.A | Roles.B): + return True + if x not in (Roles.A | Roles.B): + return False + + return False + @external def bar(x: Roles) -> bool: - a: int128 = 0 - b: int128 = 0 if x in self.roles[self]: return True + if x not in self.roles[self]: + return False + return False @external @@ -20,4 +30,7 @@ def foo(x: int128) -> bool: if x in [a, b]: return True + if x not in [a, b]: + raise "nope" + return False \ No newline at end of file From 9fdc7dc22878a1acda4c16f25fe59d80e414d2ce Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 4 Sep 2023 13:54:52 -0500 Subject: [PATCH 216/338] conditionally apply refinements to Solidity --- slither/slithir/convert.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 8bb20412b..91fe30da7 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -114,8 +114,8 @@ def convert_expression(expression: Expression, node: "Node") -> List[Operation]: visitor = ExpressionToSlithIR(expression, node) result = visitor.result() - - result = apply_ir_heuristics(result, node) + is_solidity = node.compilation_unit.is_solidity + result = apply_ir_heuristics(result, node, is_solidity) if result: if node.type in [NodeType.IF, NodeType.IFLOOP]: @@ -1910,7 +1910,7 @@ def _find_source_mapping_references(irs: List[Operation]) -> None: ################################################################################### -def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Operation]: +def apply_ir_heuristics(irs: List[Operation], node: "Node", is_solidity: bool) -> List[Operation]: """ Apply a set of heuristic to improve slithIR """ @@ -1920,9 +1920,11 @@ def apply_ir_heuristics(irs: List[Operation], node: "Node") -> List[Operation]: irs = propagate_type_and_convert_call(irs, node) irs = remove_unused(irs) find_references_origin(irs) - # TODO refine only for Solidity - # convert_constant_types(irs) - convert_delete(irs) + + # These are heuristics that are only applied to Solidity + if is_solidity: + convert_constant_types(irs) + convert_delete(irs) _find_source_mapping_references(irs) From 16140f29c854e6db7ba43f94a3c0c9cd640944e1 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 4 Sep 2023 13:55:28 -0500 Subject: [PATCH 217/338] cleanup and formatting --- .../core/declarations/solidity_variables.py | 45 +++++++++---------- slither/vyper_parsing/ast/types.py | 3 -- slither/vyper_parsing/declarations/struct.py | 6 +-- .../vyper_parsing/variables/event_variable.py | 7 ++- .../vyper_parsing/vyper_compilation_unit.py | 4 +- tests/unit/core/test_source_mapping.py | 3 +- 6 files changed, 33 insertions(+), 35 deletions(-) diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index 03fd81f04..d5aec009f 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -40,7 +40,6 @@ SOLIDITY_VARIABLES_COMPOSED = { "chain.id": "uint256", "block.prevhash": "bytes32", "self.balance": "uint256", - } SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { @@ -89,30 +88,30 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "code(address)": ["bytes"], "codehash(address)": ["bytes32"], # Vyper - "create_from_blueprint()":[], - "empty()":[], - "convert()":[], # TODO make type conversion - "len()":["uint256"], - "method_id()":[], + "create_from_blueprint()": [], + "empty()": [], + "convert()": [], # TODO make type conversion + "len()": ["uint256"], + "method_id()": [], "unsafe_sub()": [], "unsafe_add()": [], - "unsafe_div()":[], - "unsafe_mul()":[], - "pow_mod256()":[], - "max_value()":[], - "min_value()":[], - "concat()":[], - "ecrecover()":[], - "isqrt()":[], - "range()":[], - "min()":[], - "max()":[], - "shift()":[], - "abs()":[], - "raw_call()":["bool", "bytes32"], - "_abi_encode()":[], - "slice()":[], - "uint2str()":["string"], + "unsafe_div()": [], + "unsafe_mul()": [], + "pow_mod256()": [], + "max_value()": [], + "min_value()": [], + "concat()": [], + "ecrecover()": [], + "isqrt()": [], + "range()": [], + "min()": [], + "max()": [], + "shift()": [], + "abs()": [], + "raw_call()": ["bool", "bytes32"], + "_abi_encode()": [], + "slice()": [], + "uint2str()": ["string"], } diff --git a/slither/vyper_parsing/ast/types.py b/slither/vyper_parsing/ast/types.py index e07e6d213..6eff6d252 100644 --- a/slither/vyper_parsing/ast/types.py +++ b/slither/vyper_parsing/ast/types.py @@ -85,9 +85,6 @@ class Index(ASTNode): value: ASTNode -# TODO CONSTANT? - - @dataclass class Bytes(ASTNode): value: bytes diff --git a/slither/vyper_parsing/declarations/struct.py b/slither/vyper_parsing/declarations/struct.py index 0da2c7fed..70a6bd7b7 100644 --- a/slither/vyper_parsing/declarations/struct.py +++ b/slither/vyper_parsing/declarations/struct.py @@ -7,17 +7,15 @@ from slither.vyper_parsing.ast.types import StructDef, AnnAssign class StructVyper: - def __init__( # pylint: disable=too-many-arguments + def __init__( self, st: Structure, struct: StructDef, ) -> None: - print(struct) - self._structure = st st.name = struct.name - # st.canonical_name = canonicalName + st.canonical_name = struct.name + self._structure.contract.name self._elemsNotParsed: List[AnnAssign] = struct.body diff --git a/slither/vyper_parsing/variables/event_variable.py b/slither/vyper_parsing/variables/event_variable.py index 2dc5db544..5167610a8 100644 --- a/slither/vyper_parsing/variables/event_variable.py +++ b/slither/vyper_parsing/variables/event_variable.py @@ -10,8 +10,11 @@ class EventVariableVyper: print(variable_data) self._variable = variable self._variable.name = variable_data.target.id - if isinstance(variable_data.annotation, Call) and variable_data.annotation.func.id == "indexed": - self._variable.indexed = True + if ( + isinstance(variable_data.annotation, Call) + and variable_data.annotation.func.id == "indexed" + ): + self._variable.indexed = True else: self._variable.indexed = False self._elem_to_parse = variable_data.annotation diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index 2650ffe8e..d4ebf8415 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -52,12 +52,12 @@ class VyperCompilationUnit: if not self._parsed: raise SlitherException("Parse the contract before running analyses") - for contract, contract_parser in self._underlying_contract_to_parser.items(): + for contract_parser in self._underlying_contract_to_parser.values(): # State variables are analyzed for all contracts because interfaces may # reference them, specifically, constants. contract_parser.analyze_state_variables() - for contract, contract_parser in self._underlying_contract_to_parser.items(): + for contract_parser in self._underlying_contract_to_parser.values(): contract_parser.analyze() self._convert_to_slithir() diff --git a/tests/unit/core/test_source_mapping.py b/tests/unit/core/test_source_mapping.py index 16a26215b..552c08dc9 100644 --- a/tests/unit/core/test_source_mapping.py +++ b/tests/unit/core/test_source_mapping.py @@ -114,6 +114,7 @@ def test_references_user_defined_types_when_casting(solc_binary_path): lines = _sort_references_lines(a.references) assert lines == [12, 18] + def test_references_self_identifier(): """ Tests that shadowing state variables with local variables does not affect references. @@ -125,4 +126,4 @@ def test_references_self_identifier(): a = contracts[0].state_variables[0] assert len(a.references) == 1 lines = _sort_references_lines(a.references) - assert lines == [4] \ No newline at end of file + assert lines == [4] From 9c4bc505d39be9d4d7083caf7eda26ab2ffe3c2c Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 07:44:03 -0500 Subject: [PATCH 218/338] handle break/continue --- .../vyper_parsing/declarations/function.py | 65 ++++--- ..._parsing__vyper_cfgir_for2_for_loop__0.txt | 40 ++--- ...ast_parsing__vyper_cfgir_for3_get_D__0.txt | 40 ++--- ...g__vyper_cfgir_for_break_continue_f__0.txt | 164 ++++++++++++++++++ ...t_parsing__vyper_cfgir_for_for_loop__0.txt | 40 ++--- 5 files changed, 268 insertions(+), 81 deletions(-) create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_break_continue_f__0.txt diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index f023953fa..9932a7c22 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -229,7 +229,12 @@ class FunctionVyper: curr_node = entry_node for expr in cfg: - def parse_statement(curr_node, expr): + def parse_statement( + curr_node: NodeVyper, + expr: ASTNode, + continue_destination=None, + break_destination=None, + ) -> NodeVyper: if isinstance(expr, AnnAssign): local_var = LocalVariable() local_var.set_function(self._function) @@ -266,6 +271,8 @@ class FunctionVyper: elif isinstance(expr, For): node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + link_underlying_nodes(curr_node, node_startLoop) local_var = LocalVariable() @@ -371,18 +378,10 @@ class FunctionVyper: else: raise NotImplementedError + # After creating condition node, we link it declaration of the loop variable link_underlying_nodes(counter_node, node_condition) - # We update the index variable or range variable in the loop body - expr.body.insert(0, loop_var) - body_node = None - new_node = node_condition - for stmt in expr.body: - body_node = parse_statement(new_node, stmt) - new_node = body_node - - node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) - + # Create an expression for the loop increment (counter_var += 1) loop_increment = AugAssign( "-1:-1:-1", -1, @@ -394,6 +393,25 @@ class FunctionVyper: node_increment.add_unparsed_expression(loop_increment) link_underlying_nodes(node_increment, node_condition) + prev_continue_destination = continue_destination + prev_break_destination = break_destination + continue_destination = node_increment + break_destination = node_endLoop + + # We assign the index variable or range variable in the loop body on each iteration + expr.body.insert(0, loop_var) + body_node = None + new_node = node_condition + for stmt in expr.body: + body_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) + new_node = body_node + + # Reset to previous jump destinations for nested loops + continue_destination = prev_continue_destination + break_destination = prev_break_destination + if body_node is not None: link_underlying_nodes(body_node, node_increment) @@ -402,9 +420,15 @@ class FunctionVyper: curr_node = node_endLoop elif isinstance(expr, Continue): - pass + new_node = self._new_node(NodeType.CONTINUE, expr.src, scope) + link_underlying_nodes(curr_node, new_node) + link_underlying_nodes(new_node, continue_destination) + elif isinstance(expr, Break): - pass + new_node = self._new_node(NodeType.BREAK, expr.src, scope) + link_underlying_nodes(curr_node, new_node) + link_underlying_nodes(new_node, break_destination) + elif isinstance(expr, Return): new_node = self._new_node(NodeType.RETURN, expr.src, scope) if expr.value is not None: @@ -436,19 +460,22 @@ class FunctionVyper: true_node = None new_node = condition_node for stmt in expr.body: - true_node = parse_statement(new_node, stmt) + true_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) new_node = true_node - # link_underlying_nodes(condition_node, true_node) + link_underlying_nodes(true_node, endIf_node) false_node = None new_node = condition_node for stmt in expr.orelse: - false_node = parse_statement(new_node, stmt) + false_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) new_node = false_node if false_node is not None: - # link_underlying_nodes(condition_node, false_node) link_underlying_nodes(false_node, endIf_node) else: @@ -481,13 +508,11 @@ class FunctionVyper: local_var = LocalVariable() local_var.set_function(self._function) local_var.set_offset(param.src, self._function.compilation_unit) - print("add_param", param) local_var_parser = LocalVariableVyper(local_var, param) if initialized: local_var.initialized = True - # see https://solidity.readthedocs.io/en/v0.4.24/types.html?highlight=storage%20location#data-location if local_var.location == "default": local_var.set_location("memory") @@ -496,7 +521,6 @@ class FunctionVyper: def _parse_params(self, params: Arguments): - print(params) self._function.parameters_src().set_offset(params.src, self._function.compilation_unit) if params.defaults: self._function._default_args_as_expressions = params.defaults @@ -506,7 +530,6 @@ class FunctionVyper: def _parse_returns(self, returns: Union[Name, Tuple, Subscript]): - print(returns) self._function.returns_src().set_offset(returns.src, self._function.compilation_unit) # Only the type of the arg is given, not a name. We create an an `Arg` with an empty name # so that the function has the correct return type in its signature but doesn't clash with diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt index 949e814ff..c1f5f2f13 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt @@ -12,16 +12,18 @@ _strategies(address[3]) = ['strategies(address[3])']"]; 1->2; 2[label="Node Type: BEGIN_LOOP 2 "]; -2->3; -3[label="Node Type: NEW VARIABLE 3 +2->4; +3[label="Node Type: END_LOOP 3 +"]; +4[label="Node Type: NEW VARIABLE 4 EXPRESSION: counter_var = 0 IRs: counter_var(uint256) := 0(uint256)"]; -3->4; -4[label="Node Type: IF_LOOP 4 +4->5; +5[label="Node Type: IF_LOOP 5 EXPRESSION: counter_var <= 10 @@ -29,17 +31,25 @@ counter_var <= 10 IRs: TMP_0(bool) = counter_var <= 10 CONDITION TMP_0"]; -4->5[label="True"]; -4->7[label="False"]; -5[label="Node Type: NEW VARIABLE 5 +5->7[label="True"]; +5->3[label="False"]; +6[label="Node Type: EXPRESSION 6 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +6->5; +7[label="Node Type: NEW VARIABLE 7 EXPRESSION: i = counter_var IRs: i(uint256) := counter_var(uint256)"]; -5->6; -6[label="Node Type: NEW VARIABLE 6 +7->8; +8[label="Node Type: NEW VARIABLE 8 EXPRESSION: max_withdraw = IStrategy(_strategies[i]).maxWithdraw(self) @@ -49,15 +59,5 @@ REF_0(address) -> _strategies[i] TMP_1 = CONVERT REF_0 to IStrategy TMP_2(uint256) = HIGH_LEVEL_CALL, dest:TMP_1(IStrategy), function:maxWithdraw, arguments:['self'] max_withdraw(uint256) := TMP_2(uint256)"]; -6->8; -7[label="Node Type: END_LOOP 7 -"]; -8[label="Node Type: EXPRESSION 8 - -EXPRESSION: -counter_var += 1 - -IRs: -counter_var(uint256) = counter_var (c)+ 1"]; -8->4; +8->6; } diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt index ae6d397b0..f8ab6cef9 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for3_get_D__0.txt @@ -12,16 +12,18 @@ S(uint256) := 0(uint256)"]; 1->2; 2[label="Node Type: BEGIN_LOOP 2 "]; -2->3; -3[label="Node Type: NEW VARIABLE 3 +2->4; +3[label="Node Type: END_LOOP 3 +"]; +4[label="Node Type: NEW VARIABLE 4 EXPRESSION: counter_var = 0 IRs: counter_var(uint256) := 0(uint256)"]; -3->4; -4[label="Node Type: IF_LOOP 4 +4->5; +5[label="Node Type: IF_LOOP 5 EXPRESSION: counter_var <= len()(_xp) @@ -30,33 +32,31 @@ IRs: TMP_0(uint256) = SOLIDITY_CALL len()(_xp) TMP_1(bool) = counter_var <= TMP_0 CONDITION TMP_1"]; -4->5[label="True"]; -4->7[label="False"]; -5[label="Node Type: NEW VARIABLE 5 +5->7[label="True"]; +5->3[label="False"]; +6[label="Node Type: EXPRESSION 6 EXPRESSION: -x = _xp[counter_var] +counter_var += 1 IRs: -REF_0(uint256) -> _xp[counter_var] -x(uint256) := REF_0(uint256)"]; -5->6; -6[label="Node Type: EXPRESSION 6 +counter_var(uint256) = counter_var (c)+ 1"]; +6->5; +7[label="Node Type: NEW VARIABLE 7 EXPRESSION: -S += x +x = _xp[counter_var] IRs: -S(uint256) = S (c)+ x"]; -6->8; -7[label="Node Type: END_LOOP 7 -"]; +REF_0(uint256) -> _xp[counter_var] +x(uint256) := REF_0(uint256)"]; +7->8; 8[label="Node Type: EXPRESSION 8 EXPRESSION: -counter_var += 1 +S += x IRs: -counter_var(uint256) = counter_var (c)+ 1"]; -8->4; +S(uint256) = S (c)+ x"]; +8->6; } diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_break_continue_f__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_break_continue_f__0.txt new file mode 100644 index 000000000..b35bdaa94 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_break_continue_f__0.txt @@ -0,0 +1,164 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: BEGIN_LOOP 1 +"]; +1->3; +2[label="Node Type: END_LOOP 2 +"]; +3[label="Node Type: NEW VARIABLE 3 + +EXPRESSION: +counter_var = 0 + +IRs: +counter_var(uint256) := 0(uint256)"]; +3->4; +4[label="Node Type: IF_LOOP 4 + +EXPRESSION: +counter_var <= 100 + +IRs: +TMP_0(bool) = counter_var <= 100 +CONDITION TMP_0"]; +4->6[label="True"]; +4->2[label="False"]; +5[label="Node Type: EXPRESSION 5 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +5->4; +6[label="Node Type: NEW VARIABLE 6 + +EXPRESSION: +i = counter_var + +IRs: +i(uint256) := counter_var(uint256)"]; +6->7; +7[label="Node Type: IF 7 + +EXPRESSION: +i > 100 + +IRs: +TMP_1(bool) = i > 100 +CONDITION TMP_1"]; +7->9[label="True"]; +7->8[label="False"]; +8[label="Node Type: END_IF 8 +"]; +8->10; +9[label="Node Type: BREAK 9 +"]; +9->2; +10[label="Node Type: IF 10 + +EXPRESSION: +i < 3 + +IRs: +TMP_2(bool) = i < 3 +CONDITION TMP_2"]; +10->12[label="True"]; +10->11[label="False"]; +11[label="Node Type: END_IF 11 +"]; +11->13; +12[label="Node Type: CONTINUE 12 +"]; +12->5; +13[label="Node Type: NEW VARIABLE 13 + +EXPRESSION: +x = 10 + +IRs: +x(uint256) := 10(uint256)"]; +13->14; +14[label="Node Type: BEGIN_LOOP 14 +"]; +14->16; +15[label="Node Type: END_LOOP 15 +"]; +15->5; +16[label="Node Type: NEW VARIABLE 16 + +EXPRESSION: +counter_var_scope_0 = 0 + +IRs: +counter_var_scope_0(uint256) := 0(uint256)"]; +16->17; +17[label="Node Type: IF_LOOP 17 + +EXPRESSION: +counter_var <= 10 + +IRs: +TMP_3(bool) = counter_var <= 10 +CONDITION TMP_3"]; +17->19[label="True"]; +17->15[label="False"]; +18[label="Node Type: EXPRESSION 18 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +18->17; +19[label="Node Type: NEW VARIABLE 19 + +EXPRESSION: +j = counter_var + +IRs: +j(uint256) := counter_var(uint256)"]; +19->20; +20[label="Node Type: IF 20 + +EXPRESSION: +j > 10 + +IRs: +TMP_4(bool) = j > 10 +CONDITION TMP_4"]; +20->22[label="True"]; +20->21[label="False"]; +21[label="Node Type: END_IF 21 +"]; +21->23; +22[label="Node Type: CONTINUE 22 +"]; +22->18; +23[label="Node Type: IF 23 + +EXPRESSION: +j < 3 + +IRs: +TMP_5(bool) = j < 3 +CONDITION TMP_5"]; +23->25[label="True"]; +23->24[label="False"]; +24[label="Node Type: END_IF 24 +"]; +24->26; +25[label="Node Type: BREAK 25 +"]; +25->15; +26[label="Node Type: EXPRESSION 26 + +EXPRESSION: +x -= 1 + +IRs: +x(uint256) = x (c)- 1"]; +26->18; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt index 5c4123662..575f0d55f 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for_for_loop__0.txt @@ -4,16 +4,18 @@ digraph{ 0->1; 1[label="Node Type: BEGIN_LOOP 1 "]; -1->2; -2[label="Node Type: NEW VARIABLE 2 +1->3; +2[label="Node Type: END_LOOP 2 +"]; +3[label="Node Type: NEW VARIABLE 3 EXPRESSION: counter_var = 0 IRs: counter_var(uint256) := 0(uint256)"]; -2->3; -3[label="Node Type: IF_LOOP 3 +3->4; +4[label="Node Type: IF_LOOP 4 EXPRESSION: counter_var <= len()(self.strategies) @@ -22,9 +24,17 @@ IRs: TMP_0(uint256) = SOLIDITY_CALL len()(strategies) TMP_1(bool) = counter_var <= TMP_0 CONDITION TMP_1"]; -3->4[label="True"]; -3->6[label="False"]; -4[label="Node Type: NEW VARIABLE 4 +4->6[label="True"]; +4->2[label="False"]; +5[label="Node Type: EXPRESSION 5 + +EXPRESSION: +counter_var += 1 + +IRs: +counter_var(uint256) = counter_var (c)+ 1"]; +5->4; +6[label="Node Type: NEW VARIABLE 6 EXPRESSION: strategy = strategies[counter_var] @@ -32,8 +42,8 @@ strategy = strategies[counter_var] IRs: REF_0(address) -> strategies[counter_var] strategy(address) := REF_0(address)"]; -4->5; -5[label="Node Type: NEW VARIABLE 5 +6->7; +7[label="Node Type: NEW VARIABLE 7 EXPRESSION: z = IStrategy(strategy).asset() @@ -42,15 +52,5 @@ IRs: TMP_2 = CONVERT strategy to IStrategy TMP_3(address) = HIGH_LEVEL_CALL, dest:TMP_2(IStrategy), function:asset, arguments:[] z(address) := TMP_3(address)"]; -5->7; -6[label="Node Type: END_LOOP 6 -"]; -7[label="Node Type: EXPRESSION 7 - -EXPRESSION: -counter_var += 1 - -IRs: -counter_var(uint256) = counter_var (c)+ 1"]; -7->3; +7->5; } From 9df54e9c3a52859c42195ae24890e52f42079f3f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 07:44:39 -0500 Subject: [PATCH 219/338] update tests --- ...ast_parsing__vyper_cfgir_builtins_c__0.txt | 38 +++++++++++++ ..._vyper_cfgir_builtins_test_builtins__0.txt | 9 +-- ...parsing__vyper_cfgir_default_args_a__0.txt | 28 +++++++++ ...parsing__vyper_cfgir_default_args_b__0.txt | 24 ++++++++ ...slitherConstructorConstantVariables__0.txt | 9 +++ ...yper_cfgir_interface_conversion_bar__0.txt | 57 +++++++++++++++++++ ...yper_cfgir_interface_conversion_foo__0.txt | 12 ++++ ..._vyper_cfgir_tuple_struct___default__0.txt | 28 +++++++++ ...slitherConstructorConstantVariables__0.txt | 9 +++ tests/e2e/vyper_parsing/test_data/ERC20.vy | 13 ----- tests/e2e/vyper_parsing/test_data/builtins.vy | 21 +++---- tests/e2e/vyper_parsing/test_data/chain.vy | 4 -- .../vyper_parsing/test_data/default_args.vy | 12 ++++ tests/e2e/vyper_parsing/test_data/for.vy | 3 - .../test_data/for_break_continue.vy | 17 ++++++ tests/e2e/vyper_parsing/test_data/initarry.vy | 4 +- .../{tricky.vy => interface_constant.vy} | 0 .../{tuple.vy => interface_conversion.vy} | 2 - .../vyper_parsing/test_data/tuple_struct.vy | 10 ++++ .../test_data/{literal.vy => types.vy} | 4 -- 20 files changed, 258 insertions(+), 46 deletions(-) create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_a__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_b__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_bar__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_foo__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_struct___default__0.txt create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_types_slitherConstructorConstantVariables__0.txt delete mode 100644 tests/e2e/vyper_parsing/test_data/chain.vy create mode 100644 tests/e2e/vyper_parsing/test_data/default_args.vy create mode 100644 tests/e2e/vyper_parsing/test_data/for_break_continue.vy rename tests/e2e/vyper_parsing/test_data/{tricky.vy => interface_constant.vy} (100%) rename tests/e2e/vyper_parsing/test_data/{tuple.vy => interface_conversion.vy} (99%) create mode 100644 tests/e2e/vyper_parsing/test_data/tuple_struct.vy rename tests/e2e/vyper_parsing/test_data/{literal.vy => types.vy} (86%) diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt new file mode 100644 index 000000000..3c6eaec3e --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt @@ -0,0 +1,38 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +user_shares = () + +IRs: +user_shares(uint256[10]) = []"]; +1->2; +2[label="Node Type: EXPRESSION 2 + +EXPRESSION: +user_shares.append(1) + +IRs: +REF_1 -> LENGTH user_shares +TMP_3(uint256) := REF_1(uint256) +TMP_4(uint256) = TMP_3 (c)+ 1 +REF_1(uint256) (->user_shares) := TMP_4(uint256) +REF_2(uint256) -> user_shares[TMP_3] +REF_2(uint256) (->user_shares) := 1(uint256)"]; +2->3; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +user_shares.pop() + +IRs: +REF_4 -> LENGTH user_shares +TMP_6(uint256) = REF_4 (c)- 1 +REF_5(uint256) -> user_shares[TMP_6] +REF_5 = delete REF_5 +REF_6 -> LENGTH user_shares +REF_6(uint256) (->user_shares) := TMP_6(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt index 07141a2b1..9b7768a6b 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt @@ -53,10 +53,11 @@ f(uint256) := block.timestamp(uint256)"]; 7[label="Node Type: NEW VARIABLE 7 EXPRESSION: -h = chain.id +h = bytes32(chain.id) IRs: -h(uint256) := chain.id(uint256)"]; +TMP_0 = CONVERT chain.id to bytes32 +h(bytes32) := TMP_0(bytes32)"]; 7->8; 8[label="Node Type: NEW VARIABLE 8 @@ -64,8 +65,8 @@ EXPRESSION: i = slice()(msg.data,0,32) IRs: -TMP_0(None) = SOLIDITY_CALL slice()(msg.data,0,32) -i(bytes[32]) = ['TMP_0(None)']"]; +TMP_1(None) = SOLIDITY_CALL slice()(msg.data,0,32) +i(bytes[32]) = ['TMP_1(None)']"]; 8->9; 9[label="Node Type: NEW VARIABLE 9 diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_a__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_a__0.txt new file mode 100644 index 000000000..2f0451a52 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_a__0.txt @@ -0,0 +1,28 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: EXPRESSION 1 + +EXPRESSION: +self.b(x,True) + +IRs: +INTERNAL_CALL, default_args.b()(x,True)"]; +1->2; +2[label="Node Type: EXPRESSION 2 + +EXPRESSION: +self.b(1,self.config) + +IRs: +INTERNAL_CALL, default_args.b()(1,config)"]; +2->3; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +self.b(1,z) + +IRs: +INTERNAL_CALL, default_args.b()(1,z)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_b__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_b__0.txt new file mode 100644 index 000000000..23126acae --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_default_args_b__0.txt @@ -0,0 +1,24 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: IF 1 + +EXPRESSION: +config + +IRs: +CONDITION config"]; +1->3[label="True"]; +1->2[label="False"]; +2[label="Node Type: END_IF 2 +"]; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +self.counter = y + +IRs: +counter(uint256) := y(uint256)"]; +3->2; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..753f5a938 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,9 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +MAX_TICKS_UINT = 50 + +IRs: +MAX_TICKS_UINT(uint256) := 50(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_bar__0.txt new file mode 100644 index 000000000..1a19c5614 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_bar__0.txt @@ -0,0 +1,57 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = 0 + +IRs: +a(int128) := 0(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = 0 + +IRs: +b(int128) := 0(uint256)"]; +2->3; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +(a,b) = self.foo() + +IRs: +TUPLE_0(int128,int128) = INTERNAL_CALL, interface_conversion.foo()() +a(int128)= UNPACK TUPLE_0 index: 0 +b(int128)= UNPACK TUPLE_0 index: 1 "]; +3->4; +4[label="Node Type: NEW VARIABLE 4 + +EXPRESSION: +x = 0x0000000000000000000000000000000000000000 + +IRs: +x(address) := 0(address)"]; +4->5; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +c = 0 + +IRs: +c(uint256) := 0(uint256)"]; +5->6; +6[label="Node Type: EXPRESSION 6 + +EXPRESSION: +(a,c) = Test(x).foo() + +IRs: +TMP_0 = CONVERT x to Test +TUPLE_1(int128,uint256) = HIGH_LEVEL_CALL, dest:TMP_0(Test), function:foo, arguments:[] +a(int128)= UNPACK TUPLE_1 index: 0 +c(uint256)= UNPACK TUPLE_1 index: 1 "]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_foo__0.txt new file mode 100644 index 000000000..8d1c1166b --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_foo__0.txt @@ -0,0 +1,12 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: RETURN 1 + +EXPRESSION: +(2,3) + +IRs: +RETURN 2,3"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_struct___default__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_struct___default__0.txt new file mode 100644 index 000000000..7587cdfa2 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_struct___default__0.txt @@ -0,0 +1,28 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +chainlink_lrd = Test(msg.sender).get() + +IRs: +TMP_0 = CONVERT msg.sender to Test +TUPLE_0(uint80,int256,uint256,uint256,uint80) = HIGH_LEVEL_CALL, dest:TMP_0(Test), function:get, arguments:[] +TMP_1(uint80)= UNPACK TUPLE_0 index: 0 +TMP_2(int256)= UNPACK TUPLE_0 index: 1 +TMP_3(uint256)= UNPACK TUPLE_0 index: 2 +TMP_4(uint256)= UNPACK TUPLE_0 index: 3 +TMP_5(uint80)= UNPACK TUPLE_0 index: 4 +chainlink_lrd(FAKE_TUPLE_0_1_2_3_4) = new FAKE_TUPLE_0_1_2_3_4(TMP_1,TMP_2,TMP_3,TMP_4,TMP_5)"]; +1->2; +2[label="Node Type: RETURN 2 + +EXPRESSION: +chainlink_lrd[0] + +IRs: +REF_1(uint80) -> chainlink_lrd._0 +RETURN REF_1"]; +} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_types_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_types_slitherConstructorConstantVariables__0.txt new file mode 100644 index 000000000..b53263a8d --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_types_slitherConstructorConstantVariables__0.txt @@ -0,0 +1,9 @@ +digraph{ +0[label="Node Type: OTHER_ENTRYPOINT 0 + +EXPRESSION: +MAX_BANDS = 10 + +IRs: +MAX_BANDS(uint256) := 10(uint256)"]; +} diff --git a/tests/e2e/vyper_parsing/test_data/ERC20.vy b/tests/e2e/vyper_parsing/test_data/ERC20.vy index 682b8cf26..a3bb62694 100644 --- a/tests/e2e/vyper_parsing/test_data/ERC20.vy +++ b/tests/e2e/vyper_parsing/test_data/ERC20.vy @@ -1,22 +1,9 @@ interface ERC20: - def totalSupply() -> uint256: view - - - def balanceOf(_owner: address) -> uint256: view - - - def allowance(_owner: address, _spender: address) -> uint256: view - - def transfer(_to: address, _value: uint256) -> bool: nonpayable - - def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable - - def approve(_spender: address, _value: uint256) -> bool: nonpayable diff --git a/tests/e2e/vyper_parsing/test_data/builtins.vy b/tests/e2e/vyper_parsing/test_data/builtins.vy index 4fb908a09..4c4a72927 100644 --- a/tests/e2e/vyper_parsing/test_data/builtins.vy +++ b/tests/e2e/vyper_parsing/test_data/builtins.vy @@ -3,29 +3,22 @@ @external def test_builtins(): a: address = block.coinbase - b: uint256 = block.difficulty - c: uint256 = block.prevrandao - d: uint256 = block.number - e: bytes32 = block.prevhash - f: uint256 = block.timestamp - - h: uint256 = chain.id - + h: bytes32 = convert(chain.id, bytes32) i: Bytes[32] = slice(msg.data, 0, 32) - j: uint256 = msg.gas - k: address = msg.sender - l: uint256 = msg.value - m: address = tx.origin - n: uint256 = tx.gasprice - x: uint256 = self.balance + +@external +def c(x: uint256): + user_shares: DynArray[uint256, 10] = [] + user_shares.append(1) + user_shares.pop() diff --git a/tests/e2e/vyper_parsing/test_data/chain.vy b/tests/e2e/vyper_parsing/test_data/chain.vy deleted file mode 100644 index 81a770479..000000000 --- a/tests/e2e/vyper_parsing/test_data/chain.vy +++ /dev/null @@ -1,4 +0,0 @@ - -@external -def test(): - x: bytes32 = convert(chain.id, bytes32) \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/default_args.vy b/tests/e2e/vyper_parsing/test_data/default_args.vy new file mode 100644 index 000000000..10115363b --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/default_args.vy @@ -0,0 +1,12 @@ +counter: uint256 +config: bool +@internal +def b(y: uint256, config: bool = True): + if config: + self.counter = y + +@external +def a(x: uint256, z: bool): + self.b(x) + self.b(1, self.config) + self.b(1, z) \ No newline at end of file diff --git a/tests/e2e/vyper_parsing/test_data/for.vy b/tests/e2e/vyper_parsing/test_data/for.vy index b9f09bf6f..7df83bbbb 100644 --- a/tests/e2e/vyper_parsing/test_data/for.vy +++ b/tests/e2e/vyper_parsing/test_data/for.vy @@ -16,9 +16,6 @@ interface IStrategy: def convertToShares(assets: uint256) -> uint256: view def previewWithdraw(assets: uint256) -> uint256: view - - - struct X: y: int8 diff --git a/tests/e2e/vyper_parsing/test_data/for_break_continue.vy b/tests/e2e/vyper_parsing/test_data/for_break_continue.vy new file mode 100644 index 000000000..3ea8e6cbd --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/for_break_continue.vy @@ -0,0 +1,17 @@ +@external +def f(): + for i in range(100): + if (i > 100): + break + + if (i < 3): + continue + x: uint256 = 10 + for j in range(10): + if (j > 10): + continue + + if (j < 3): + break + + x -= 1 diff --git a/tests/e2e/vyper_parsing/test_data/initarry.vy b/tests/e2e/vyper_parsing/test_data/initarry.vy index bfbd29a27..35c3c0693 100644 --- a/tests/e2e/vyper_parsing/test_data/initarry.vy +++ b/tests/e2e/vyper_parsing/test_data/initarry.vy @@ -3,8 +3,8 @@ interface ERC20: def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable def approve(_spender: address, _value: uint256) -> bool: nonpayable -BORROWED_TOKEN: immutable(ERC20) # x -COLLATERAL_TOKEN: immutable(ERC20) # x +BORROWED_TOKEN: immutable(ERC20) +COLLATERAL_TOKEN: immutable(ERC20) @external def __init__(x: address, y: address): diff --git a/tests/e2e/vyper_parsing/test_data/tricky.vy b/tests/e2e/vyper_parsing/test_data/interface_constant.vy similarity index 100% rename from tests/e2e/vyper_parsing/test_data/tricky.vy rename to tests/e2e/vyper_parsing/test_data/interface_constant.vy diff --git a/tests/e2e/vyper_parsing/test_data/tuple.vy b/tests/e2e/vyper_parsing/test_data/interface_conversion.vy similarity index 99% rename from tests/e2e/vyper_parsing/test_data/tuple.vy rename to tests/e2e/vyper_parsing/test_data/interface_conversion.vy index f0c7e66fe..4bdbd7277 100644 --- a/tests/e2e/vyper_parsing/test_data/tuple.vy +++ b/tests/e2e/vyper_parsing/test_data/interface_conversion.vy @@ -1,5 +1,3 @@ - - interface Test: def foo() -> (int128, uint256): nonpayable diff --git a/tests/e2e/vyper_parsing/test_data/tuple_struct.vy b/tests/e2e/vyper_parsing/test_data/tuple_struct.vy new file mode 100644 index 000000000..1bcb57b85 --- /dev/null +++ b/tests/e2e/vyper_parsing/test_data/tuple_struct.vy @@ -0,0 +1,10 @@ +interface Test: + def get() -> (uint80, int256, uint256, uint256, uint80): view +@external +def __default__() -> uint80: + chainlink_lrd: (uint80, int256, uint256, uint256, uint80) = Test(msg.sender).get() + return chainlink_lrd[0] + + + + diff --git a/tests/e2e/vyper_parsing/test_data/literal.vy b/tests/e2e/vyper_parsing/test_data/types.vy similarity index 86% rename from tests/e2e/vyper_parsing/test_data/literal.vy rename to tests/e2e/vyper_parsing/test_data/types.vy index e0686301e..02f18fe5a 100644 --- a/tests/e2e/vyper_parsing/test_data/literal.vy +++ b/tests/e2e/vyper_parsing/test_data/types.vy @@ -3,13 +3,9 @@ symbol: public(String[32]) decimals: public(uint256) totalSupply: public(uint256) - - - balances: HashMap[address, uint256] allowances: HashMap[address, HashMap[address, uint256]] - MAX_BANDS: constant(uint256) = 10 x: public(uint256[3][4]) From a6209dfe5315b5ceb01582d834e379905b315aa9 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 07:45:12 -0500 Subject: [PATCH 220/338] cleanup --- .../vyper_parsing/declarations/contract.py | 2 - .../expressions/expression_parsing.py | 28 ++----------- .../expressions/find_variable.py | 41 +++++++------------ slither/vyper_parsing/type_parsing.py | 6 +-- .../vyper_parsing/variables/event_variable.py | 1 - 5 files changed, 19 insertions(+), 59 deletions(-) diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 0e2140fa1..a4e098942 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -459,7 +459,6 @@ class ContractVyper: def parse_state_variables(self) -> None: for varNotParsed in self._variablesNotParsed: - print(varNotParsed) var = StateVariable() var.set_contract(self._contract) var.set_offset(varNotParsed.src, self._contract.compilation_unit) @@ -506,7 +505,6 @@ class ContractVyper: var_parser.analyze(self._contract) def analyze(self) -> None: - print("Analyze", self._contract._name) for struct_parser in self._structures_parser: struct_parser.analyze(self._contract) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 3f76ea281..aec07143c 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -74,9 +74,6 @@ from slither.vyper_parsing.ast.types import ( def parse_expression(expression: Dict, caller_context) -> "Expression": - print("parse_expression") - print(expression, "\n") - # assert False if isinstance(expression, Int): literal = Literal(str(expression.value), ElementaryType("uint256")) @@ -106,8 +103,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return literal if isinstance(expression, Call): - print("Call") - print(expression) called = parse_expression(expression.func, caller_context) if isinstance(called, Identifier) and isinstance(called.value, SolidityFunction): if called.value.name == "empty()": @@ -195,8 +190,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": rets = None if isinstance(called, Identifier): - print("called", called) - print("called.value", called.value.__class__.__name__) # Since the AST lacks the type of the return values, we recover it. if isinstance(called.value, Function): rets = called.value.returns @@ -235,7 +228,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return x return str(x.type) - print(rets) # def vars_to_typestr(rets: List[Expression]) -> str: # if len(rets) == 0: # return "" @@ -248,7 +240,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if len(rets) == 1 else f"tuple({','.join(map(get_type_str, rets))})" ) - print(arguments) parsed_expr = CallExpression(called, arguments, type_str) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -258,9 +249,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": if isinstance(expression.value, Name): # TODO this is ambiguous because it could be a state variable or a call to balance if expression.value.id == "self" and member_name != "balance": - var, was_created = find_variable(member_name, caller_context, is_self=True) - if was_created: - var.set_offset(expression.src, caller_context.compilation_unit) + var = find_variable(member_name, caller_context, is_self=True) parsed_expr = SelfIdentifier(var) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) var.references.append(parsed_expr.source_mapping) @@ -286,12 +275,9 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` - print(expr) - print(expr.__class__.__name__) - if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType): # If we access a member of an interface, needs to be interface instead of self namespace - var, was_created = find_variable(member_name, expr.type.type) + var = find_variable(member_name, expr.type.type) if isinstance(var, Function): rets = var.returns @@ -313,9 +299,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return member_access if isinstance(expression, Name): - var, was_created = find_variable(expression.id, caller_context) - if was_created: - var.set_offset(expression.src, caller_context.compilation_unit) + var = find_variable(expression.id, caller_context) parsed_expr = Identifier(var) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -398,12 +382,6 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": return conditions.pop() - for elem in expression.right.elements: - elem_expr = parse_expression(elem, caller_context) - print("elem", repr(elem_expr)) - parsed_expr = BinaryOperation(lhs, elem_expr, inner_op) - parsed_expr.set_offset(expression.src, caller_context.compilation_unit) - conditions.append(parsed_expr) else: # enum type membership check https://docs.vyperlang.org/en/stable/types.html?h#id18 is_member_op = ( BinaryOperationType.get_type("==") diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index e888aa014..06fcce995 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -35,7 +35,6 @@ def _find_variable_in_function_parser( if function_parser is None: return None func_variables = function_parser.variables_as_dict - print("func_variables", func_variables) if var_name in func_variables: return func_variables[var_name] @@ -51,13 +50,11 @@ def _find_in_contract( return None # variable are looked from the contract declarer - print(contract) contract_variables = contract.variables_as_dict if var_name in contract_variables: return contract_variables[var_name] functions = {f.name: f for f in contract.functions if not f.is_shadowed} - # print(functions) if var_name in functions: return functions[var_name] @@ -74,7 +71,7 @@ def _find_in_contract( if var_name in enums: return enums[var_name] - # If the enum is refered as its name rather than its canonicalName + # If the enum is referred as its name rather than its canonicalName enums = {e.name: e for e in contract.enums} if var_name in enums: return enums[var_name] @@ -84,7 +81,7 @@ def _find_in_contract( def find_variable( var_name: str, - caller_context, + caller_context: Union[FunctionContract, Contract], is_self: bool = False, ) -> Tuple[ Union[ @@ -96,8 +93,7 @@ def find_variable( Event, Enum, Structure, - ], - bool, + ] ]: """ Return the variable found and a boolean indicating if the variable was created @@ -107,6 +103,8 @@ def find_variable( :type var_name: :param caller_context: :type caller_context: + :param is_self: + :type is_self: :return: :rtype: """ @@ -114,59 +112,48 @@ def find_variable( from slither.vyper_parsing.declarations.contract import ContractVyper from slither.vyper_parsing.declarations.function import FunctionVyper - print("caller_context") - print(caller_context) - print(caller_context.__class__.__name__) - print("var", var_name) if isinstance(caller_context, Contract): - direct_contracts = [caller_context] - direct_functions = caller_context.functions_declared current_scope = caller_context.file_scope next_context = caller_context else: - direct_contracts = [caller_context.contract] - direct_functions = caller_context.contract.functions_declared current_scope = caller_context.contract.file_scope next_context = caller_context.contract - # print(direct_functions) function_parser: Optional[FunctionVyper] = ( caller_context if isinstance(caller_context, FunctionContract) else None ) - # print("function_parser", function_parser) + # If a local shadows a state variable but the attribute is `self`, we want to # return the state variable and not the local. if not is_self: ret1 = _find_variable_in_function_parser(var_name, function_parser) if ret1: - return ret1, False + return ret1 ret = _find_in_contract(var_name, next_context, caller_context) if ret: - return ret, False + return ret - # print(current_scope.variables) if var_name in current_scope.variables: - return current_scope.variables[var_name], False + return current_scope.variables[var_name] # Could refer to any enum all_enumss = [c.enums_as_dict for c in current_scope.contracts.values()] all_enums = {k: v for d in all_enumss for k, v in d.items()} if var_name in all_enums: - return all_enums[var_name], False + return all_enums[var_name] contracts = current_scope.contracts if var_name in contracts: - return contracts[var_name], False + return contracts[var_name] if var_name in SOLIDITY_VARIABLES: - return SolidityVariable(var_name), False + return SolidityVariable(var_name) if f"{var_name}()" in SOLIDITY_FUNCTIONS: - return SolidityFunction(f"{var_name}()"), False + return SolidityFunction(f"{var_name}()") - print(next_context.events_as_dict) if f"{var_name}()" in next_context.events_as_dict: - return next_context.events_as_dict[f"{var_name}()"], False + return next_context.events_as_dict[f"{var_name}()"] raise VariableNotFound(f"Variable not found: {var_name} (context {caller_context})") diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index fc45a144c..b8f9b468e 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -12,7 +12,7 @@ from slither.core.solidity_types.user_defined_type import UserDefinedType from slither.core.declarations.function_contract import FunctionContract -def parse_type(annotation: Union[Name, Subscript, Call], caller_context): +def parse_type(annotation: Union[Name, Subscript, Call, Tuple], caller_context): from slither.vyper_parsing.expressions.expression_parsing import parse_expression if isinstance(caller_context, FunctionContract): @@ -21,7 +21,7 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): contract = caller_context assert isinstance(annotation, (Name, Subscript, Call, Tuple)) - print(annotation) + if isinstance(annotation, Name): name = annotation.id elif isinstance(annotation, Subscript): @@ -90,11 +90,9 @@ def parse_type(annotation: Union[Name, Subscript, Call], caller_context): if name in contract.structures_as_dict: return UserDefinedType(contract.structures_as_dict[name]) - print(contract.enums_as_dict) if name in contract.enums_as_dict: return UserDefinedType(contract.enums_as_dict[name]) - print(contract.file_scope.contracts) if name in contract.file_scope.contracts: return UserDefinedType(contract.file_scope.contracts[name]) assert False diff --git a/slither/vyper_parsing/variables/event_variable.py b/slither/vyper_parsing/variables/event_variable.py index 5167610a8..2f7fe7c85 100644 --- a/slither/vyper_parsing/variables/event_variable.py +++ b/slither/vyper_parsing/variables/event_variable.py @@ -7,7 +7,6 @@ from slither.vyper_parsing.ast.types import AnnAssign, Call class EventVariableVyper: def __init__(self, variable: EventVariable, variable_data: AnnAssign): - print(variable_data) self._variable = variable self._variable.name = variable_data.target.id if ( From c21798021c3aebbb39348898ba1ed611370d4d28 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 10:11:00 -0500 Subject: [PATCH 221/338] fix some lint warnings --- slither/core/compilation_unit.py | 6 +- slither/slither.py | 3 +- .../visitors/slithir/expression_to_slithir.py | 4 +- slither/vyper_parsing/ast/types.py | 5 +- slither/vyper_parsing/cfg/node.py | 2 +- .../vyper_parsing/declarations/contract.py | 1 - slither/vyper_parsing/declarations/event.py | 1 - .../vyper_parsing/declarations/function.py | 457 +++++++++--------- slither/vyper_parsing/declarations/struct.py | 2 +- .../expressions/expression_parsing.py | 23 +- .../expressions/find_variable.py | 17 +- slither/vyper_parsing/type_parsing.py | 7 +- .../vyper_parsing/variables/event_variable.py | 2 - .../vyper_parsing/variables/state_variable.py | 2 - .../variables/structure_variable.py | 3 - .../vyper_parsing/vyper_compilation_unit.py | 2 +- tests/e2e/vyper_parsing/test_ast_parsing.py | 1 - .../unit/slithir/vyper/test_ir_generation.py | 27 +- 18 files changed, 249 insertions(+), 316 deletions(-) diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 556c6c7da..c1ce98d37 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -38,10 +38,10 @@ class Language(Enum): def from_str(label: str): if label == "solc": return Language.SOLIDITY - elif label == "vyper": + if label == "vyper": return Language.VYPER - else: - raise ValueError(f"Unknown language: {label}") + + raise ValueError(f"Unknown language: {label}") # pylint: disable=too-many-instance-attributes,too-many-public-methods diff --git a/slither/slither.py b/slither/slither.py index 07444c72f..b434cfccb 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -13,6 +13,7 @@ from slither.printers.abstract_printer import AbstractPrinter from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit from slither.utils.output import Output +from slither.vyper_parsing.ast.ast import parse logger = logging.getLogger("Slither") logging.basicConfig() @@ -103,8 +104,6 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes if compilation_unit_slither.is_vyper: vyper_parser = VyperCompilationUnit(compilation_unit_slither) for path, ast in compilation_unit.asts.items(): - from slither.vyper_parsing.ast.ast import parse - ast_nodes = parse(ast["ast"]) vyper_parser.parse_module(ast_nodes, path) self._parsers.append(vyper_parser) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index fa8cef8e3..c43b2507f 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -171,7 +171,9 @@ class ExpressionToSlithIR(ExpressionVisitor): def result(self) -> List[Operation]: return self._result - def _post_assignement_operation(self, expression: AssignmentOperation) -> None: + def _post_assignement_operation( + self, expression: AssignmentOperation + ) -> None: # pylint: disable=too-many-branches,too-many-statements left = get(expression.expression_left) right = get(expression.expression_right) operation: Operation diff --git a/slither/vyper_parsing/ast/types.py b/slither/vyper_parsing/ast/types.py index 6eff6d252..d62bf6fb4 100644 --- a/slither/vyper_parsing/ast/types.py +++ b/slither/vyper_parsing/ast/types.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import List, Optional, Dict, Union, ForwardRef +from typing import List, Optional, Union from dataclasses import dataclass @@ -167,9 +167,6 @@ class Raise(ASTNode): exc: ASTNode -from enum import Enum - - @dataclass class Expr(ASTNode): value: ASTNode diff --git a/slither/vyper_parsing/cfg/node.py b/slither/vyper_parsing/cfg/node.py index 3d5ffee91..5a584fe16 100644 --- a/slither/vyper_parsing/cfg/node.py +++ b/slither/vyper_parsing/cfg/node.py @@ -1,4 +1,4 @@ -from typing import Union, Optional, Dict, TYPE_CHECKING +from typing import Optional, Dict from slither.core.cfg.node import Node from slither.core.cfg.node import NodeType diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index a4e098942..2cd14f1d0 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -1,4 +1,3 @@ -import logging from pathlib import Path from typing import List, TYPE_CHECKING from slither.vyper_parsing.ast.types import ( diff --git a/slither/vyper_parsing/declarations/event.py b/slither/vyper_parsing/declarations/event.py index e6ed5a12e..b73e46211 100644 --- a/slither/vyper_parsing/declarations/event.py +++ b/slither/vyper_parsing/declarations/event.py @@ -1,7 +1,6 @@ """ Event module """ -from typing import TYPE_CHECKING, Dict from slither.core.variables.event_variable import EventVariable from slither.vyper_parsing.variables.event_variable import EventVariableVyper diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 9932a7c22..17d77cfb9 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -1,16 +1,13 @@ -import logging -from typing import Dict, Optional, Union, List, TYPE_CHECKING, Tuple, Set +from typing import Dict, Union, List, TYPE_CHECKING, Tuple -from slither.core.cfg.node import NodeType, link_nodes, insert_node, Node +from slither.core.cfg.node import NodeType, link_nodes, Node from slither.core.cfg.scope import Scope -from slither.core.declarations.contract import Contract from slither.core.declarations.function import ( Function, FunctionType, ) from slither.core.declarations.function import ModifierStatements from slither.core.declarations.modifier import Modifier -from slither.core.expressions import AssignmentOperation from slither.core.source_mapping.source_mapping import Source from slither.core.variables.local_variable import LocalVariable from slither.vyper_parsing.cfg.node import NodeVyper @@ -41,6 +38,7 @@ class FunctionVyper: self._functionNotParsed = function_data self._decoratorNotParsed = None self._local_variables_parser: List[LocalVariableVyper] = [] + self._variables_renamed = [] self._contract_parser = contract_parser self._node_to_NodeVyper: Dict[Node, NodeVyper] = {} @@ -226,277 +224,268 @@ class FunctionVyper: self._function.entry_point = entry_node.underlying_node scope = Scope(True, False, self.underlying_function) - curr_node = entry_node - for expr in cfg: + def parse_statement( + curr_node: NodeVyper, + expr: ASTNode, + continue_destination=None, + break_destination=None, + ) -> NodeVyper: + if isinstance(expr, AnnAssign): + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) + + local_var_parser = LocalVariableVyper(local_var, expr) + self._add_local_variable(local_var_parser) + + new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + if expr.value is not None: + local_var.initialized = True + new_node.add_unparsed_expression(expr.value) + new_node.underlying_node.add_variable_declaration(local_var) + link_underlying_nodes(curr_node, new_node) - def parse_statement( - curr_node: NodeVyper, - expr: ASTNode, - continue_destination=None, - break_destination=None, - ) -> NodeVyper: - if isinstance(expr, AnnAssign): - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) - - local_var_parser = LocalVariableVyper(local_var, expr) - self._add_local_variable(local_var_parser) - - new_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - if expr.value is not None: - local_var.initialized = True - new_node.add_unparsed_expression(expr.value) - new_node.underlying_node.add_variable_declaration(local_var) - link_underlying_nodes(curr_node, new_node) + curr_node = new_node - curr_node = new_node + elif isinstance(expr, (AugAssign, Assign)): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) + link_underlying_nodes(curr_node, new_node) - elif isinstance(expr, (AugAssign, Assign)): + curr_node = new_node + + elif isinstance(expr, Expr): + # TODO This is a workaround to handle Vyper putting payable/view in the function body... + if not isinstance(expr.value, Name): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr) + new_node.add_unparsed_expression(expr.value) link_underlying_nodes(curr_node, new_node) curr_node = new_node - elif isinstance(expr, Expr): - # TODO This is a workaround to handle Vyper putting payable/view in the function body... - if not isinstance(expr.value, Name): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr.value) - link_underlying_nodes(curr_node, new_node) + elif isinstance(expr, For): - curr_node = new_node + node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) + node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) - elif isinstance(expr, For): + link_underlying_nodes(curr_node, node_startLoop) - node_startLoop = self._new_node(NodeType.STARTLOOP, expr.src, scope) - node_endLoop = self._new_node(NodeType.ENDLOOP, expr.src, scope) + local_var = LocalVariable() + local_var.set_function(self._function) + local_var.set_offset(expr.src, self._function.compilation_unit) - link_underlying_nodes(curr_node, node_startLoop) - - local_var = LocalVariable() - local_var.set_function(self._function) - local_var.set_offset(expr.src, self._function.compilation_unit) - - counter_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=Name("-1:-1:-1", -1, "counter_var"), - annotation=Name("-1:-1:-1", -1, "uint256"), - value=Int("-1:-1:-1", -1, 0), - ) - local_var_parser = LocalVariableVyper(local_var, counter_var) - self._add_local_variable(local_var_parser) - counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) - local_var.initialized = True - counter_node.add_unparsed_expression(counter_var.value) - counter_node.underlying_node.add_variable_declaration(local_var) - - link_underlying_nodes(node_startLoop, counter_node) - - node_condition = None - if isinstance(expr.iter, (Attribute, Name)): - # HACK - # The loop variable is not annotated so we infer its type by looking at the type of the iterator - if isinstance(expr.iter, Attribute): # state variable - iter_expr = expr.iter - loop_iterator = list( - filter( - lambda x: x._variable.name == iter_expr.attr, - self._contract_parser._variables_parser, - ) - )[0] - - else: # local variable - iter_expr = expr.iter - loop_iterator = list( - filter( - lambda x: x._variable.name == iter_expr.id, - self._local_variables_parser, - ) - )[0] - - # TODO use expr.src instead of -1:-1:1? - cond_expr = Compare( - "-1:-1:-1", - -1, - left=Name("-1:-1:-1", -1, "counter_var"), - op="<=", - right=Call( - "-1:-1:-1", - -1, - func=Name("-1:-1:-1", -1, "len"), - args=[iter_expr], - keywords=[], - keyword=None, - ), - ) - node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) - node_condition.add_unparsed_expression(cond_expr) - - if loop_iterator._elem_to_parse.value.id == "DynArray": - loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[ - 0 - ] - else: - loop_var_annotation = loop_iterator._elem_to_parse.value - - value = Subscript( - "-1:-1:-1", - -1, - value=Name("-1:-1:-1", -1, loop_iterator._variable.name), - slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var")), - ) - loop_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=expr.target, - annotation=loop_var_annotation, - value=value, - ) - - elif isinstance(expr.iter, Call): # range - range_val = expr.iter.args[0] - cond_expr = Compare( + counter_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=Name("-1:-1:-1", -1, "counter_var"), + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Int("-1:-1:-1", -1, 0), + ) + local_var_parser = LocalVariableVyper(local_var, counter_var) + self._add_local_variable(local_var_parser) + counter_node = self._new_node(NodeType.VARIABLE, expr.src, scope) + local_var.initialized = True + counter_node.add_unparsed_expression(counter_var.value) + counter_node.underlying_node.add_variable_declaration(local_var) + + link_underlying_nodes(node_startLoop, counter_node) + + node_condition = None + if isinstance(expr.iter, (Attribute, Name)): + # HACK + # The loop variable is not annotated so we infer its type by looking at the type of the iterator + if isinstance(expr.iter, Attribute): # state variable + iter_expr = expr.iter + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.attr, + self._contract_parser._variables_parser, + ) + )[0] + + else: # local variable + iter_expr = expr.iter + loop_iterator = list( + filter( + lambda x: x._variable.name == iter_expr.id, + self._local_variables_parser, + ) + )[0] + + # TODO use expr.src instead of -1:-1:1? + cond_expr = Compare( + "-1:-1:-1", + -1, + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=Call( "-1:-1:-1", -1, - left=Name("-1:-1:-1", -1, "counter_var"), - op="<=", - right=range_val, - ) - node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) - node_condition.add_unparsed_expression(cond_expr) - loop_var = AnnAssign( - expr.target.src, - expr.target.node_id, - target=expr.target, - annotation=Name("-1:-1:-1", -1, "uint256"), - value=Name("-1:-1:-1", -1, "counter_var"), - ) + func=Name("-1:-1:-1", -1, "len"), + args=[iter_expr], + keywords=[], + keyword=None, + ), + ) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) + if loop_iterator._elem_to_parse.value.id == "DynArray": + loop_var_annotation = loop_iterator._elem_to_parse.slice.value.elements[0] else: - raise NotImplementedError + loop_var_annotation = loop_iterator._elem_to_parse.value - # After creating condition node, we link it declaration of the loop variable - link_underlying_nodes(counter_node, node_condition) + value = Subscript( + "-1:-1:-1", + -1, + value=Name("-1:-1:-1", -1, loop_iterator._variable.name), + slice=Index("-1:-1:-1", -1, value=Name("-1:-1:-1", -1, "counter_var")), + ) + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=loop_var_annotation, + value=value, + ) - # Create an expression for the loop increment (counter_var += 1) - loop_increment = AugAssign( + elif isinstance(expr.iter, Call): # range + range_val = expr.iter.args[0] + cond_expr = Compare( "-1:-1:-1", -1, - target=Name("-1:-1:-1", -1, "counter_var"), - op="+=", - value=Int("-1:-1:-1", -1, 1), + left=Name("-1:-1:-1", -1, "counter_var"), + op="<=", + right=range_val, + ) + node_condition = self._new_node(NodeType.IFLOOP, expr.src, scope) + node_condition.add_unparsed_expression(cond_expr) + loop_var = AnnAssign( + expr.target.src, + expr.target.node_id, + target=expr.target, + annotation=Name("-1:-1:-1", -1, "uint256"), + value=Name("-1:-1:-1", -1, "counter_var"), ) - node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) - node_increment.add_unparsed_expression(loop_increment) - link_underlying_nodes(node_increment, node_condition) - - prev_continue_destination = continue_destination - prev_break_destination = break_destination - continue_destination = node_increment - break_destination = node_endLoop - - # We assign the index variable or range variable in the loop body on each iteration - expr.body.insert(0, loop_var) - body_node = None - new_node = node_condition - for stmt in expr.body: - body_node = parse_statement( - new_node, stmt, continue_destination, break_destination - ) - new_node = body_node - - # Reset to previous jump destinations for nested loops - continue_destination = prev_continue_destination - break_destination = prev_break_destination - - if body_node is not None: - link_underlying_nodes(body_node, node_increment) - - link_underlying_nodes(node_condition, node_endLoop) - - curr_node = node_endLoop - - elif isinstance(expr, Continue): - new_node = self._new_node(NodeType.CONTINUE, expr.src, scope) - link_underlying_nodes(curr_node, new_node) - link_underlying_nodes(new_node, continue_destination) - elif isinstance(expr, Break): - new_node = self._new_node(NodeType.BREAK, expr.src, scope) - link_underlying_nodes(curr_node, new_node) - link_underlying_nodes(new_node, break_destination) + else: + raise NotImplementedError + + # After creating condition node, we link it declaration of the loop variable + link_underlying_nodes(counter_node, node_condition) + + # Create an expression for the loop increment (counter_var += 1) + loop_increment = AugAssign( + "-1:-1:-1", + -1, + target=Name("-1:-1:-1", -1, "counter_var"), + op="+=", + value=Int("-1:-1:-1", -1, 1), + ) + node_increment = self._new_node(NodeType.EXPRESSION, expr.src, scope) + node_increment.add_unparsed_expression(loop_increment) + link_underlying_nodes(node_increment, node_condition) + + continue_destination = node_increment + break_destination = node_endLoop + + # We assign the index variable or range variable in the loop body on each iteration + expr.body.insert(0, loop_var) + body_node = None + new_node = node_condition + for stmt in expr.body: + body_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) + new_node = body_node - elif isinstance(expr, Return): - new_node = self._new_node(NodeType.RETURN, expr.src, scope) - if expr.value is not None: - new_node.add_unparsed_expression(expr.value) + if body_node is not None: + link_underlying_nodes(body_node, node_increment) - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + link_underlying_nodes(node_condition, node_endLoop) - elif isinstance(expr, Assert): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr) + curr_node = node_endLoop - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + elif isinstance(expr, Continue): + new_node = self._new_node(NodeType.CONTINUE, expr.src, scope) + link_underlying_nodes(curr_node, new_node) + link_underlying_nodes(new_node, continue_destination) - elif isinstance(expr, Log): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + elif isinstance(expr, Break): + new_node = self._new_node(NodeType.BREAK, expr.src, scope) + link_underlying_nodes(curr_node, new_node) + link_underlying_nodes(new_node, break_destination) + + elif isinstance(expr, Return): + new_node = self._new_node(NodeType.RETURN, expr.src, scope) + if expr.value is not None: new_node.add_unparsed_expression(expr.value) - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - elif isinstance(expr, If): - condition_node = self._new_node(NodeType.IF, expr.test.src, scope) - condition_node.add_unparsed_expression(expr.test) + elif isinstance(expr, Assert): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) - endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - true_node = None - new_node = condition_node - for stmt in expr.body: - true_node = parse_statement( - new_node, stmt, continue_destination, break_destination - ) - new_node = true_node + elif isinstance(expr, Log): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr.value) - link_underlying_nodes(true_node, endIf_node) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node - false_node = None - new_node = condition_node - for stmt in expr.orelse: - false_node = parse_statement( - new_node, stmt, continue_destination, break_destination - ) - new_node = false_node + elif isinstance(expr, If): + condition_node = self._new_node(NodeType.IF, expr.test.src, scope) + condition_node.add_unparsed_expression(expr.test) - if false_node is not None: - link_underlying_nodes(false_node, endIf_node) + endIf_node = self._new_node(NodeType.ENDIF, expr.src, scope) - else: - link_underlying_nodes(condition_node, endIf_node) + true_node = None + new_node = condition_node + for stmt in expr.body: + true_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) + new_node = true_node - link_underlying_nodes(curr_node, condition_node) - curr_node = endIf_node + link_underlying_nodes(true_node, endIf_node) - elif isinstance(expr, Pass): - pass - elif isinstance(expr, Raise): - new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) - new_node.add_unparsed_expression(expr) - link_underlying_nodes(curr_node, new_node) - curr_node = new_node + false_node = None + new_node = condition_node + for stmt in expr.orelse: + false_node = parse_statement( + new_node, stmt, continue_destination, break_destination + ) + new_node = false_node + + if false_node is not None: + link_underlying_nodes(false_node, endIf_node) else: - raise ParsingError(f"Statement not parsed {expr.__class__.__name__} {expr}") + link_underlying_nodes(condition_node, endIf_node) + + link_underlying_nodes(curr_node, condition_node) + curr_node = endIf_node - return curr_node + elif isinstance(expr, Pass): + pass + elif isinstance(expr, Raise): + new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) + new_node.add_unparsed_expression(expr) + link_underlying_nodes(curr_node, new_node) + curr_node = new_node + + else: + raise ParsingError(f"Statement not parsed {expr.__class__.__name__} {expr}") + return curr_node + + curr_node = entry_node + for expr in cfg: curr_node = parse_statement(curr_node, expr) # endregion diff --git a/slither/vyper_parsing/declarations/struct.py b/slither/vyper_parsing/declarations/struct.py index 70a6bd7b7..308dbcb2b 100644 --- a/slither/vyper_parsing/declarations/struct.py +++ b/slither/vyper_parsing/declarations/struct.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Dict, List +from typing import List from slither.core.declarations.structure import Structure from slither.core.variables.structure_variable import StructureVariable diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index aec07143c..a5a031ecf 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -1,8 +1,5 @@ -import logging -import re -from typing import Union, Dict, TYPE_CHECKING, List, Any - -import slither.core.expressions.type_conversion +from typing import Dict, TYPE_CHECKING +from collections import deque from slither.core.declarations.solidity_variables import ( SOLIDITY_VARIABLES_COMPOSED, SolidityVariableComposed, @@ -10,16 +7,11 @@ from slither.core.declarations.solidity_variables import ( from slither.core.declarations import SolidityFunction, Function from slither.core.expressions import ( CallExpression, - ConditionalExpression, ElementaryTypeNameExpression, Identifier, IndexAccess, Literal, MemberAccess, - NewArray, - NewContract, - NewElementaryType, - SuperCallExpression, SelfIdentifier, TupleExpression, TypeConversion, @@ -43,12 +35,6 @@ from slither.core.declarations.contract import Contract from slither.vyper_parsing.expressions.find_variable import find_variable from slither.vyper_parsing.type_parsing import parse_type from slither.all_exceptions import ParsingError - -if TYPE_CHECKING: - from slither.core.expressions.expression import Expression - - -from collections import deque from slither.vyper_parsing.ast.types import ( Int, Call, @@ -72,8 +58,11 @@ from slither.vyper_parsing.ast.types import ( Raise, ) +if TYPE_CHECKING: + from slither.core.expressions.expression import Expression + -def parse_expression(expression: Dict, caller_context) -> "Expression": +def parse_expression(expression: Dict, caller_context) -> "Expression": # pylint if isinstance(expression, Int): literal = Literal(str(expression.value), ElementaryType("uint256")) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index 06fcce995..cc6a48ae7 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -1,27 +1,17 @@ -from typing import TYPE_CHECKING, Optional, Union, List, Tuple +from typing import TYPE_CHECKING, Optional, Union, Tuple from slither.core.declarations import Event, Enum, Structure from slither.core.declarations.contract import Contract from slither.core.declarations.custom_error import CustomError from slither.core.declarations.function import Function from slither.core.declarations.function_contract import FunctionContract -from slither.core.declarations.function_top_level import FunctionTopLevel -from slither.core.declarations.solidity_import_placeholder import SolidityImportPlaceHolder from slither.core.declarations.solidity_variables import ( SOLIDITY_FUNCTIONS, SOLIDITY_VARIABLES, SolidityFunction, SolidityVariable, ) -from slither.core.scope.scope import FileScope -from slither.core.solidity_types import ( - ArrayType, - FunctionType, - MappingType, - TypeAlias, -) from slither.core.variables.variable import Variable -from slither.exceptions import SlitherError from slither.solc_parsing.exceptions import VariableNotFound if TYPE_CHECKING: @@ -109,8 +99,9 @@ def find_variable( :rtype: """ - from slither.vyper_parsing.declarations.contract import ContractVyper - from slither.vyper_parsing.declarations.function import FunctionVyper + from slither.vyper_parsing.declarations.function import ( + FunctionVyper, + ) # pylint: disable=import-outside-toplevel if isinstance(caller_context, Contract): current_scope = caller_context.file_scope diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index b8f9b468e..21d91e513 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -12,7 +12,9 @@ from slither.core.solidity_types.user_defined_type import UserDefinedType from slither.core.declarations.function_contract import FunctionContract -def parse_type(annotation: Union[Name, Subscript, Call, Tuple], caller_context): +def parse_type( + annotation: Union[Name, Subscript, Call, Tuple], caller_context +): # pylint disable=too-many-branches,too-many-return-statements,import-outside-toplevel from slither.vyper_parsing.expressions.expression_parsing import parse_expression if isinstance(caller_context, FunctionContract): @@ -33,8 +35,7 @@ def parse_type(annotation: Union[Name, Subscript, Call, Tuple], caller_context): type_ = parse_type(annotation.slice.value.elements[0], caller_context) length = parse_expression(annotation.slice.value.elements[1], caller_context) return ArrayType(type_, length) - else: - assert annotation.value.id == "HashMap" + if annotation.value.id == "HashMap": type_from = parse_type(annotation.slice.value.elements[0], caller_context) type_to = parse_type(annotation.slice.value.elements[1], caller_context) diff --git a/slither/vyper_parsing/variables/event_variable.py b/slither/vyper_parsing/variables/event_variable.py index 2f7fe7c85..507c17665 100644 --- a/slither/vyper_parsing/variables/event_variable.py +++ b/slither/vyper_parsing/variables/event_variable.py @@ -1,5 +1,3 @@ -from typing import Dict - from slither.core.variables.event_variable import EventVariable from slither.vyper_parsing.type_parsing import parse_type from slither.vyper_parsing.ast.types import AnnAssign, Call diff --git a/slither/vyper_parsing/variables/state_variable.py b/slither/vyper_parsing/variables/state_variable.py index a2e925a6e..361bbaba6 100644 --- a/slither/vyper_parsing/variables/state_variable.py +++ b/slither/vyper_parsing/variables/state_variable.py @@ -1,5 +1,3 @@ -from typing import Dict - from slither.core.variables.state_variable import StateVariable from slither.vyper_parsing.ast.types import VariableDecl from slither.vyper_parsing.type_parsing import parse_type diff --git a/slither/vyper_parsing/variables/structure_variable.py b/slither/vyper_parsing/variables/structure_variable.py index eab7a71c4..7bef8712e 100644 --- a/slither/vyper_parsing/variables/structure_variable.py +++ b/slither/vyper_parsing/variables/structure_variable.py @@ -1,6 +1,3 @@ -from typing import Dict - - from slither.core.variables.structure_variable import StructureVariable from slither.vyper_parsing.type_parsing import parse_type from slither.vyper_parsing.ast.types import AnnAssign diff --git a/slither/vyper_parsing/vyper_compilation_unit.py b/slither/vyper_parsing/vyper_compilation_unit.py index d4ebf8415..2a47d9864 100644 --- a/slither/vyper_parsing/vyper_compilation_unit.py +++ b/slither/vyper_parsing/vyper_compilation_unit.py @@ -25,7 +25,7 @@ class VyperCompilationUnit: sourceUnit = int(sourceUnit_candidates[0]) self._compilation_unit.source_units[sourceUnit] = filename - if os.path.isfile(filename) and not filename in self._compilation_unit.core.source_code: + if os.path.isfile(filename) and filename not in self._compilation_unit.core.source_code: self._compilation_unit.core.add_source_code(filename) scope = self._compilation_unit.get_scope(filename) diff --git a/tests/e2e/vyper_parsing/test_ast_parsing.py b/tests/e2e/vyper_parsing/test_ast_parsing.py index 8529f3e1c..7ca818436 100644 --- a/tests/e2e/vyper_parsing/test_ast_parsing.py +++ b/tests/e2e/vyper_parsing/test_ast_parsing.py @@ -1,4 +1,3 @@ -from typing import Dict from pathlib import Path from slither import Slither diff --git a/tests/unit/slithir/vyper/test_ir_generation.py b/tests/unit/slithir/vyper/test_ir_generation.py index 6bcdaab10..73c9b5e70 100644 --- a/tests/unit/slithir/vyper/test_ir_generation.py +++ b/tests/unit/slithir/vyper/test_ir_generation.py @@ -1,38 +1,13 @@ # # pylint: disable=too-many-lines -import pathlib -from argparse import ArgumentTypeError -from collections import defaultdict -from inspect import getsourcefile -from typing import Union, List, Dict, Callable -import pytest -from slither import Slither -from slither.core.cfg.node import Node, NodeType -from slither.core.declarations import Function, Contract -from slither.core.solidity_types import ArrayType, ElementaryType -from slither.core.variables.local_variable import LocalVariable -from slither.core.variables.state_variable import StateVariable +from slither.core.solidity_types import ElementaryType from slither.slithir.operations import ( - OperationWithLValue, Phi, - Assignment, - HighLevelCall, - Return, - Operation, - Binary, - BinaryType, InternalCall, - Index, - InitArray, ) -from slither.slithir.utils.ssa import is_used_later from slither.slithir.variables import ( Constant, - ReferenceVariable, - LocalIRVariable, - StateIRVariable, - TemporaryVariableSSA, ) From e80238d8e94b5adce5447d39767fbce85ce0a411 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 13:09:49 -0500 Subject: [PATCH 222/338] add struct defs to file scope --- slither/vyper_parsing/declarations/contract.py | 2 ++ slither/vyper_parsing/type_parsing.py | 3 +++ ...ant_slitherConstructorConstantVariables__0.txt | 4 ++-- .../vyper_parsing/test_data/interface_constant.vy | 15 +++++---------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 2cd14f1d0..e1b8ffd67 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -453,6 +453,8 @@ class ContractVyper: st_parser = StructVyper(st, struct) self._contract.structures_as_dict[st.name] = st self._structures_parser.append(st_parser) + # Interfaces can refer to struct defs + self._contract.file_scope.structures[st.name] = st self._structuresNotParsed = [] diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index 21d91e513..e11a4a9f7 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -96,4 +96,7 @@ def parse_type( if name in contract.file_scope.contracts: return UserDefinedType(contract.file_scope.contracts[name]) + + if name in contract.file_scope.structures: + return UserDefinedType(contract.file_scope.structures[name]) assert False diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt index 753f5a938..31ff6d408 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_constant_slitherConstructorConstantVariables__0.txt @@ -2,8 +2,8 @@ digraph{ 0[label="Node Type: OTHER_ENTRYPOINT 0 EXPRESSION: -MAX_TICKS_UINT = 50 +MY_CONSTANT = 50 IRs: -MAX_TICKS_UINT(uint256) := 50(uint256)"]; +MY_CONSTANT(uint256) := 50(uint256)"]; } diff --git a/tests/e2e/vyper_parsing/test_data/interface_constant.vy b/tests/e2e/vyper_parsing/test_data/interface_constant.vy index 4a5b71851..7e6612c68 100644 --- a/tests/e2e/vyper_parsing/test_data/interface_constant.vy +++ b/tests/e2e/vyper_parsing/test_data/interface_constant.vy @@ -1,12 +1,7 @@ -interface LMGauge: - def callback_collateral_shares(n: int256, collateral_per_share: DynArray[uint256, MAX_TICKS_UINT]): nonpayable - def callback_user_shares(user: address, n: int256, user_shares: DynArray[uint256, MAX_TICKS_UINT]): nonpayable +struct MyStruct: + liquidation_range: address +MY_CONSTANT: constant(uint256) = 50 +interface MyInterface: + def my_func(a: int256, b: DynArray[uint256, MY_CONSTANT]) -> MyStruct: nonpayable -MAX_TICKS_UINT: constant(uint256) = 50 - - -struct Loan: - liquidation_range: LMGauge - -x: public(Loan) \ No newline at end of file From 239369c853d5e8817f2fc9ed3f806450fb77340e Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 13:14:54 -0500 Subject: [PATCH 223/338] propagate return type on call to state variable with interface type --- .../expressions/expression_parsing.py | 24 +++++++- ...yper_cfgir_interface_conversion_baz__0.txt | 56 +++++++++++++++++++ .../test_data/interface_conversion.vy | 12 ++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_baz__0.txt diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index a5a031ecf..50dd05cf2 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -5,6 +5,7 @@ from slither.core.declarations.solidity_variables import ( SolidityVariableComposed, ) from slither.core.declarations import SolidityFunction, Function +from slither.core.variables.state_variable import StateVariable from slither.core.expressions import ( CallExpression, ElementaryTypeNameExpression, @@ -63,6 +64,7 @@ if TYPE_CHECKING: def parse_expression(expression: Dict, caller_context) -> "Expression": # pylint + print("parse_expression", expression) if isinstance(expression, Int): literal = Literal(str(expression.value), ElementaryType("uint256")) @@ -178,8 +180,8 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin arguments = [parse_expression(a, caller_context) for a in expression.args] rets = None + # Since the AST lacks the type of the return values, we recover it. if isinstance(called, Identifier): - # Since the AST lacks the type of the return values, we recover it. if isinstance(called.value, Function): rets = called.value.returns # Default arguments are not represented in the AST, so we recover them as well. @@ -264,7 +266,25 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` - if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType): + if isinstance(expr, Identifier) and isinstance(expr.value, StateVariable) and isinstance(expr.value.type, UserDefinedType) and isinstance(expr.value.type.type, Contract): + # If we access a member of an interface, needs to be interface instead of self namespace + var = find_variable(member_name, expr.value.type.type) + if isinstance(var, Function): + rets = var.returns + + def get_type_str(x): + if isinstance(x, str): + return x + return str(x.type) + + type_str = ( + get_type_str(rets[0]) + if len(rets) == 1 + else f"tuple({','.join(map(get_type_str, rets))})" + ) + member_name_ret_type = type_str + + if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType) and isinstance(expr.type.type, Contract): # If we access a member of an interface, needs to be interface instead of self namespace var = find_variable(member_name, expr.type.type) if isinstance(var, Function): diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_baz__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_baz__0.txt new file mode 100644 index 000000000..4280229d0 --- /dev/null +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_interface_conversion_baz__0.txt @@ -0,0 +1,56 @@ +digraph{ +0[label="Node Type: ENTRY_POINT 0 +"]; +0->1; +1[label="Node Type: NEW VARIABLE 1 + +EXPRESSION: +a = 0 + +IRs: +a(int128) := 0(uint256)"]; +1->2; +2[label="Node Type: NEW VARIABLE 2 + +EXPRESSION: +b = 0 + +IRs: +b(int128) := 0(uint256)"]; +2->3; +3[label="Node Type: EXPRESSION 3 + +EXPRESSION: +(a,b) = self.foo() + +IRs: +TUPLE_2(int128,int128) = INTERNAL_CALL, interface_conversion.foo()() +a(int128)= UNPACK TUPLE_2 index: 0 +b(int128)= UNPACK TUPLE_2 index: 1 "]; +3->4; +4[label="Node Type: NEW VARIABLE 4 + +EXPRESSION: +x = 0x0000000000000000000000000000000000000000 + +IRs: +x(address) := 0(address)"]; +4->5; +5[label="Node Type: NEW VARIABLE 5 + +EXPRESSION: +c = 0 + +IRs: +c(uint256) := 0(uint256)"]; +5->6; +6[label="Node Type: EXPRESSION 6 + +EXPRESSION: +(a,c) = self.tester.foo() + +IRs: +TUPLE_3(int128,uint256) = HIGH_LEVEL_CALL, dest:tester(Test), function:foo, arguments:[] +a(int128)= UNPACK TUPLE_3 index: 0 +c(uint256)= UNPACK TUPLE_3 index: 1 "]; +} diff --git a/tests/e2e/vyper_parsing/test_data/interface_conversion.vy b/tests/e2e/vyper_parsing/test_data/interface_conversion.vy index 4bdbd7277..ad30f0ebf 100644 --- a/tests/e2e/vyper_parsing/test_data/interface_conversion.vy +++ b/tests/e2e/vyper_parsing/test_data/interface_conversion.vy @@ -1,6 +1,8 @@ interface Test: def foo() -> (int128, uint256): nonpayable +tester: Test + @internal def foo() -> (int128, int128): return 2, 3 @@ -15,3 +17,13 @@ def bar(): c: uint256 = 0 a, c = Test(x).foo() +@external +def baz(): + a: int128 = 0 + b: int128 = 0 + (a, b) = self.foo() + + x: address = 0x0000000000000000000000000000000000000000 + c: uint256 = 0 + a, c = self.tester.foo() + From e8fa8b85fa039dc303628fe545c618f39db8b5a5 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 13:15:41 -0500 Subject: [PATCH 224/338] more cleanup --- slither/core/compilation_unit.py | 4 ++ slither/core/declarations/function.py | 8 +-- .../core/declarations/solidity_variables.py | 4 +- slither/core/expressions/identifier.py | 1 - slither/detectors/abstract_detector.py | 2 +- .../visitors/slithir/expression_to_slithir.py | 1 - ...ast_parsing__vyper_cfgir_chain_test__0.txt | 13 ---- ...st_parsing__vyper_cfgir_if_compute__0.txt} | 72 +++++++++---------- ...slitherConstructorConstantVariables__0.txt | 9 --- ...slitherConstructorConstantVariables__0.txt | 9 --- .../ast_parsing__vyper_cfgir_tuple_bar__0.txt | 57 --------------- .../ast_parsing__vyper_cfgir_tuple_foo__0.txt | 12 ---- tests/e2e/vyper_parsing/test_data/if.vy | 37 +++++----- 13 files changed, 64 insertions(+), 165 deletions(-) delete mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt rename tests/e2e/vyper_parsing/snapshots/{ast_parsing__vyper_cfgir_if_limit_p_o__0.txt => ast_parsing__vyper_cfgir_if_compute__0.txt} (65%) delete mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt delete mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt delete mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt delete mode 100644 tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index c1ce98d37..23387e6fc 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -97,6 +97,10 @@ class SlitherCompilationUnit(Context): # region Compiler ################################################################################### ################################################################################### + @property + def language(self) -> Language: + return self._language + @property def is_vyper(self) -> bool: return self._language == Language.VYPER diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index a4a172b97..e803154d0 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -107,7 +107,6 @@ def _filter_state_variables_written(expressions: List["Expression"]): return ret -# TODO replace class FunctionLanguage(Enum): Solidity = 0 Yul = 1 @@ -220,8 +219,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu self.compilation_unit: "SlitherCompilationUnit" = compilation_unit - # Assume we are analyzing Solidity by default - self.function_language: FunctionLanguage = FunctionLanguage.Solidity + self.function_language: FunctionLanguage = ( + FunctionLanguage.Solidity if compilation_unit.is_solidity else FunctionLanguage.Vyper + ) self._id: Optional[str] = None @@ -1527,7 +1527,6 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu def _analyze_read_write(self) -> None: """Compute variables read/written/...""" write_var = [x.variables_written_as_expression for x in self.nodes] - print(write_var) write_var = [x for x in write_var if x] write_var = [item for sublist in write_var for item in sublist] write_var = list(set(write_var)) @@ -1763,7 +1762,6 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu node.irs_ssa = [ir for ir in node.irs_ssa if not self._unchange_phi(ir)] def generate_slithir_and_analyze(self) -> None: - print("generate_slithir_and_analyze") for node in self.nodes: node.slithir_generation() diff --git a/slither/core/declarations/solidity_variables.py b/slither/core/declarations/solidity_variables.py index d5aec009f..7c81266bf 100644 --- a/slither/core/declarations/solidity_variables.py +++ b/slither/core/declarations/solidity_variables.py @@ -17,6 +17,7 @@ SOLIDITY_VARIABLES = { "block": "", "super": "", "chain": "", + "ZERO_ADDRESS": "address", } SOLIDITY_VARIABLES_COMPOSED = { @@ -89,8 +90,9 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = { "codehash(address)": ["bytes32"], # Vyper "create_from_blueprint()": [], + "create_minimal_proxy_to()": [], "empty()": [], - "convert()": [], # TODO make type conversion + "convert()": [], "len()": ["uint256"], "method_id()": [], "unsafe_sub()": [], diff --git a/slither/core/expressions/identifier.py b/slither/core/expressions/identifier.py index d4c426100..5cd29a9f5 100644 --- a/slither/core/expressions/identifier.py +++ b/slither/core/expressions/identifier.py @@ -26,7 +26,6 @@ class Identifier(Expression): ], ) -> None: super().__init__() - assert value # pylint: disable=import-outside-toplevel from slither.core.declarations import Contract, SolidityVariable, SolidityFunction from slither.solc_parsing.yul.evm_functions import YulBuiltin diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index c3f661a11..8baf9bb3c 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -182,7 +182,7 @@ class AbstractDetector(metaclass=abc.ABCMeta): and self.compilation_unit.solc_version in self.VULNERABLE_SOLC_VERSIONS ) if self.LANGUAGE: - return self.compilation_unit._language.value == self.LANGUAGE + return self.compilation_unit.language.value == self.LANGUAGE return True @abc.abstractmethod diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index c43b2507f..ff26166a9 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -482,7 +482,6 @@ class ExpressionToSlithIR(ExpressionVisitor): def _post_literal(self, expression: Literal) -> None: expression_type = expression.type assert isinstance(expression_type, ElementaryType) - print(expression.value) cst = Constant(expression.value, expression_type, expression.subdenomination) set_val(expression, cst) diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt deleted file mode 100644 index 6f12cb530..000000000 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_chain_test__0.txt +++ /dev/null @@ -1,13 +0,0 @@ -digraph{ -0[label="Node Type: ENTRY_POINT 0 -"]; -0->1; -1[label="Node Type: NEW VARIABLE 1 - -EXPRESSION: -x = bytes32(chain.id) - -IRs: -TMP_0 = CONVERT chain.id to bytes32 -x(bytes32) := TMP_0(bytes32)"]; -} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_compute__0.txt similarity index 65% rename from tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt rename to tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_compute__0.txt index 0c7ae7d7a..b623aa188 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_limit_p_o__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_if_compute__0.txt @@ -5,34 +5,34 @@ digraph{ 1[label="Node Type: NEW VARIABLE 1 EXPRESSION: -p_new = p +a = p IRs: -p_new(uint256) := p(uint256)"]; +a(uint256) := p(uint256)"]; 1->2; 2[label="Node Type: NEW VARIABLE 2 EXPRESSION: -dt = 1 +b = 1 IRs: -dt(uint256) := 1(uint256)"]; +b(uint256) := 1(uint256)"]; 2->3; 3[label="Node Type: NEW VARIABLE 3 EXPRESSION: -ratio = 0 +c = 0 IRs: -ratio(uint256) := 0(uint256)"]; +c(uint256) := 0(uint256)"]; 3->4; 4[label="Node Type: IF 4 EXPRESSION: -dt > 0 +b > 0 IRs: -TMP_0(bool) = dt > 0 +TMP_0(bool) = b > 0 CONDITION TMP_0"]; 4->6[label="True"]; 4->5[label="False"]; @@ -41,26 +41,26 @@ CONDITION TMP_0"]; 6[label="Node Type: NEW VARIABLE 6 EXPRESSION: -old_p_o = 1 +old_a = 1 IRs: -old_p_o(uint256) := 1(uint256)"]; +old_a(uint256) := 1(uint256)"]; 6->7; 7[label="Node Type: NEW VARIABLE 7 EXPRESSION: -old_ratio = 2 +old_c = 2 IRs: -old_ratio(uint256) := 2(uint256)"]; +old_c(uint256) := 2(uint256)"]; 7->8; 8[label="Node Type: IF 8 EXPRESSION: -p > old_p_o +p > old_a IRs: -TMP_1(bool) = p > old_p_o +TMP_1(bool) = p > old_a CONDITION TMP_1"]; 8->10[label="True"]; 8->15[label="False"]; @@ -70,23 +70,23 @@ CONDITION TMP_1"]; 10[label="Node Type: EXPRESSION 10 EXPRESSION: -ratio = unsafe_div()(old_p_o * 10 ** 18,p) +c = unsafe_div()(old_a * 10 ** 18,p) IRs: TMP_2(uint256) = 10 (c)** 18 -TMP_3(uint256) = old_p_o (c)* TMP_2 +TMP_3(uint256) = old_a (c)* TMP_2 TMP_4(None) = SOLIDITY_CALL unsafe_div()(TMP_3,p) -ratio(uint256) := TMP_4(None)"]; +c(uint256) := TMP_4(None)"]; 10->11; 11[label="Node Type: IF 11 EXPRESSION: -ratio < 10 ** 36 / 1 +c < 10 ** 36 / 1 IRs: TMP_5(uint256) = 10 (c)** 36 TMP_6(uint256) = TMP_5 (c)/ 1 -TMP_7(bool) = ratio < TMP_6 +TMP_7(bool) = c < TMP_6 CONDITION TMP_7"]; 11->13[label="True"]; 11->12[label="False"]; @@ -96,44 +96,44 @@ CONDITION TMP_7"]; 13[label="Node Type: EXPRESSION 13 EXPRESSION: -p_new = unsafe_div()(old_p_o * 1,10 ** 18) +a = unsafe_div()(old_a * 1,10 ** 18) IRs: -TMP_8(uint256) = old_p_o (c)* 1 +TMP_8(uint256) = old_a (c)* 1 TMP_9(uint256) = 10 (c)** 18 TMP_10(None) = SOLIDITY_CALL unsafe_div()(TMP_8,TMP_9) -p_new(uint256) := TMP_10(None)"]; +a(uint256) := TMP_10(None)"]; 13->14; 14[label="Node Type: EXPRESSION 14 EXPRESSION: -ratio = 10 ** 36 / 1 +c = 10 ** 36 / 1 IRs: TMP_11(uint256) = 10 (c)** 36 TMP_12(uint256) = TMP_11 (c)/ 1 -ratio(uint256) := TMP_12(uint256)"]; +c(uint256) := TMP_12(uint256)"]; 14->12; 15[label="Node Type: EXPRESSION 15 EXPRESSION: -ratio = unsafe_div()(p * 10 ** 18,old_p_o) +c = unsafe_div()(p * 10 ** 18,old_a) IRs: TMP_13(uint256) = 10 (c)** 18 TMP_14(uint256) = p (c)* TMP_13 -TMP_15(None) = SOLIDITY_CALL unsafe_div()(TMP_14,old_p_o) -ratio(uint256) := TMP_15(None)"]; +TMP_15(None) = SOLIDITY_CALL unsafe_div()(TMP_14,old_a) +c(uint256) := TMP_15(None)"]; 15->16; 16[label="Node Type: IF 16 EXPRESSION: -ratio < 10 ** 36 / 1 +c < 10 ** 36 / 1 IRs: TMP_16(uint256) = 10 (c)** 36 TMP_17(uint256) = TMP_16 (c)/ 1 -TMP_18(bool) = ratio < TMP_17 +TMP_18(bool) = c < TMP_17 CONDITION TMP_18"]; 16->18[label="True"]; 16->17[label="False"]; @@ -143,30 +143,30 @@ CONDITION TMP_18"]; 18[label="Node Type: EXPRESSION 18 EXPRESSION: -p_new = unsafe_div()(old_p_o * 10 ** 18,1) +a = unsafe_div()(old_a * 10 ** 18,1) IRs: TMP_19(uint256) = 10 (c)** 18 -TMP_20(uint256) = old_p_o (c)* TMP_19 +TMP_20(uint256) = old_a (c)* TMP_19 TMP_21(None) = SOLIDITY_CALL unsafe_div()(TMP_20,1) -p_new(uint256) := TMP_21(None)"]; +a(uint256) := TMP_21(None)"]; 18->19; 19[label="Node Type: EXPRESSION 19 EXPRESSION: -ratio = 10 ** 36 / 1 +c = 10 ** 36 / 1 IRs: TMP_22(uint256) = 10 (c)** 36 TMP_23(uint256) = TMP_22 (c)/ 1 -ratio(uint256) := TMP_23(uint256)"]; +c(uint256) := TMP_23(uint256)"]; 19->17; 20[label="Node Type: EXPRESSION 20 EXPRESSION: -ratio = 1 +c = 1 IRs: -ratio(uint256) := 1(uint256)"]; +c(uint256) := 1(uint256)"]; 20->5; } diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt deleted file mode 100644 index b53263a8d..000000000 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_literal_slitherConstructorConstantVariables__0.txt +++ /dev/null @@ -1,9 +0,0 @@ -digraph{ -0[label="Node Type: OTHER_ENTRYPOINT 0 - -EXPRESSION: -MAX_BANDS = 10 - -IRs: -MAX_BANDS(uint256) := 10(uint256)"]; -} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt deleted file mode 100644 index 753f5a938..000000000 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tricky_slitherConstructorConstantVariables__0.txt +++ /dev/null @@ -1,9 +0,0 @@ -digraph{ -0[label="Node Type: OTHER_ENTRYPOINT 0 - -EXPRESSION: -MAX_TICKS_UINT = 50 - -IRs: -MAX_TICKS_UINT(uint256) := 50(uint256)"]; -} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt deleted file mode 100644 index 0d2540498..000000000 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_bar__0.txt +++ /dev/null @@ -1,57 +0,0 @@ -digraph{ -0[label="Node Type: ENTRY_POINT 0 -"]; -0->1; -1[label="Node Type: NEW VARIABLE 1 - -EXPRESSION: -a = 0 - -IRs: -a(int128) := 0(uint256)"]; -1->2; -2[label="Node Type: NEW VARIABLE 2 - -EXPRESSION: -b = 0 - -IRs: -b(int128) := 0(uint256)"]; -2->3; -3[label="Node Type: EXPRESSION 3 - -EXPRESSION: -(a,b) = self.foo() - -IRs: -TUPLE_0(int128,int128) = INTERNAL_CALL, tuple.foo()() -a(int128)= UNPACK TUPLE_0 index: 0 -b(int128)= UNPACK TUPLE_0 index: 1 "]; -3->4; -4[label="Node Type: NEW VARIABLE 4 - -EXPRESSION: -x = 0x0000000000000000000000000000000000000000 - -IRs: -x(address) := 0(address)"]; -4->5; -5[label="Node Type: NEW VARIABLE 5 - -EXPRESSION: -c = 0 - -IRs: -c(uint256) := 0(uint256)"]; -5->6; -6[label="Node Type: EXPRESSION 6 - -EXPRESSION: -(a,c) = Test(x).foo() - -IRs: -TMP_0 = CONVERT x to Test -TUPLE_1(int128,uint256) = HIGH_LEVEL_CALL, dest:TMP_0(Test), function:foo, arguments:[] -a(int128)= UNPACK TUPLE_1 index: 0 -c(uint256)= UNPACK TUPLE_1 index: 1 "]; -} diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt deleted file mode 100644 index 8d1c1166b..000000000 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_tuple_foo__0.txt +++ /dev/null @@ -1,12 +0,0 @@ -digraph{ -0[label="Node Type: ENTRY_POINT 0 -"]; -0->1; -1[label="Node Type: RETURN 1 - -EXPRESSION: -(2,3) - -IRs: -RETURN 2,3"]; -} diff --git a/tests/e2e/vyper_parsing/test_data/if.vy b/tests/e2e/vyper_parsing/test_data/if.vy index 23483ca45..e706b9c0e 100644 --- a/tests/e2e/vyper_parsing/test_data/if.vy +++ b/tests/e2e/vyper_parsing/test_data/if.vy @@ -1,25 +1,22 @@ @external @view -def limit_p_o(p: uint256): - p_new: uint256 = p - dt: uint256 = 1 - ratio: uint256 = 0 +def compute(p: uint256): + a: uint256 = p + b: uint256 = 1 + c: uint256 = 0 - if dt > 0: - old_p_o: uint256 = 1 - old_ratio: uint256 = 2 - # ratio = p_o_min / p_o_max - if p > old_p_o: - ratio = unsafe_div(old_p_o * 10**18, p) - if ratio < 10**36 / 1: - p_new = unsafe_div(old_p_o * 1, 10**18) - ratio = 10**36 / 1 + if b > 0: + old_a: uint256 = 1 + old_c: uint256 = 2 + if p > old_a: + c = unsafe_div(old_a * 10**18, p) + if c < 10**36 / 1: + a = unsafe_div(old_a * 1, 10**18) + c = 10**36 / 1 else: - ratio = unsafe_div(p * 10**18, old_p_o) - if ratio < 10**36 / 1: - p_new = unsafe_div(old_p_o * 10**18, 1) - ratio = 10**36 / 1 + c = unsafe_div(p * 10**18, old_a) + if c < 10**36 / 1: + a = unsafe_div(old_a * 10**18, 1) + c = 10**36 / 1 - # ratio is guaranteed to be less than 1e18 - # Also guaranteed to be limited, therefore can have all ops unsafe - ratio = 1 + c = 1 From 961db4563ffd4a0e30707b28355e869fa32f815a Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 13:50:50 -0500 Subject: [PATCH 225/338] address lints and improve typing --- .../visitors/slithir/expression_to_slithir.py | 5 +- slither/vyper_parsing/ast/ast.py | 46 ++++- .../vyper_parsing/declarations/contract.py | 3 +- slither/vyper_parsing/declarations/event.py | 2 +- .../vyper_parsing/declarations/function.py | 39 ++++- slither/vyper_parsing/declarations/struct.py | 2 +- .../expressions/expression_parsing.py | 161 ++++++++---------- .../expressions/find_variable.py | 4 +- slither/vyper_parsing/type_parsing.py | 13 +- 9 files changed, 162 insertions(+), 113 deletions(-) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index ff26166a9..1a2a85b2d 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -171,9 +171,8 @@ class ExpressionToSlithIR(ExpressionVisitor): def result(self) -> List[Operation]: return self._result - def _post_assignement_operation( - self, expression: AssignmentOperation - ) -> None: # pylint: disable=too-many-branches,too-many-statements + # pylint: disable=too-many-branches,too-many-statements + def _post_assignement_operation(self, expression: AssignmentOperation) -> None: left = get(expression.expression_left) right = get(expression.expression_right) operation: Operation diff --git a/slither/vyper_parsing/ast/ast.py b/slither/vyper_parsing/ast/ast.py index 228805c89..f05a167dc 100644 --- a/slither/vyper_parsing/ast/ast.py +++ b/slither/vyper_parsing/ast/ast.py @@ -1,6 +1,48 @@ from typing import Dict, Callable, List -from slither.vyper_parsing.ast.types import ASTNode -from slither.vyper_parsing.ast.types import * +from slither.vyper_parsing.ast.types import ( + ASTNode, + Module, + ImportFrom, + EventDef, + AnnAssign, + Name, + Call, + StructDef, + VariableDecl, + Subscript, + Index, + Hex, + Int, + Str, + Tuple, + FunctionDef, + Assign, + Raise, + Attribute, + Assert, + Keyword, + Arguments, + Arg, + UnaryOp, + BinOp, + Expr, + Log, + Return, + VyDict, + VyList, + NameConstant, + If, + Compare, + For, + Break, + Continue, + Pass, + InterfaceDef, + EnumDef, + Bytes, + AugAssign, + BoolOp, +) class ParsingError(Exception): diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index e1b8ffd67..6ca9c6557 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -32,7 +32,7 @@ if TYPE_CHECKING: from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit -class ContractVyper: +class ContractVyper: # pylint: disable=too-many-instance-attributes def __init__( self, slither_parser: "VyperCompilationUnit", contract: Contract, module: Module ) -> None: @@ -426,6 +426,7 @@ class ContractVyper: contract_parser = ContractVyper(self._slither_parser, contract, node) self._contract.file_scope.contracts[contract.name] = contract + # pylint: disable=protected-access self._slither_parser._underlying_contract_to_parser[contract] = contract_parser elif isinstance(node, AnnAssign): # implements: ERC20 diff --git a/slither/vyper_parsing/declarations/event.py b/slither/vyper_parsing/declarations/event.py index b73e46211..43d781439 100644 --- a/slither/vyper_parsing/declarations/event.py +++ b/slither/vyper_parsing/declarations/event.py @@ -11,7 +11,7 @@ from slither.vyper_parsing.ast.types import AnnAssign, Pass from slither.vyper_parsing.ast.types import EventDef -class EventVyper: +class EventVyper: # pylint: disable=too-few-public-methods """ Event class """ diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 17d77cfb9..5a898aaf2 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -1,4 +1,4 @@ -from typing import Dict, Union, List, TYPE_CHECKING, Tuple +from typing import Dict, Union, List, TYPE_CHECKING from slither.core.cfg.node import NodeType, link_nodes, Node from slither.core.cfg.scope import Scope @@ -13,7 +13,33 @@ from slither.core.variables.local_variable import LocalVariable from slither.vyper_parsing.cfg.node import NodeVyper from slither.solc_parsing.exceptions import ParsingError from slither.vyper_parsing.variables.local_variable import LocalVariableVyper -from slither.vyper_parsing.ast.types import * +from slither.vyper_parsing.ast.types import ( + Int, + Call, + Attribute, + Name, + Tuple as TupleVyper, + ASTNode, + AnnAssign, + FunctionDef, + Return, + Assert, + Compare, + Log, + Subscript, + If, + Pass, + Assign, + AugAssign, + Raise, + Expr, + For, + Index, + Arg, + Arguments, + Continue, + Break, +) if TYPE_CHECKING: from slither.core.compilation_unit import SlitherCompilationUnit @@ -24,7 +50,7 @@ def link_underlying_nodes(node1: NodeVyper, node2: NodeVyper): link_nodes(node1.underlying_node, node2.underlying_node) -class FunctionVyper: +class FunctionVyper: # pylint: disable=too-many-instance-attributes def __init__( self, function: Function, @@ -183,7 +209,7 @@ class FunctionVyper: contract = self._contract_parser.underlying_contract compilation_unit = self._contract_parser.underlying_contract.compilation_unit modifier = Modifier(compilation_unit) - modifier._name = name + modifier.name = name modifier.set_offset(decorator.src, compilation_unit) modifier.set_contract(contract) modifier.set_contract_declarer(contract) @@ -218,6 +244,7 @@ class FunctionVyper: ################################################################################### ################################################################################### + # pylint: disable=too-many-branches,too-many-statements,protected-access,too-many-locals def _parse_cfg(self, cfg: List[ASTNode]) -> None: entry_node = self._new_node(NodeType.ENTRYPOINT, "-1:-1:-1", self.underlying_function) @@ -517,7 +544,7 @@ class FunctionVyper: local_var = self._add_param(param) self._function.add_parameters(local_var.underlying_variable) - def _parse_returns(self, returns: Union[Name, Tuple, Subscript]): + def _parse_returns(self, returns: Union[Name, TupleVyper, Subscript]): self._function.returns_src().set_offset(returns.src, self._function.compilation_unit) # Only the type of the arg is given, not a name. We create an an `Arg` with an empty name @@ -527,7 +554,7 @@ class FunctionVyper: local_var = self._add_param(Arg(returns.src, returns.node_id, "", annotation=returns)) self._function.add_return(local_var.underlying_variable) else: - assert isinstance(returns, Tuple) + assert isinstance(returns, TupleVyper) for ret in returns.elements: local_var = self._add_param(Arg(ret.src, ret.node_id, "", annotation=ret)) self._function.add_return(local_var.underlying_variable) diff --git a/slither/vyper_parsing/declarations/struct.py b/slither/vyper_parsing/declarations/struct.py index 308dbcb2b..3a3ccf7b8 100644 --- a/slither/vyper_parsing/declarations/struct.py +++ b/slither/vyper_parsing/declarations/struct.py @@ -6,7 +6,7 @@ from slither.vyper_parsing.variables.structure_variable import StructureVariable from slither.vyper_parsing.ast.types import StructDef, AnnAssign -class StructVyper: +class StructVyper: # pylint: disable=too-few-public-methods def __init__( self, st: Structure, diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 50dd05cf2..6edc46f74 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -1,10 +1,10 @@ -from typing import Dict, TYPE_CHECKING +from typing import Optional, List, Union, TYPE_CHECKING from collections import deque from slither.core.declarations.solidity_variables import ( SOLIDITY_VARIABLES_COMPOSED, SolidityVariableComposed, ) -from slither.core.declarations import SolidityFunction, Function +from slither.core.declarations import SolidityFunction, FunctionContract from slither.core.variables.state_variable import StateVariable from slither.core.expressions import ( CallExpression, @@ -57,14 +57,25 @@ from slither.vyper_parsing.ast.types import ( AugAssign, VyList, Raise, + ASTNode, ) if TYPE_CHECKING: from slither.core.expressions.expression import Expression -def parse_expression(expression: Dict, caller_context) -> "Expression": # pylint - print("parse_expression", expression) +def vars_to_typestr(rets: Optional[List["Expression"]]) -> str: + if rets is None: + return "tuple()" + if len(rets) == 1: + return str(rets[0].type) + return f"tuple({','.join(str(ret.type) for ret in rets)})" + + +# pylint: disable=too-many-branches,too-many-statements,too-many-locals +def parse_expression( + expression: ASTNode, caller_context: Union[FunctionContract, Contract] +) -> "Expression": if isinstance(expression, Int): literal = Literal(str(expression.value), ElementaryType("uint256")) @@ -103,14 +114,14 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - elif called.value.name == "convert()": + if called.value.name == "convert()": arg = parse_expression(expression.args[0], caller_context) type_to = parse_type(expression.args[1], caller_context) parsed_expr = TypeConversion(arg, type_to) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - elif called.value.name == "min_value()": + if called.value.name == "min_value()": type_to = parse_type(expression.args[0], caller_context) member_type = str(type_to) # TODO return Literal @@ -126,7 +137,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - elif called.value.name == "max_value()": + if called.value.name == "max_value()": type_to = parse_type(expression.args[0], caller_context) member_type = str(type_to) # TODO return Literal @@ -142,7 +153,7 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr - elif called.value.name == "raw_call()": + if called.value.name == "raw_call()": args = [parse_expression(a, caller_context) for a in expression.args] # This is treated specially in order to force `extract_tmp_call` to treat this as a `HighLevelCall` which will be converted # to a `LowLevelCall` by `convert_to_low_level`. This is an artifact of the late conversion of Solidity... @@ -182,9 +193,10 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin rets = None # Since the AST lacks the type of the return values, we recover it. if isinstance(called, Identifier): - if isinstance(called.value, Function): + if isinstance(called.value, FunctionContract): rets = called.value.returns # Default arguments are not represented in the AST, so we recover them as well. + # pylint: disable=protected-access if called.value._default_args_as_expressions and len(arguments) < len( called.value.parameters ): @@ -209,28 +221,9 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin elif isinstance(called, MemberAccess) and called.type is not None: # (recover_type_2) Propagate the type collected to the `CallExpression` # see recover_type_1 - rets = [called.type] - - if rets is None: - rets = ["tuple()"] - - def get_type_str(x): - if isinstance(x, str): - return x - return str(x.type) - - # def vars_to_typestr(rets: List[Expression]) -> str: - # if len(rets) == 0: - # return "" - # if len(rets) == 1: - # return str(rets[0].type) - # return f"tuple({','.join(str(ret.type) for ret in rets)})" - - type_str = ( - get_type_str(rets[0]) - if len(rets) == 1 - else f"tuple({','.join(map(get_type_str, rets))})" - ) + rets = [called] + + type_str = vars_to_typestr(rets) parsed_expr = CallExpression(called, arguments, type_str) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) return parsed_expr @@ -266,41 +259,28 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to # its enclosing `CallExpression` - if isinstance(expr, Identifier) and isinstance(expr.value, StateVariable) and isinstance(expr.value.type, UserDefinedType) and isinstance(expr.value.type.type, Contract): + if ( + isinstance(expr, Identifier) + and isinstance(expr.value, StateVariable) + and isinstance(expr.value.type, UserDefinedType) + and isinstance(expr.value.type.type, Contract) + ): # If we access a member of an interface, needs to be interface instead of self namespace var = find_variable(member_name, expr.value.type.type) - if isinstance(var, Function): + if isinstance(var, FunctionContract): rets = var.returns + member_name_ret_type = vars_to_typestr(rets) - def get_type_str(x): - if isinstance(x, str): - return x - return str(x.type) - - type_str = ( - get_type_str(rets[0]) - if len(rets) == 1 - else f"tuple({','.join(map(get_type_str, rets))})" - ) - member_name_ret_type = type_str - - if isinstance(expr, TypeConversion) and isinstance(expr.type, UserDefinedType) and isinstance(expr.type.type, Contract): + if ( + isinstance(expr, TypeConversion) + and isinstance(expr.type, UserDefinedType) + and isinstance(expr.type.type, Contract) + ): # If we access a member of an interface, needs to be interface instead of self namespace var = find_variable(member_name, expr.type.type) - if isinstance(var, Function): + if isinstance(var, FunctionContract): rets = var.returns - - def get_type_str(x): - if isinstance(x, str): - return x - return str(x.type) - - type_str = ( - get_type_str(rets[0]) - if len(rets) == 1 - else f"tuple({','.join(map(get_type_str, rets))})" - ) - member_name_ret_type = type_str + member_name_ret_type = vars_to_typestr(rets) member_access = MemberAccess(member_name, member_name_ret_type, expr) @@ -359,7 +339,9 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin is_tuple = isinstance(rhs, TupleExpression) is_array = isinstance(rhs, Identifier) and isinstance(rhs.value.type, ArrayType) if is_array: - assert rhs.value.type.is_fixed_array + assert ( + rhs.value.type.is_fixed_array + ), "Dynamic arrays are not supported in comparison operators" if is_tuple or is_array: length = len(rhs.expressions) if is_tuple else rhs.value.type.length_value.value inner_op = ( @@ -391,37 +373,36 @@ def parse_expression(expression: Dict, caller_context) -> "Expression": # pylin return conditions.pop() - else: # enum type membership check https://docs.vyperlang.org/en/stable/types.html?h#id18 - is_member_op = ( - BinaryOperationType.get_type("==") - if expression.op == "NotIn" - else BinaryOperationType.get_type("!=") - ) - # If all bits are cleared, then the lhs is not a member of the enum - # This allows representing membership in multiple enum members - # For example, if enum Foo has members A (1), B (2), and C (4), then - # (x in [Foo.A, Foo.B]) is equivalent to (x & (Foo.A | Foo.B) != 0), - # where (Foo.A | Foo.B) evaluates to 3. - # Thus, when x is 3, (x & (Foo.A | Foo.B) != 0) is true. - - enum_bit_mask = BinaryOperation( - TypeConversion(lhs, ElementaryType("uint256")), - TypeConversion(rhs, ElementaryType("uint256")), - BinaryOperationType.get_type("&"), - ) - membership_check = BinaryOperation( - enum_bit_mask, Literal("0", ElementaryType("uint256")), is_member_op - ) - membership_check.set_offset(lhs.source_mapping, caller_context.compilation_unit) - return membership_check - - else: # a regular logical operator - rhs = parse_expression(expression.right, caller_context) - op = BinaryOperationType.get_type(expression.op) + # enum type membership check https://docs.vyperlang.org/en/stable/types.html?h#id18 + is_member_op = ( + BinaryOperationType.get_type("==") + if expression.op == "NotIn" + else BinaryOperationType.get_type("!=") + ) + # If all bits are cleared, then the lhs is not a member of the enum + # This allows representing membership in multiple enum members + # For example, if enum Foo has members A (1), B (2), and C (4), then + # (x in [Foo.A, Foo.B]) is equivalent to (x & (Foo.A | Foo.B) != 0), + # where (Foo.A | Foo.B) evaluates to 3. + # Thus, when x is 3, (x & (Foo.A | Foo.B) != 0) is true. + enum_bit_mask = BinaryOperation( + TypeConversion(lhs, ElementaryType("uint256")), + TypeConversion(rhs, ElementaryType("uint256")), + BinaryOperationType.get_type("&"), + ) + membership_check = BinaryOperation( + enum_bit_mask, Literal("0", ElementaryType("uint256")), is_member_op + ) + membership_check.set_offset(lhs.source_mapping, caller_context.compilation_unit) + return membership_check + + # a regular logical operator + rhs = parse_expression(expression.right, caller_context) + op = BinaryOperationType.get_type(expression.op) - parsed_expr = BinaryOperation(lhs, rhs, op) - parsed_expr.set_offset(expression.src, caller_context.compilation_unit) - return parsed_expr + parsed_expr = BinaryOperation(lhs, rhs, op) + parsed_expr.set_offset(expression.src, caller_context.compilation_unit) + return parsed_expr if isinstance(expression, BinOp): lhs = parse_expression(expression.left, caller_context) diff --git a/slither/vyper_parsing/expressions/find_variable.py b/slither/vyper_parsing/expressions/find_variable.py index cc6a48ae7..0509a29d7 100644 --- a/slither/vyper_parsing/expressions/find_variable.py +++ b/slither/vyper_parsing/expressions/find_variable.py @@ -98,10 +98,10 @@ def find_variable( :return: :rtype: """ - + # pylint: disable=import-outside-toplevel from slither.vyper_parsing.declarations.function import ( FunctionVyper, - ) # pylint: disable=import-outside-toplevel + ) if isinstance(caller_context, Contract): current_scope = caller_context.file_scope diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index e11a4a9f7..915611866 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -1,20 +1,19 @@ +from typing import Union from slither.core.solidity_types.elementary_type import ( ElementaryType, ElementaryTypeName, ) # TODO rename solidity type from slither.core.solidity_types.array_type import ArrayType from slither.core.solidity_types.mapping_type import MappingType - from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple -from typing import Union from slither.core.solidity_types.user_defined_type import UserDefinedType +from slither.core.declarations import FunctionContract, Contract -from slither.core.declarations.function_contract import FunctionContract - - +# pylint: disable=too-many-branches,too-many-return-statements,import-outside-toplevel,too-many-locals def parse_type( - annotation: Union[Name, Subscript, Call, Tuple], caller_context -): # pylint disable=too-many-branches,too-many-return-statements,import-outside-toplevel + annotation: Union[Name, Subscript, Call, Tuple], + caller_context: Union[FunctionContract, Contract], +): from slither.vyper_parsing.expressions.expression_parsing import parse_expression if isinstance(caller_context, FunctionContract): From 404914cdfa574ce51b88c0faa04b9d71d1b979ec Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 5 Sep 2023 14:22:41 -0500 Subject: [PATCH 226/338] link issues for TODO comments, lint --- .../vyper_parsing/declarations/function.py | 2 +- .../expressions/expression_parsing.py | 11 +++-- slither/vyper_parsing/type_parsing.py | 46 +++++++++---------- .../vyper_parsing/variables/local_variable.py | 9 ++-- tests/unit/core/test_function_declaration.py | 5 ++ 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 5a898aaf2..70e04c8e5 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -282,7 +282,7 @@ class FunctionVyper: # pylint: disable=too-many-instance-attributes curr_node = new_node elif isinstance(expr, Expr): - # TODO This is a workaround to handle Vyper putting payable/view in the function body... + # TODO This is a workaround to handle Vyper putting payable/view in the function body... https://github.com/vyperlang/vyper/issues/3578 if not isinstance(expr.value, Name): new_node = self._new_node(NodeType.EXPRESSION, expr.src, scope) new_node.add_unparsed_expression(expr.value) diff --git a/slither/vyper_parsing/expressions/expression_parsing.py b/slither/vyper_parsing/expressions/expression_parsing.py index 6edc46f74..d51467fab 100644 --- a/slither/vyper_parsing/expressions/expression_parsing.py +++ b/slither/vyper_parsing/expressions/expression_parsing.py @@ -83,7 +83,7 @@ def parse_expression( return literal if isinstance(expression, Hex): - # TODO this is an implicit conversion and could potentially be bytes20 or other? + # TODO this is an implicit conversion and could potentially be bytes20 or other? https://github.com/vyperlang/vyper/issues/3580 literal = Literal(str(expression.value), ElementaryType("address")) literal.set_offset(expression.src, caller_context.compilation_unit) return literal @@ -191,7 +191,7 @@ def parse_expression( arguments = [parse_expression(a, caller_context) for a in expression.args] rets = None - # Since the AST lacks the type of the return values, we recover it. + # Since the AST lacks the type of the return values, we recover it. https://github.com/vyperlang/vyper/issues/3581 if isinstance(called, Identifier): if isinstance(called.value, FunctionContract): rets = called.value.returns @@ -212,7 +212,7 @@ def parse_expression( elif isinstance(called.value, Contract): # Type conversions are not explicitly represented in the AST e.g. converting address to contract/ interface, - # so we infer that a type conversion is occurring if `called` is a `Contract` type. + # so we infer that a type conversion is occurring if `called` is a `Contract` type. https://github.com/vyperlang/vyper/issues/3580 type_to = parse_type(expression.func, caller_context) parsed_expr = TypeConversion(arguments[0], type_to) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) @@ -231,7 +231,7 @@ def parse_expression( if isinstance(expression, Attribute): member_name = expression.attr if isinstance(expression.value, Name): - # TODO this is ambiguous because it could be a state variable or a call to balance + # TODO this is ambiguous because it could be a state variable or a call to balance https://github.com/vyperlang/vyper/issues/3582 if expression.value.id == "self" and member_name != "balance": var = find_variable(member_name, caller_context, is_self=True) parsed_expr = SelfIdentifier(var) @@ -241,6 +241,7 @@ def parse_expression( expr = parse_expression(expression.value, caller_context) # TODO this is ambiguous because it could be a type conversion of an interface or a member access + # see https://github.com/vyperlang/vyper/issues/3580 and ttps://github.com/vyperlang/vyper/issues/3582 if expression.attr == "address": parsed_expr = TypeConversion(expr, ElementaryType("address")) parsed_expr.set_offset(expression.src, caller_context.compilation_unit) @@ -258,7 +259,7 @@ def parse_expression( member_name_ret_type = None # (recover_type_1) This may be a call to an interface and we don't have the return types, # so we see if there's a function identifier with `member_name` and propagate the type to - # its enclosing `CallExpression` + # its enclosing `CallExpression`. https://github.com/vyperlang/vyper/issues/3581 if ( isinstance(expr, Identifier) and isinstance(expr.value, StateVariable) diff --git a/slither/vyper_parsing/type_parsing.py b/slither/vyper_parsing/type_parsing.py index 915611866..34c76cc6e 100644 --- a/slither/vyper_parsing/type_parsing.py +++ b/slither/vyper_parsing/type_parsing.py @@ -5,9 +5,10 @@ from slither.core.solidity_types.elementary_type import ( ) # TODO rename solidity type from slither.core.solidity_types.array_type import ArrayType from slither.core.solidity_types.mapping_type import MappingType -from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple from slither.core.solidity_types.user_defined_type import UserDefinedType from slither.core.declarations import FunctionContract, Contract +from slither.vyper_parsing.ast.types import Name, Subscript, Call, Index, Tuple +from slither.solc_parsing.exceptions import ParsingError # pylint: disable=too-many-branches,too-many-return-statements,import-outside-toplevel,too-many-locals def parse_type( @@ -25,9 +26,24 @@ def parse_type( if isinstance(annotation, Name): name = annotation.id + lname = name.lower() # map `String` to string + if lname in ElementaryTypeName: + return ElementaryType(lname) + + if name in contract.structures_as_dict: + return UserDefinedType(contract.structures_as_dict[name]) + + if name in contract.enums_as_dict: + return UserDefinedType(contract.enums_as_dict[name]) + + if name in contract.file_scope.contracts: + return UserDefinedType(contract.file_scope.contracts[name]) + + if name in contract.file_scope.structures: + return UserDefinedType(contract.file_scope.structures[name]) elif isinstance(annotation, Subscript): assert isinstance(annotation.slice, Index) - # This is also a strange construct... + # This is also a strange construct... https://github.com/vyperlang/vyper/issues/3577 if isinstance(annotation.slice.value, Tuple): assert isinstance(annotation.value, Name) if annotation.value.id == "DynArray": @@ -44,17 +60,17 @@ def parse_type( type_ = parse_type(annotation.value, caller_context) elif isinstance(annotation.value, Name): - # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression, so we grab the value. - # Subscript(src='13:10:0', node_id=7, value=Name(src='13:6:0', node_id=8, id='String'), slice=Index(src='13:10:0', node_id=12, value=Int(src='20:2:0', node_id=10, value=64))) + # TODO it is weird that the ast_type is `Index` when it's a type annotation and not an expression, so we grab the value. https://github.com/vyperlang/vyper/issues/3577 type_ = parse_type(annotation.value, caller_context) if annotation.value.id == "String": + # This is an elementary type return type_ length = parse_expression(annotation.slice.value, caller_context) return ArrayType(type_, length) elif isinstance(annotation, Call): - # TODO event variable represented as Call + # TODO event variable represented as Call https://github.com/vyperlang/vyper/issues/3579 return parse_type(annotation.args[0], caller_context) elif isinstance(annotation, Tuple): @@ -80,22 +96,4 @@ def parse_type( return UserDefinedType(st) - else: - assert False - - lname = name.lower() # TODO map String to string - if lname in ElementaryTypeName: - return ElementaryType(lname) - - if name in contract.structures_as_dict: - return UserDefinedType(contract.structures_as_dict[name]) - - if name in contract.enums_as_dict: - return UserDefinedType(contract.enums_as_dict[name]) - - if name in contract.file_scope.contracts: - return UserDefinedType(contract.file_scope.contracts[name]) - - if name in contract.file_scope.structures: - return UserDefinedType(contract.file_scope.structures[name]) - assert False + raise ParsingError(f"Type name not found {name} context {caller_context}") diff --git a/slither/vyper_parsing/variables/local_variable.py b/slither/vyper_parsing/variables/local_variable.py index b50dea44b..1195743e1 100644 --- a/slither/vyper_parsing/variables/local_variable.py +++ b/slither/vyper_parsing/variables/local_variable.py @@ -6,7 +6,7 @@ from slither.vyper_parsing.type_parsing import parse_type class LocalVariableVyper: - def __init__(self, variable: LocalVariable, variable_data: Union[Arg, Name]) -> None: + def __init__(self, variable: LocalVariable, variable_data: Union[Arg, AnnAssign, Name]) -> None: self._variable: LocalVariable = variable if isinstance(variable_data, Arg): @@ -15,12 +15,9 @@ class LocalVariableVyper: elif isinstance(variable_data, AnnAssign): self._variable.name = variable_data.target.id self._elem_to_parse = variable_data.annotation - elif isinstance(variable_data, Name): - self._variable.name = variable_data.id - self._elem_to_parse = variable_data else: - # param Subscript - self._variable.name = "" + assert isinstance(variable_data, Name) + self._variable.name = variable_data.id self._elem_to_parse = variable_data assert isinstance(self._elem_to_parse, (Name, Subscript, Call, Tuple)) diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index c4844074e..cea207613 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -305,6 +305,7 @@ def test_public_variable(solc_binary_path) -> None: assert var.type == ElementaryType("bytes32") +# pylint: disable=too-many-statements def test_vyper_functions(slither_from_vyper_source) -> None: with slither_from_vyper_source( """ @@ -352,6 +353,7 @@ def __default__(): assert not f.view assert not f.pure assert not f.is_implemented + assert f.is_empty f = functions["__default__()"] assert f.function_type == FunctionType.FALLBACK @@ -360,6 +362,7 @@ def __default__(): assert not f.view assert not f.pure assert not f.is_implemented + assert f.is_empty f = functions["withdraw()"] assert f.function_type == FunctionType.NORMAL @@ -370,10 +373,12 @@ def __default__(): assert f.can_send_eth() assert f.can_reenter() assert f.is_implemented + assert not f.is_empty f = functions["withdraw_locked()"] assert not f.is_reentrant assert f.is_implemented + assert not f.is_empty var = contract.get_state_variable_from_name("balances") assert var From 1c4730dd1152d192cb350ef38c7bd70e6610bc32 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 7 Sep 2023 15:24:12 +0200 Subject: [PATCH 227/338] Improve import aliasing --- slither/core/declarations/__init__.py | 1 + .../visitors/slithir/expression_to_slithir.py | 67 ++++++++++++++++++ tests/e2e/solc_parsing/test_ast_parsing.py | 1 + .../solc_parsing/test_data/aliasing/l1.sol | 24 +++++++ .../solc_parsing/test_data/aliasing/l2.sol | 1 + .../solc_parsing/test_data/aliasing/l3.sol | 1 + .../solc_parsing/test_data/aliasing/main.sol | 20 ++++++ .../aliasing/main.sol-0.8.19-compact.zip | Bin 0 -> 5817 bytes .../aliasing/main.sol-0.8.19-compact.json | 9 +++ 9 files changed, 124 insertions(+) create mode 100644 tests/e2e/solc_parsing/test_data/aliasing/l1.sol create mode 100644 tests/e2e/solc_parsing/test_data/aliasing/l2.sol create mode 100644 tests/e2e/solc_parsing/test_data/aliasing/l3.sol create mode 100644 tests/e2e/solc_parsing/test_data/aliasing/main.sol create mode 100644 tests/e2e/solc_parsing/test_data/compile/aliasing/main.sol-0.8.19-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/aliasing/main.sol-0.8.19-compact.json diff --git a/slither/core/declarations/__init__.py b/slither/core/declarations/__init__.py index f34118751..f6e902e06 100644 --- a/slither/core/declarations/__init__.py +++ b/slither/core/declarations/__init__.py @@ -20,3 +20,4 @@ from .function_top_level import FunctionTopLevel from .custom_error_contract import CustomErrorContract from .custom_error_top_level import CustomErrorTopLevel from .custom_error import CustomError +from .solidity_import_placeholder import SolidityImportPlaceHolder diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 005ad81a4..35b79a1ce 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -2,6 +2,7 @@ import logging from typing import Union, List, TYPE_CHECKING, Any from slither.core import expressions +from slither.core.scope.scope import FileScope from slither.core.declarations import ( Function, SolidityVariable, @@ -11,6 +12,8 @@ from slither.core.declarations import ( EnumContract, EnumTopLevel, Enum, + SolidityImportPlaceHolder, + Import, ) from slither.core.expressions import ( AssignmentOperation, @@ -524,12 +527,76 @@ class ExpressionToSlithIR(ExpressionVisitor): set_val(expression, expr.custom_errors_as_dict[expression.member_name]) return + if isinstance(expr, (SolidityImportPlaceHolder, Import)): + scope = ( + expr.import_directive.scope + if isinstance(expr, SolidityImportPlaceHolder) + else expr.scope + ) + if self._check_elem_in_scope(expression.member_name, scope, expression): + return + val_ref = ReferenceVariable(self._node) member = Member(expr, Constant(expression.member_name), val_ref) member.set_expression(expression) self._result.append(member) set_val(expression, val_ref) + def _check_elem_in_scope(self, elem: str, scope: FileScope, expression: MemberAccess) -> bool: + if elem in scope.renaming: + self._check_elem_in_scope(scope.renaming[elem], scope, expression) + return True + + if elem in scope.contracts: + set_val(expression, scope.contracts[elem]) + return True + + if elem in scope.structures: + set_val(expression, scope.structures[elem]) + return True + + if elem in scope.variables: + set_val(expression, scope.variables[elem]) + return True + + if elem in scope.enums: + set_val(expression, scope.enums[elem]) + return True + + if elem in scope.user_defined_types: + set_val(expression, scope.user_defined_types[elem]) + return True + + for import_directive in scope.imports: + if elem == import_directive.alias: + set_val(expression, import_directive) + return True + + for custom_error in scope.custom_errors: + if custom_error.name == elem: + set_val(expression, custom_error) + return True + + if str(expression.type).startswith("function "): + # This is needed to handle functions overloading + signature_to_seaarch = ( + str(expression.type) + .replace("function ", elem) + .replace("pure ", "") + .replace("view ", "") + .replace("struct ", "") + .replace("enum ", "") + .replace(" memory", "") + .split(" returns", maxsplit=1)[0] + ) + + for function in scope.functions: + if signature_to_seaarch == function.full_name: + set_val(expression, function) + return True + + return False + def _post_new_array(self, expression: NewArray) -> None: val = TemporaryVariable(self._node) operation = TmpNewArray(expression.array_type, val) diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index 307e6736f..63baed549 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -459,6 +459,7 @@ ALL_TESTS = [ ["0.6.9", "0.7.6", "0.8.16"], ), Test("user_defined_operators-0.8.19.sol", ["0.8.19"]), + Test("aliasing/main.sol", ["0.8.19"]), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/aliasing/l1.sol b/tests/e2e/solc_parsing/test_data/aliasing/l1.sol new file mode 100644 index 000000000..86cb0bd5f --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/aliasing/l1.sol @@ -0,0 +1,24 @@ +import "./l2.sol" as L2; +import {MyErr as MyImportError} from "./l3.sol"; + +type fd is uint; +error MyError(); +uint constant qwe = 34; + +struct SS { + uint g; +} + +enum MyEnum { + A, + B +} + +function tpf(MyEnum p) returns(uint) {return 4;} +function tpf(fd p) pure returns(uint) {return 4;} +function tpf(uint e, SS memory g) view returns(uint) {return 4;} + +library MyC { + function callme() public {} + +} diff --git a/tests/e2e/solc_parsing/test_data/aliasing/l2.sol b/tests/e2e/solc_parsing/test_data/aliasing/l2.sol new file mode 100644 index 000000000..14d3b5fba --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/aliasing/l2.sol @@ -0,0 +1 @@ +function l() {} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/aliasing/l3.sol b/tests/e2e/solc_parsing/test_data/aliasing/l3.sol new file mode 100644 index 000000000..1c92842a9 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/aliasing/l3.sol @@ -0,0 +1 @@ +error MyErr(); \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/aliasing/main.sol b/tests/e2e/solc_parsing/test_data/aliasing/main.sol new file mode 100644 index 000000000..c725b96c5 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/aliasing/main.sol @@ -0,0 +1,20 @@ +import "./l1.sol" as R; + +contract Tp { + + function re(R.SS calldata param1, R.MyEnum param2) public { + R.MyEnum a = R.MyEnum.A; + R.SS memory b = R.SS(R.qwe); + R.MyC.callme(); + R.tpf(2, param1); + R.tpf(param2); + R.tpf(R.fd.wrap(4)); + R.L2.l(); + revert R.MyImportError(); + } + + function re2() public { + revert R.MyError(); + } + +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/compile/aliasing/main.sol-0.8.19-compact.zip b/tests/e2e/solc_parsing/test_data/compile/aliasing/main.sol-0.8.19-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..cbfa8d909ec68209a6a63170fc634e6e813d2f33 GIT binary patch literal 5817 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\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n}\n", + "re2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file From c95b953b2c706a78be5362761fc5586cdc138d50 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 7 Sep 2023 17:22:02 +0200 Subject: [PATCH 228/338] Prioritize checking canonical_name for type inference --- slither/solc_parsing/solidity_types/type_parsing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/solc_parsing/solidity_types/type_parsing.py b/slither/solc_parsing/solidity_types/type_parsing.py index e12290722..3d7639829 100644 --- a/slither/solc_parsing/solidity_types/type_parsing.py +++ b/slither/solc_parsing/solidity_types/type_parsing.py @@ -82,9 +82,9 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t # all_enums = [c.enums for c in contracts] # all_enums = [item for sublist in all_enums for item in sublist] # all_enums += contract.slither.enums_top_level - var_type = next((e for e in all_enums if e.name == enum_name), None) + var_type = next((e for e in all_enums if e.canonical_name == enum_name), None) if not var_type: - var_type = next((e for e in all_enums if e.canonical_name == enum_name), None) + var_type = next((e for e in all_enums if e.name == enum_name), None) if not var_type: # any contract can refer to another contract's structure name_struct = name @@ -94,9 +94,9 @@ def _find_from_type_name( # pylint: disable=too-many-locals,too-many-branches,t # all_structures = [c.structures for c in contracts] # all_structures = [item for sublist in all_structures for item in sublist] # all_structures += contract.slither.structures_top_level - var_type = next((st for st in all_structures if st.name == name_struct), None) + var_type = next((st for st in all_structures if st.canonical_name == name_struct), None) if not var_type: - var_type = next((st for st in all_structures if st.canonical_name == name_struct), None) + var_type = next((st for st in all_structures if st.name == name_struct), None) # case where struct xxx.xx[] where not well formed in the AST if not var_type: depth = 0 From ff52901e6d1240fcd6633e5cee59577226adde66 Mon Sep 17 00:00:00 2001 From: joodiewoodo <38355190+dokzai@users.noreply.github.com> Date: Thu, 7 Sep 2023 23:03:56 -0400 Subject: [PATCH 229/338] Allow underscore in variable naming convention for internal state variables (#2110) * fix: allow underscore in variable naming convention for internal state variables and update test_detector tests snapshot * change set visibility of _myPublic to public, update test snapshots --- .../naming_convention/naming_convention.py | 2 +- ...ention_0_4_25_naming_convention_sol__0.txt | 14 +++++++------- ...ention_0_5_16_naming_convention_sol__0.txt | 14 +++++++------- ...ention_0_6_11_naming_convention_sol__0.txt | 14 +++++++------- ...vention_0_7_6_naming_convention_sol__0.txt | 14 +++++++------- .../0.4.25/naming_convention.sol | 3 ++- .../0.4.25/naming_convention.sol-0.4.25.zip | Bin 3545 -> 3659 bytes ...arning_for_public_constants.sol-0.4.25.zip | Bin 1377 -> 1380 bytes .../0.5.16/naming_convention.sol | 3 ++- .../0.5.16/naming_convention.sol-0.5.16.zip | Bin 3563 -> 3671 bytes ...arning_for_public_constants.sol-0.5.16.zip | Bin 1382 -> 1387 bytes .../0.6.11/naming_convention.sol | 3 ++- .../0.6.11/naming_convention.sol-0.6.11.zip | Bin 3566 -> 3688 bytes ...arning_for_public_constants.sol-0.6.11.zip | Bin 1402 -> 1409 bytes .../0.7.6/naming_convention.sol | 3 ++- .../0.7.6/naming_convention.sol-0.7.6.zip | Bin 3481 -> 3605 bytes ...warning_for_public_constants.sol-0.7.6.zip | Bin 1357 -> 1367 bytes 17 files changed, 37 insertions(+), 33 deletions(-) diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 02deb719e..0633799e5 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -167,7 +167,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 results.append(res) else: - if var.visibility == "private": + if var.visibility in ["private", "internal"]: correct_naming = self.is_mixed_case_with_underscore(var.name) else: correct_naming = self.is_mixed_case(var.name) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt index ed4177ca1..e4a643678 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#59) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#60) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#56) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.4.25 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#67) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt index 35c11193f..96f6aab3c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#59) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#60) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#56) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.5.16 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#67) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt index f692e211b..f1986fb78 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#59) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#60) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#56) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#67) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt index af17cabe8..b471cbfa2 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_co Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#59) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#60) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#56) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/ Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#67) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol index 7181ca911..add7867e0 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol @@ -53,7 +53,8 @@ contract Test { contract T { uint private _myPrivateVar; - uint _myPublicVar; + uint internal _myInternalVar; + uint public _myPublicVar; function test(uint _unused, uint _used) public returns(uint){ diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip index c7aaae071dbf8633c6c3ccd451a16b70b9ddd938..fe35f0c006f2a1526c143d8def79ef54a25e15c3 100644 GIT binary patch delta 3541 zcmV;`4Jz{48_OIRP)h>@KL7#%4ghDFCs&x_8Zws+0078)kr+~cO_*8QcqqqPRb~nJ zWXL2H807psVK9!fD&p|6=0Ku$knG4&vYB3y^^P$vjeL2gg{xK7S*Ww=&2KqVd1^B5 zw`_`>>&EzD8*b())Mt(31r;v^pjrj-TBpUNY%cWUo9uJ#)=3m3%@AW^TQrWvcUZkuOLMs*Tw_uAix;faD?v<{$vOk{3KfzsPSRdp zYypUIniJylkiZV4!v`MKQc&J`UoMiVr{=K=D%+ndCNJvghWGV|#|obcTUNJC58V0b zv%=E>zBu83@E-7a2li!cE5F+>`_H*wgjT|4SZwTXG<#?XTK)7333sQXdBi+QMJP3= zZ;FjMUWy{4t|>17@PMsX4AwpLhS1WH0X|2!i`4CF?T!*;C4@>NC;DTY;6*qS&gMb$ zR-0xW+KQrukkEN?x1tp5nk@@WT`#Vf96I`wY%Ropk?GE7ajx2}v!v851?+ADw;w;o z$ktV1BiCGK$NS+|g=`tS~{o(6QC<)3*pL#{!Jk)!<=X zd3C}4$Xn~tu!gR2T4z8)HA9nSERtq{w%c>;EM4^?;N5M=$;R@tIvUe1-_}J~Q-p0W zE7kLVf`cxGi*ifcF~arTRJNy_`Q)hTg2}TR3Ih zE7%D_i`e&pZm362LIcnG@2+txAX`CbH$uhSwY*XRc^8vueh9#S$RFQHQXhpfI>lM#JY9?tj2fV3|0M=vt0{ z4h0UMcH5a^nUksWEbX%IrXJ}EiBM{*aB|rDKri+opex0ymdA)yjX+z>BX3jxZy(b| z_Up=zHkyQewGWDKNg>tIC@8`4zm%(q#rdtfdK-F0kH6+6-L)3q2L50ICb>p!>~uVN~DWcy?w)r6|IY1iHda9J~7KP@265?A^*tg2_(6GI3dJiVF1`q?vVECroS$_e+6zsaeloD%ex_;Lv>|t3|FIK;(?{0~zA)}BNO%VXB^aMk=;U!oR53LS z4v+ACUA^spLrNlNfN2dL3 zhgLU13*9G;sf}?NkJpKxo}%k|re)d2;!(gu3??(q{HOZ&$zE%_6n#N|V#ZNo*Bnf8 z>GnqK3o@4^R3YPh;M)at!-s>7qm-S?m?_|nk;v^#y8x!A;#`wB@f-*?*Lu~e(-&~< zZ`rv@X}5w@N$aOqS~S@0Drphr792P?nnmNSuNu^+Yod$3CPL1gLG0;_u0qF7o5hH+ zrWq~2t!(s94KK&Giia_O(QM1E|G$FYgcM^pl+!_zpe>mQYU>Ld?~Zwo_LmASDph42 z-TWk0r0sX)EV;zZY+7@%dKwUV@;CHIt2P+*l>>WXQ6_XA5+;ePHaY+dp3@LdIo9tC z7|$%Fn47jxu*&&N=ON&AQ8q8Ox5NOa4;`>zqgtgzUZOofWuuXQ;7qRzAPlb8v&2`n zMnjFS#zq@`(gs*D?Pn`0qXmIg-|M3lE^TaK` zVbKYS3E|{*P*l4XSfbbL);B|l;2T#C^jG@UEOg>D#1Kg8!O0+jQazt&>hgy@$8^rn zR7B(%FDtr!Of|4(*xLSYVa5FYl*0hfXSu|o4QdCigXEpp9hN125{&U!*;y#0)TR@)ryM>?N9=M<2Yc= zOGj>*&%qV8f+Gtxxp>%rHN6DtGWH!UI>T^VIyfSKu|n0nuKuFE7SpnGF}4jQzjAvn zMw!4Y%|^CTPo#Dx(qv8iB)77|I6h~`=0v83*>lfRyAN_;f^nrqE(O3r9?Tv$CxwRGIJE#?eqAFy3tN)!T!Q)yn< zQ%HcDHSuXW&lOhD9Dj5XzrTIGjljHBgg7Bk|7K(d^8Y1fh}uS^Co&QWAIA8vRinv6 z-9oGQt~w23;a*_rwuykTszU23`M;I7Sx}(jnmn==|0oC!+*2@o)nYS^(F8v)|GKe% z<5T-}qG$B|LnMo`Eu!;g%C~r4(Na}$oV(PSpkiWFm&%Q^jm3fSg`$B29s+mQ@8&lF zkV(HR@JUbxMbZ}@dDMLdwpiG;R4Qoq!I#@k%#F1ELgc}|8R@v+EgZJXb0v@C(QWo z=`edB?Ro8;QmeRfU+F@1nGGm(eEAS9FgYkNW)=n^KKub9qE?#~WhldmF@6&p0 za@=j;_v&pEzJxO#R6tl0(;G7zbB4Vti61sFDP5B&Rb*mk?dlcYMuPp=n%)|J$knPF zAB5^+>Za2O6|_7wk1-lmZhBX5q~U^OXYCu^9HB0+3T8+)B~^}JK)BjgK|yKfct8`d z@r&x+s{WLIzH_K*G6SV(y^;Cx51oY50}tEA87|O)GZ~Xalkl(tyAd{b0Ra@n2$*DY z9Yy)*gVR&4)5l^nV6UO!@J->6eKPF)TlIztC*rzdGM_pr^%>(wb-!q{|oY5+3+CcTr!&ywf*&)Kv@CBVaJq5f+4}DO_~)fyajSYu!(zWgQvzy#sGaWDO+SHm zQn%JQi^hbq^?o4tNaqm_X1Pj#u|+H;V6+K{Ze9tqdMCksJah;_h>ArX&t&(`U`h{j zclBS`v(h9gICw1HY3F2qdSPxk+7liqJ>s^$@h9);3bGj7=4gM>iC++$hx5_-((Y4` z%;Upj70E%RIRbv{!Q_8`Paka*yPJ1r&+N=ZbE_8w_oa7)vC@eNg|+`nyX}N3a0;doXL} zr9Y6MRj2i(DR>aboc$uJQOI5+1Z^@KL7#%4gflhcUE^qDA6Si001O|}t(Qr6=UkA>bk%pZW|Xyk zrQehl-7UuMkhBqR$jJKsgicE^Du{2gnf-lK0mJLEE$(v)!9&G>yoJj^uc!Rrdgecw zf|5&2qk}pYMf`Dp+y`AgZtk4(g%W|$XF#1!Hda8{d-wt!I02Fr#%AC(&jN?jV^P(P z)n8pS=ezP|QTUBvP6dBESfIIKZA3H)`~rAI%H` zzEeRSm)PEZ?IM96-*&RXUXc(fr|X0X5YLlxVD;^Ql&6hzsS!xI}m-MmoN$ZkZMW?E*YnIQ@z+|0 zp<1^A9mq@`P+KK}|JF7Wv@MTTl_uT|Wq68-Cqb8s=W3*Qjq=CS zgUje`whmOGEZnE)yAASDwXXSnr-ANMBXg#9WT0g?*0CEt&5v?}uFdf~It_?vD%UMD zK_Wr8Er8#6MSR*$B~vLA$5GJrHeEevH+_%>-s1I2N=vc0_6;a=RVtWwao3_Clr&%EfptcyT7;*yz)%I*D81G_k zp98}OE(?{T;Sk|noM{T#(gh0tcW|I?|Ly*|5tPHnu-4$Q3KO z0DcdQ-mjGF41I=oj{Nes{XbbWNFVSjR%+9K#As(}N-q^9cpG0LV9btP&3YZ@!!juw z<$WU3Z^?7_2jV6;Q-|;4s=pbyT~LXVKk4gL%Rc3LReCkGzJ*mBJ<2u)Nx*YcgbVf)CHO5KM_uU#MKDe4=({Jbf1|x(Gkkfn|z;b>am1+!u-a2 zQDIe`iv_r_Ud|+d<#Lo?*_xauL#gGnk{gOGbfLpG@>CusIj6%udY(Nvbs-D$<+->d zke}yKb$ZK8Y#%e8sP7{12OI{G3_N5Ozc{VFzVAWy&G=s7-W`0m_izgl>OhEpdxpqc zhJA*3xyLgXbNL2S6gjJ0@V*E9{evnSyPU^t7t-zZS@hdqgPX|2aPBm4&?bxW)5{qw zrA#D^9^x^DrB4nv12Jy9^oU6topTK&$m{2)&v-P%4M(HL zWW|oT!dy+qefqad2xv!pAR)zl#XzUb!AQ4&)J3*ZRB)r&=!y|n<=6wHcM$o@W6+o| zc(WK7!e2LAbB*>^09g5?Vw)ASHBhF=#J(n>j9P+?=U}8%=E6|jQwB4 zi>stqVaB7Bx(q_p?z%94!Z->0QEFvs`Qiy%Kq7eN#P*)ih2=v1jIq0^_v|!nX^KW4 z&Lvb2u)TM+-Js_urexa7Q}y3qzQhLN)j&-2c28D$rkZQ=JGq&2>|v(}AFdXNQLBS$mY6_AJ}2I>6y{h6?pXBK!^3l!W<7F$h!{)7E#N{b62lTExi zOm^gbbePN`8*&;Wo}<^4I_1;5s*UGX?o5 zwvo;1FFFNav;pVFUrtMW$NMSnJ)xkA7Ln!6?<;#NUlA7z%=HL`-C<&BY=|Y=dY-bL z@4k+^+^-nx6X4I{pEFEDx69nQ_V^`E^d#B)Vkt&<*AU=;f{r)F1Ux(V1{<(f06fuD zlkIsT@>})>(A$E1{;?sp2$5x?1+D~uh!G?C-rDqQMXVTxXqF)}mfAuN33)WW(Zh62*v~BuNaLH)T-Me-)Hb{?8Om zSmHK+-NkrKmfJTCy9N>5y&9pPs9>NhSR=!lJsF8+-|A?|bi@E`h@cg(zj~h}gyPi+ zBYhCJ+0!0kAGWqwCv0V$?1WCQ%LtX~0a#g?u$c)KwU|i(|wU>Km9p6%9_OAC;t9EWaIKgIc zWLC=Pcz=3{w_nhLHvkb+PuOp`(T{l!D6&2Z*lp9fvJV9j-%#{dRGncGN*uuEN+wr- zX3zJ=V#2Q6Xik^E(`qQn^M2z^9Q`9y>4* zbi7ddHk6q^7d8H5iFXm+kHb2+jwC_$ zD!TxSXe$-!gqy&*xL5VzfjkhcnTs#^%>?0X01a(~@k+@z^kqcha!92`F&A-v!nd=N zBAmiR*40lqJJ*f=N5b}PG9*q{E5M{LoTnO6XXdR2bZ9+iz7pW>sK7x~l}0!emE>Q@ z{pdc!9u}YKFpzBgs6T7ChYkJI8>yze=uhRKaJ7IMJ4iFBbHsF2#1puQ+|On|EbtUD z&>dOJ!^;kCOl0y&<_LstclZrAWkFAr@<%uti%_erOKQ@;J0k!-M5kE0`RG<=# z3vM%wZl7?^@QhB{E0i*+wj=*#iK8FYOV5TbHqYVIFM~j?+4mDQR((F(OrbZaGpgNB zeqx?V01I?zLI*vwNYHmsNKSmODBNGfy}yacE@RB(kJgBp(8jF=4LnbO6r)mFB$f0G zI~QztEWP{f?`3$eNKOx5E2yb`BW@Qq4>Az-XreEA>6dI3YqFXazXLxrwf-sk#7IiE z6*?b~3obrS(^qysVhMXy7*9ydn>VpVBsa!A44%c;N-Y@Ge$-J09@fi}D*o_v<*S_7 z&)-+OTg3TD<+UOmZkalNn0FNe>AhyVq_{*Cr^m3Ne+wEcLJ#jbsqYi67tTMo6Tn)( zL~K(7VLrM-{07h^R&QHGq%RE}3pca9e8pSuaEd;O30+jkhKTq>btrG)^_miy8pL+u zMW3BbB3)#Pg}wxpU8YctEuot#*HjYvn&tFFRPQC|-S~dps>m@mnqOP%O@uh!66CHI zrp4xT$*h8o0IzHRv=jswP)h*@KL7#%4ghJHCs+6BU8$4=008C>001|W5d}JtRU>~*m|5C* zD92k>W(oLY$RrgQ3gjxjEce0ipYt5wxmsI%$I za$k9XT!?udx6&J$w&H&G7+LYOEtlk#@|V!at;z|l3~s|pTZ`KN_u^zBL^=@L^V9t_nvA-NYQM3b-E(u zR}mV6ssVNB*1s|CW8d!&pl?FI9 zpOe%$3VOMBURdr>3hG0IUB{EW(YkHzrxK<{-H_B-5doP%%FIk8bYy>jj5|*+(1rH2 z9{6geynditQA z7OGeZmS+q76XEw9nLj2#z-N1*pe)0oa!xcs$CTaRtW3uPE|Y{Cyl%v8{ik22T}52b*_EP5ALs51igDmC zcEhk|P$f#nranIDCmnCa{erUiEh=ssd$hf(#SE0Ah-TMJV>{=d?b6_!z_LMms`k#zhGy zA|V(G%=?UNAR&J!ANQYX?#(q-atO>>BQ-X4+B*~lfNh+~W*@R8m(roY_`KqUOv5S@ z?dya1YjmF5ObrQw^Z_YeK|VfGX5HN94WL&s3O?|6oTZcf}G&Hic2hN6gvw(k-=hL&i8?$REmAD*K>3grj z3XU6XC~t-zO+aBI)E*y-zYN9`O!{G4bkc{rUmaMF+zW!FeKoQVU?KUInb-Zh@lV+= zU%S6-Y`aBi{`rFPN!;gQk|3tRUVnTTI?h0Fexh2pob+)2pqw*FKd7915lalBV_uES zqMJ6sUPXUC$B3+u+s4M`{nXt#`_^IYbf;~@UNw20E7o1PH>0MBPUH3}+K||?O_KeG zBM6QWxPGSe_$y~{+&vR2043{ZuS<_+Q7Oo`{ESFdt%?H{6KoSQ(jX(JsVBY#8D8`5O5^lrMk%NxhrBwR*a3!0_fZX_oxUuzv0q zvc5bix`!X^X0P2{;v1U6Bgwm(DGtNu(A=WJJJ?wJE6?e(5%-N&Nlf=HCKF&CNr&33 z(=w)T5H^KU(Vba84=w#!Ay;Kj;++_6Rg=b@X5V(C~)9P)h*< kKL8Xz00ICG0BM;gSNG{%sgwi&0Ok*p1zQH`1ONa40F-`9YybcN delta 1213 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 delta 3444 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol index 7181ca911..add7867e0 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol @@ -53,7 +53,8 @@ contract Test { contract T { uint private _myPrivateVar; - uint _myPublicVar; + uint internal _myInternalVar; + uint public _myPublicVar; function test(uint _unused, uint _used) public returns(uint){ diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip index 3e6277ac1b0975ae85638b853cbde20646ccd7d2..b91697087411d7fed7effcb98875fdbf53f7a74f 100644 GIT binary patch delta 3577 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 ZR_r<*r#cM)0BC)a6%I`Xfeiov0078)u@wLS diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip index 67f8eff7ee737a57bf2ee1036db7d482c4926445..ed813d07b9be8e890dcdba4f865b432c1a77860b 100644 GIT binary patch delta 1245 zcmV<31S0$T3V{n4P)h>@KL7#%4ghJHCs+1C%$%_V006iTkr-fqO_*8QcqqqPRb~nJ zWXL2H807psVK9!fD&p|6=0Ku$knG4&vYB3y^^P$vjeL2gg{xK7S=SBtKOl888a$}y z?7meBGBj`~m&-#p=E9&=Y#IZ!d=kIw6mvH2#t-Bf3L+x|hA9LYtG{(*ZO9he`Pt%@ z99+AjzSX&+R+e}~Xj(A3cl383y=mPAtt?kF!S3%I z%x>Iof-%-1gqi30R7jx=7s^%4s@M{t*PZ_xP0M7F4PG z$!m5QoXiRjj)H&uA{a$6bX|c_&6y`Ox#Tc{!Qd|)H#t~;eF>ONb4~ju`Zz&?pRDj8i|yex+5G`u4?t)Lpd~j9^S}rh9Cp#k;jGJ=b_f z_)qqQ?E!RuMDQ$$Wj=608lsSFpFu*}Cmk+?qv~{lu>s>ST}?DCvf{ns3R&${S;Opk zaI50}CpU47&(DSJMXyygN@c`0&}jO~HN|7%tOPX5Xj{=caw1qO(jRGxlugKS|a+h^9SH*e8%p80gO6 z{|tYB&Ad&-m=TpI)$G!%ERM4mZi?038GgP_Z>ArmSEw>nF!?nMFwvgCx{)F;i^sd7 zFrWp&_P4Uf={&* z-vteL16V!4rhf?{1wB9TN4kswUJ-yW^7}FJK>~p3MfhVdB-H{+>TCKGInZ1H2_Ijx|D*!IiJA6vAfSJ575h_&=kFY zxYUpF`V6GD=sf$=Heix76~07<21Gc?gCyE+jRcCjsG%ypjKe12u_@*1-XT|K+$SUc zjGXF60_xFe3BoBJxQ|7m25TY03U&{B0>KZ*0oJ-_RZ6HtZZW_h%&td>yi^9d&;aFP zvHb@yHuxR!`CtkHMawIYCKBEjZJZv`=bWm@3yXr+0M0 zY007Z2F}?WoA10_DMIJ`gPkZ)O928u06zc%01g0YnI~8FLCl=71ONcI50e=MTLuON H00000LXc6v delta 1245 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 ZDF6Tf000000001!Qw=}{s0{!B008*kzpnrQ delta 3371 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 Bn=b$W diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip b/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip index 7b304b5c0c51361e8d7eb38abb0c614fcc9b6015..9f2c1a1a7d5a108a3277c3cdde3a8e3958a51c5d 100644 GIT binary patch delta 1210 zcmV;r1V#JJ3fBr7P)h>@KL7#%4ghJHCs#WZb_|CE002S{001|W{RBFZRU>~*m|5C* zD92k>W(oLY$RrgQ3gjxjEce0ipYt5wxm?mMg1 z!?aES#YRK*y$&n>uC}UR(=!r7N~MGhMaQF&CtYP=swZ=xV(;-?C)ok`oa6^%<{q}9 zP1E2tL&?33pTFiG9aPi!NlJeN;~-U1_3Xxy;Q=5dfq7MNZmxntGvFysyGS4jq8GQbT$C;ac%IIn^W51f+T>z{X}0 zMbwD*2^_!yJ?!-W2&iy3y#Zox(S+HZ!fAM|BJdCoaom6xSFsWEw?BW$W+Z4$y4dDV zujTrnr}Rf7tWuhG9c$O{ccThSHO$`0Ke(L&dp7=<)MEFJBTPE4BLW!Tw4W; z!)qdAj-o|9rOVTcO3~(j`lx+q0PRdocTr#Hy@)QU+7$bA`o%Awa5(FnpNsrrFuhyt$CWCv zVv+M$dg{x)yBU8zG85pE@w48F-}y;?Yt_7M*LCv}T0YHqh%RHqOHp-CV7AVG642)X zqW!`dtQHIkx4o+Loj8=RzTal$o1*Uen{#i9YmE#eA7I=qOXpRkO|NwmM9xQ(^L5o{Ml?U)J4?+&K&42j z1!J)8I_=DF6S50Xlk6O928u06zc%01g0YnI~5} Y6m|y;hXeosLJyPd1X~8&1ONa40C4q9J^%m! delta 1195 zcmV;c1XTOi3e5@_P)h>@KL7#%4gfoicUC(~IvITg002D^kr-fqJ|EX}y%sU?M-PRi zm0nlZdjJq|?-l5q5W}VAK!X$~yhYNz{x3$S;g((ndY>|}t(Qr6=UkA>bk%pZW|Xyk zrQe*weOeB`)1lL#N+Lu>=!z=sQlS87o3+&huXYgLmwM+m3uP)To~Hn zL@5p8M8E0G-izgbkV^<^EJ&Bdy>q@3k5lY(P;?^K+u39yKr$~9q%p%E<7|9U9=e%1 znE=A7qeF=B!WF2b_=b%V6mKS701A(sQ|0>pC2ohLaAEO@SC%p3GA}1*?YF}wCV@>i zVx$qli}G^$P?gpI2BC ztFxNQgyU1chQb@n>%uM@I2veB^Qdl7bgpFO=57sw3Hg%DO;I!J25Aypkzd_5f9qTg zljpR6@j(amrZ1S^O4&Vk)FF|l?@D_xt>Bf*ctae^08V?8YRSo<)vK!X6MVZ4v+!hE ze|L7=ZR5ays2dYNOXbH7{5ui~ID-U|Fl+L68*f-s(}((dFK#DLlO`C}!AuP(haP5CRbj5S>X+9d+&VH`LpnKEsG7b7jQ5$^P%c<)gl52 zve}2r{en?{Vi5Wd_a9a2q+?&2E)a_gixd>OV?%R5938z!K0&agXiaUM*T^|GKp9h0 zq6fr(DL{O;>|$fDOj4JcV*(UH$2Z(p$~^-4)D?bY!IPruOR8{x>9d$YJnIFIYsd1M296&xdvxpTCmHnv z-%#A?dPY5=0nj}mcXv@}W z#yKuZrqNkkcK`4YWgOjj8!hpVNtt!Jhd8G(5(Y)zaJOZvhqhM-h5P3wwv|`uq-cD9 zaY)D83{b{@g+&hl#o7E)tyzkYA{*YBBa*olsTr|PFje)qwL#0da5gSZZ%8fXWm)FAe=yt;5 z`yF~RpTc#Qs@qD=!=xYaE3Pp!xf$tyiL^fF9Qaw166x4#tB=Nl#~KCejk)0 Date: Fri, 8 Sep 2023 05:16:54 +0200 Subject: [PATCH 230/338] Make the results deterministic (#2114) --- slither/detectors/statements/divide_before_multiply.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/slither/detectors/statements/divide_before_multiply.py b/slither/detectors/statements/divide_before_multiply.py index 6f199db41..334da592c 100644 --- a/slither/detectors/statements/divide_before_multiply.py +++ b/slither/detectors/statements/divide_before_multiply.py @@ -2,7 +2,7 @@ Module detecting possible loss of precision due to divide before multiple """ from collections import defaultdict -from typing import DefaultDict, List, Set, Tuple +from typing import DefaultDict, List, Tuple from slither.core.cfg.node import Node from slither.core.declarations.contract import Contract @@ -63,7 +63,7 @@ def is_assert(node: Node) -> bool: # pylint: disable=too-many-branches def _explore( - to_explore: Set[Node], f_results: List[List[Node]], divisions: DefaultDict[LVALUE, List[Node]] + to_explore: List[Node], f_results: List[List[Node]], divisions: DefaultDict[LVALUE, List[Node]] ) -> None: explored = set() while to_explore: # pylint: disable=too-many-nested-blocks @@ -114,7 +114,7 @@ def _explore( f_results.append(node_results) for son in node.sons: - to_explore.add(son) + to_explore.append(son) def detect_divide_before_multiply( @@ -145,7 +145,7 @@ def detect_divide_before_multiply( # track all the division results (and the assignment of the division results) divisions: DefaultDict[LVALUE, List[Node]] = defaultdict(list) - _explore({function.entry_point}, f_results, divisions) + _explore([function.entry_point], f_results, divisions) for f_result in f_results: results.append((function, f_result)) From 9da51fff3b5b16c04f44370fddcfe1aba48edd37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <2642849+elopez@users.noreply.github.com> Date: Fri, 8 Sep 2023 00:32:32 -0300 Subject: [PATCH 231/338] detectors: cache_array_length: include source mapping in finding (#2076) * detectors: cache_array_length: include source mapping in finding The detector was manually string-interpolating the code and line information, which left the finding without source mapping metadata and broke filtering. Include the node directly on the finding info so that the metadata is preserved. --------- Co-authored-by: alpharush <0xalpharush@protonmail.com> --- .../operations/cache_array_length.py | 5 ++--- ...yLength_0_8_17_CacheArrayLength_sol__0.txt | 20 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py index e4d8cf2c6..59289ed0f 100644 --- a/slither/detectors/operations/cache_array_length.py +++ b/slither/detectors/operations/cache_array_length.py @@ -216,9 +216,8 @@ contract C for usage in non_optimal_array_len_usages: info = [ "Loop condition ", - f"`{usage.source_mapping.content}` ", - f"({usage.source_mapping}) ", - "should use cached array length instead of referencing `length` member " + usage, + " should use cached array length instead of referencing `length` member " "of the storage array.\n ", ] res = self.generate_result(info) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt index 456c702a5..c2a5023a6 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt @@ -1,20 +1,20 @@ -Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#109) should use cached array length instead of referencing `length` member of the storage array. +Loop condition k_scope_17 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#133) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#161) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i_scope_23 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#172) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#172) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#37) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#126) should use cached array length instead of referencing `length` member of the storage array. +Loop condition j_scope_11 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#109) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#133) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i_scope_4 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#68) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#68) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i_scope_22 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#167) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#99) should use cached array length instead of referencing `length` member of the storage array. +Loop condition k_scope_9 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#99) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#167) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i_scope_6 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#80) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#37) should use cached array length instead of referencing `length` member of the storage array. +Loop condition j_scope_15 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#126) should use cached array length instead of referencing `length` member of the storage array. -Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#80) should use cached array length instead of referencing `length` member of the storage array. +Loop condition i_scope_21 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#161) should use cached array length instead of referencing `length` member of the storage array. From 53c97f9f481a2e9877b177b5186c8ffdb62e3305 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Thu, 7 Sep 2023 23:32:27 -0500 Subject: [PATCH 232/338] fix: preserve None tuple components in the left and right liftings of ternary expressions (#2120) * preserve None tuple components in the left and right liftings of ternary expressions * added a test for ternary lifting over tuples --------- Co-authored-by: Kevin Clancy --- slither/utils/expression_manipulations.py | 5 +- .../slithir/test_data/ternary_expressions.sol | 30 ++++---- .../unit/slithir/test_ternary_expressions.py | 77 ++++++++++++------- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/slither/utils/expression_manipulations.py b/slither/utils/expression_manipulations.py index 75d97042c..32b88e9b3 100644 --- a/slither/utils/expression_manipulations.py +++ b/slither/utils/expression_manipulations.py @@ -147,7 +147,7 @@ class SplitTernaryExpression: for next_expr in expression.expressions: # TODO: can we get rid of `NoneType` expressions in `TupleExpression`? # montyly: this might happen with unnamed tuple (ex: (,,,) = f()), but it needs to be checked - if next_expr: + if next_expr is not None: if self.conditional_not_ahead( next_expr, true_expression, false_expression, f_expressions @@ -158,6 +158,9 @@ class SplitTernaryExpression: true_expression.expressions[-1], false_expression.expressions[-1], ) + else: + true_expression.expressions.append(None) + false_expression.expressions.append(None) def convert_index_access( self, next_expr: IndexAccess, true_expression: Expression, false_expression: Expression diff --git a/tests/unit/slithir/test_data/ternary_expressions.sol b/tests/unit/slithir/test_data/ternary_expressions.sol index ebfb96e80..1ccd51d34 100644 --- a/tests/unit/slithir/test_data/ternary_expressions.sol +++ b/tests/unit/slithir/test_data/ternary_expressions.sol @@ -1,6 +1,6 @@ interface Test { function test() external payable returns (uint); - function testTuple() external payable returns (uint, uint); + function testTuple(uint) external payable returns (uint, uint); } contract C { // TODO @@ -36,21 +36,23 @@ contract C { } // Unused tuple variable - function g(address one) public { - (, uint x) = Test(one).testTuple(); - } - uint[] myIntegers; - function _h(uint c) internal returns(uint) { - return c; - } - function h(bool cond, uint a, uint b) public { - uint d = _h( - myIntegers[cond ? a : b] - ); + function g(address one, bool cond, uint a, uint b) public { + (, uint x) = Test(one).testTuple(myIntegers[cond ? a : b]); } - - function i(bool cond) public { + + function h(bool cond) public { bytes memory a = new bytes(cond ? 1 : 2); } } + +contract D { + function values(uint n) internal returns (uint, uint) { + return (0, 1); + } + + function a(uint n) external { + uint a; + (a,) = values(n > 0 ? 1 : 0); + } +} diff --git a/tests/unit/slithir/test_ternary_expressions.py b/tests/unit/slithir/test_ternary_expressions.py index 712c9582b..bf8556f85 100644 --- a/tests/unit/slithir/test_ternary_expressions.py +++ b/tests/unit/slithir/test_ternary_expressions.py @@ -16,30 +16,53 @@ def test_ternary_conversions(solc_binary_path) -> None: """This tests that true and false sons define the same number of variables that the father node declares""" solc_path = solc_binary_path("0.8.0") slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path) - for contract in slither.contracts: - if not contract.is_signature_only: - for function in contract.functions: - vars_declared = 0 - vars_assigned = 0 - for node in function.nodes: - if node.type in [NodeType.IF, NodeType.IFLOOP]: - - # Iterate over true and false son - for inner_node in node.sons: - # Count all variables declared - expression = inner_node.expression - if isinstance( - expression, (AssignmentOperation, NewElementaryType, CallExpression) - ): - var_expr = expression.expression_left - # Only tuples declare more than one var - if isinstance(var_expr, TupleExpression): - vars_declared += len(var_expr.expressions) - else: - vars_declared += 1 - - for ir in inner_node.irs: - # Count all variables defined - if isinstance(ir, (Assignment, Unpack)): - vars_assigned += 1 - assert vars_declared == vars_assigned and vars_assigned != 0 + contract = next(c for c in slither.contracts if c.name == "C") + for function in contract.functions: + vars_declared = 0 + vars_assigned = 0 + for node in function.nodes: + if node.type in [NodeType.IF, NodeType.IFLOOP]: + + # Iterate over true and false son + for inner_node in node.sons: + # Count all variables declared + expression = inner_node.expression + if isinstance( + expression, (AssignmentOperation, NewElementaryType, CallExpression) + ): + var_expr = expression.expression_left + # Only tuples declare more than one var + if isinstance(var_expr, TupleExpression): + vars_declared += len(var_expr.expressions) + else: + vars_declared += 1 + + for ir in inner_node.irs: + # Count all variables defined + if isinstance(ir, (Assignment, Unpack)): + vars_assigned += 1 + assert vars_declared == vars_assigned and vars_assigned != 0 + + +def test_ternary_tuple(solc_binary_path) -> None: + """ + Test that in the ternary liftings of an assignment of the form `(z, ) = ...`, + we obtain `z` from an unpack operation in both lifitings + """ + solc_path = solc_binary_path("0.8.0") + slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path) + contract = next(c for c in slither.contracts if c.name == "D") + fn = next(f for f in contract.functions if f.name == "a") + + if_nodes = [n for n in fn.nodes if n.type == NodeType.IF] + assert len(if_nodes) == 1 + + if_node = if_nodes[0] + assert isinstance(if_node.son_true.expression, AssignmentOperation) + assert ( + len([ir for ir in if_node.son_true.all_slithir_operations() if isinstance(ir, Unpack)]) == 1 + ) + assert ( + len([ir for ir in if_node.son_false.all_slithir_operations() if isinstance(ir, Unpack)]) + == 1 + ) From 8b07fe59d53498de89e5e79527c126bf0ac1f20a Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Fri, 8 Sep 2023 06:39:49 +0200 Subject: [PATCH 233/338] improve name resolution of type aliases (#2061) * BREAKING CHANGE: Renamed user_defined_types to type_aliases so it's less confusing with what we call UserDefinedType. * Added type aliased at the Contract level so now at the file scope there are only top level aliasing and fully qualified contract aliasing like C.myAlias. * Fix #1809 --- slither/core/compilation_unit.py | 6 ++-- slither/core/declarations/contract.py | 34 ++++++++++++++++++ slither/core/scope/scope.py | 6 ++-- slither/solc_parsing/declarations/contract.py | 8 ++--- .../declarations/using_for_top_level.py | 2 +- .../solc_parsing/expressions/find_variable.py | 9 +++-- .../slither_compilation_unit_solc.py | 8 ++--- .../solidity_types/type_parsing.py | 30 ++++++++-------- .../visitors/slithir/expression_to_slithir.py | 4 +-- tests/e2e/solc_parsing/test_ast_parsing.py | 1 + .../type-aliases.sol-0.8.19-compact.zip | Bin 0 -> 2111 bytes .../type-aliases.sol-0.8.19-compact.json | 6 ++++ .../solc_parsing/test_data/type-aliases.sol | 20 +++++++++++ tests/unit/core/test_source_mapping.py | 6 ++-- 14 files changed, 101 insertions(+), 39 deletions(-) create mode 100644 tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/type-aliases.sol-0.8.19-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/type-aliases.sol diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 6d24786eb..35180cefc 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -47,7 +47,7 @@ class SlitherCompilationUnit(Context): self._pragma_directives: List[Pragma] = [] self._import_directives: List[Import] = [] self._custom_errors: List[CustomErrorTopLevel] = [] - self._user_defined_value_types: Dict[str, TypeAliasTopLevel] = {} + self._type_aliases: Dict[str, TypeAliasTopLevel] = {} self._all_functions: Set[Function] = set() self._all_modifiers: Set[Modifier] = set() @@ -220,8 +220,8 @@ class SlitherCompilationUnit(Context): return self._custom_errors @property - def user_defined_value_types(self) -> Dict[str, TypeAliasTopLevel]: - return self._user_defined_value_types + def type_aliases(self) -> Dict[str, TypeAliasTopLevel]: + return self._type_aliases # endregion ################################################################################### diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 9b1488db3..f9bf15306 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -45,6 +45,7 @@ if TYPE_CHECKING: from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.scope.scope import FileScope from slither.core.cfg.node import Node + from slither.core.solidity_types import TypeAliasContract LOGGER = logging.getLogger("Contract") @@ -81,6 +82,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods self._functions: Dict[str, "FunctionContract"] = {} self._linearizedBaseContracts: List[int] = [] self._custom_errors: Dict[str, "CustomErrorContract"] = {} + self._type_aliases: Dict[str, "TypeAliasContract"] = {} # The only str is "*" self._using_for: Dict[USING_FOR_KEY, USING_FOR_ITEM] = {} @@ -364,6 +366,38 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods def custom_errors_as_dict(self) -> Dict[str, "CustomErrorContract"]: return self._custom_errors + # endregion + ################################################################################### + ################################################################################### + # region Custom Errors + ################################################################################### + ################################################################################### + + @property + def type_aliases(self) -> List["TypeAliasContract"]: + """ + list(TypeAliasContract): List of the contract's custom errors + """ + return list(self._type_aliases.values()) + + @property + def type_aliases_inherited(self) -> List["TypeAliasContract"]: + """ + list(TypeAliasContract): List of the inherited custom errors + """ + return [s for s in self.type_aliases if s.contract != self] + + @property + def type_aliases_declared(self) -> List["TypeAliasContract"]: + """ + list(TypeAliasContract): List of the custom errors declared within the contract (not inherited) + """ + return [s for s in self.type_aliases if s.contract == self] + + @property + def type_aliases_as_dict(self) -> Dict[str, "TypeAliasContract"]: + return self._type_aliases + # endregion ################################################################################### ################################################################################### diff --git a/slither/core/scope/scope.py b/slither/core/scope/scope.py index cafeb3585..937a05136 100644 --- a/slither/core/scope/scope.py +++ b/slither/core/scope/scope.py @@ -52,7 +52,7 @@ class FileScope: # User defined types # Name -> type alias - self.user_defined_types: Dict[str, TypeAlias] = {} + self.type_aliases: Dict[str, TypeAlias] = {} def add_accesible_scopes(self) -> bool: """ @@ -95,8 +95,8 @@ class FileScope: if not _dict_contain(new_scope.renaming, self.renaming): self.renaming.update(new_scope.renaming) learn_something = True - if not _dict_contain(new_scope.user_defined_types, self.user_defined_types): - self.user_defined_types.update(new_scope.user_defined_types) + if not _dict_contain(new_scope.type_aliases, self.type_aliases): + self.type_aliases.update(new_scope.type_aliases) learn_something = True return learn_something diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 74a1cbcf0..a118b1e65 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -291,10 +291,10 @@ class ContractSolc(CallerContextExpression): alias = item["name"] alias_canonical = self._contract.name + "." + item["name"] - user_defined_type = TypeAliasContract(original_type, alias, self.underlying_contract) - user_defined_type.set_offset(item["src"], self.compilation_unit) - self._contract.file_scope.user_defined_types[alias] = user_defined_type - self._contract.file_scope.user_defined_types[alias_canonical] = user_defined_type + type_alias = TypeAliasContract(original_type, alias, self.underlying_contract) + type_alias.set_offset(item["src"], self.compilation_unit) + self._contract.type_aliases_as_dict[alias] = type_alias + self._contract.file_scope.type_aliases[alias_canonical] = type_alias def _parse_struct(self, struct: Dict) -> None: diff --git a/slither/solc_parsing/declarations/using_for_top_level.py b/slither/solc_parsing/declarations/using_for_top_level.py index fe72e5780..bfed3c417 100644 --- a/slither/solc_parsing/declarations/using_for_top_level.py +++ b/slither/solc_parsing/declarations/using_for_top_level.py @@ -152,7 +152,7 @@ class UsingForTopLevelSolc(CallerContextExpression): # pylint: disable=too-few- if self._global: for scope in self.compilation_unit.scopes.values(): if isinstance(type_name, TypeAliasTopLevel): - for alias in scope.user_defined_types.values(): + for alias in scope.type_aliases.values(): if alias == type_name: scope.using_for_directives.add(self._using_for) elif isinstance(type_name, UserDefinedType): diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 32f5afc58..3bbdd268e 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -114,6 +114,8 @@ def find_top_level( :return: :rtype: """ + if var_name in scope.type_aliases: + return scope.type_aliases[var_name], False if var_name in scope.structures: return scope.structures[var_name], False @@ -205,6 +207,10 @@ def _find_in_contract( if sig == var_name: return modifier + type_aliases = contract.type_aliases_as_dict + if var_name in type_aliases: + return type_aliases[var_name] + # structures are looked on the contract declarer structures = contract.structures_as_dict if var_name in structures: @@ -362,9 +368,6 @@ def find_variable( if var_name in current_scope.renaming: var_name = current_scope.renaming[var_name] - if var_name in current_scope.user_defined_types: - return current_scope.user_defined_types[var_name], False - # Use ret0/ret1 to help mypy ret0 = _find_variable_from_ref_declaration( referenced_declaration, direct_contracts, direct_functions diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 00ac3a519..ecfecb4f0 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -344,10 +344,10 @@ class SlitherCompilationUnitSolc(CallerContextExpression): original_type = ElementaryType(underlying_type["name"]) - user_defined_type = TypeAliasTopLevel(original_type, alias, scope) - user_defined_type.set_offset(top_level_data["src"], self._compilation_unit) - self._compilation_unit.user_defined_value_types[alias] = user_defined_type - scope.user_defined_types[alias] = user_defined_type + type_alias = TypeAliasTopLevel(original_type, alias, scope) + type_alias.set_offset(top_level_data["src"], self._compilation_unit) + self._compilation_unit.type_aliases[alias] = type_alias + scope.type_aliases[alias] = type_alias else: raise SlitherException(f"Top level {top_level_data[self.get_key()]} not supported") diff --git a/slither/solc_parsing/solidity_types/type_parsing.py b/slither/solc_parsing/solidity_types/type_parsing.py index e12290722..c03b8e656 100644 --- a/slither/solc_parsing/solidity_types/type_parsing.py +++ b/slither/solc_parsing/solidity_types/type_parsing.py @@ -235,7 +235,7 @@ def parse_type( sl: "SlitherCompilationUnit" renaming: Dict[str, str] - user_defined_types: Dict[str, TypeAlias] + type_aliases: Dict[str, TypeAlias] enums_direct_access: List["Enum"] = [] # Note: for convenicence top level functions use the same parser than function in contract # but contract_parser is set to None @@ -247,13 +247,13 @@ def parse_type( sl = caller_context.compilation_unit next_context = caller_context renaming = {} - user_defined_types = sl.user_defined_value_types + type_aliases = sl.type_aliases else: assert isinstance(caller_context, FunctionSolc) sl = caller_context.underlying_function.compilation_unit next_context = caller_context.slither_parser renaming = caller_context.underlying_function.file_scope.renaming - user_defined_types = caller_context.underlying_function.file_scope.user_defined_types + type_aliases = caller_context.underlying_function.file_scope.type_aliases structures_direct_access = sl.structures_top_level all_structuress = [c.structures for c in sl.contracts] all_structures = [item for sublist in all_structuress for item in sublist] @@ -299,7 +299,7 @@ def parse_type( functions = list(scope.functions) renaming = scope.renaming - user_defined_types = scope.user_defined_types + type_aliases = scope.type_aliases elif isinstance(caller_context, (ContractSolc, FunctionSolc)): sl = caller_context.compilation_unit if isinstance(caller_context, FunctionSolc): @@ -329,7 +329,7 @@ def parse_type( functions = contract.functions + contract.modifiers renaming = scope.renaming - user_defined_types = scope.user_defined_types + type_aliases = scope.type_aliases else: raise ParsingError(f"Incorrect caller context: {type(caller_context)}") @@ -343,8 +343,8 @@ def parse_type( name = t.name if name in renaming: name = renaming[name] - if name in user_defined_types: - return user_defined_types[name] + if name in type_aliases: + return type_aliases[name] return _find_from_type_name( name, functions, @@ -365,9 +365,9 @@ def parse_type( name = t["typeDescriptions"]["typeString"] if name in renaming: name = renaming[name] - if name in user_defined_types: - _add_type_references(user_defined_types[name], t["src"], sl) - return user_defined_types[name] + if name in type_aliases: + _add_type_references(type_aliases[name], t["src"], sl) + return type_aliases[name] type_found = _find_from_type_name( name, functions, @@ -386,9 +386,9 @@ def parse_type( name = t["attributes"][type_name_key] if name in renaming: name = renaming[name] - if name in user_defined_types: - _add_type_references(user_defined_types[name], t["src"], sl) - return user_defined_types[name] + if name in type_aliases: + _add_type_references(type_aliases[name], t["src"], sl) + return type_aliases[name] type_found = _find_from_type_name( name, functions, @@ -407,8 +407,8 @@ def parse_type( name = t["name"] if name in renaming: name = renaming[name] - if name in user_defined_types: - return user_defined_types[name] + if name in type_aliases: + return type_aliases[name] type_found = _find_from_type_name( name, functions, diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 005ad81a4..a1dadbb63 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -516,8 +516,8 @@ class ExpressionToSlithIR(ExpressionVisitor): # contract A { type MyInt is int} # contract B { function f() public{ A.MyInt test = A.MyInt.wrap(1);}} # The logic is handled by _post_call_expression - if expression.member_name in expr.file_scope.user_defined_types: - set_val(expression, expr.file_scope.user_defined_types[expression.member_name]) + if expression.member_name in expr.file_scope.type_aliases: + set_val(expression, expr.file_scope.type_aliases[expression.member_name]) return # Lookup errors referred to as member of contract e.g. Test.myError.selector if expression.member_name in expr.custom_errors_as_dict: diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index 307e6736f..28ac79986 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -459,6 +459,7 @@ ALL_TESTS = [ ["0.6.9", "0.7.6", "0.8.16"], ), Test("user_defined_operators-0.8.19.sol", ["0.8.19"]), + Test("type-aliases.sol", ["0.8.19"]), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip b/tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..0c4d2b1c5e2a155c49cf64c3815266e1b19dc65c GIT binary patch literal 2111 zcma);c{~%01I9OJxsQm+D3WuIO=yngT$3ZTFiXQoIT}L9BFBu}xd~_y6zn`904c-+!L}zmKIUGm9R83BUvJOW8wPCc@A!*#UsH%K(5h z008iN@(8bl^Ki%c;(Z~$-X4zlz(?LbevUXF=lkydc*p}^Z?Cf~tN<(k@C*RZA(7mm zzo3MIk-<7RcTSg=`{h<}<8_p<#y;otLnW1npKSTWw~f zBa8XyV}68OuQM$JorFk_!s@gN;3P;l+y(BnDnyfl4kkAS`vo*Ma{A=wTpBg0$Ay>o z3-uHV%T+$-vSxLP?B0_|c3p6-ITv0jnLO9<&3+woic|Ep-Xn)} zM@b=K%e93)mX0S(p}N0n^gG*J4w(KXju6RV4#S6+?gsVPPkrA#D@_?6qn7H&9=ZJ! z=~uLW^wC>^Xwurpy*dq!5f%AaMR;Nw}WPdo=paOK7wNJQj8sd)A z(c%O>+;+^{~yroyf>)K}#v%W(-L+m5kT?$l}GW5*ylr3eb|t#Fm}7ZroySAPZ6To~5Rh z9H?q>UVPF~au$?j!J6nF+|9SC8kxc5ywCA_47jFn2x;^J+)D)JA7*# zyv}r%eesE!N0uq6-{M4ElI|)bj}~aPCal-QXVZ<($k=*6*5Hxbs8yK`hJ)r37N1#s zS*q0^2<+uzzTpI=*Hga*HS=+Ol2CLv{{k_ZX&*H7hL735m;T^pXTdrkU0voWhMBW! zz!wg_$yRFI^XJZh@}BE^Lp)8O3YHbCaE6i`qHk7?=#9o*vwEQVz~#o!cndx=B~=}) zT!%~=x*|G&i~#ZCOtA)Z+xSvd$Q)rD<+0v;3>UD{SH_BTTM~ZM^dz!MYO-{c)*MRT|}$l zZ0{y$#>g^Q_Rz6W*6Xg|?~IR7Wl5}00 zlO3D6$-)NmXPH|7Blvz1u+KQ%NU-90C)pJ5`#lgVQX5oehE;Q|Q!n>pA07QBjH}Wn z4+?m1=N;3G5Hxx3PyeVbqz77NrAEM>Yb+Dk7JyaPj&>&jFd1JG`#xf5WJ*R3c^=yA z^c1C(d`+h~+JX{DtV$uK4^zcL_dSQ$^-rCXQj5BHzl8Q+MHw&$4@z`99Hq~5Ujbv9 z?D+xX7DgwAG8T7NUvRe1(%d)=aBDIc(Nl+;7{t&u=0(JMRhY6^64O>L`{j4I(4XK%6J!mO%ueAL?(?-2om<8Od!|^T6Os znLvRB>A3lU9z6TPKPhi#D=2Dx@>0d%IQ-(*w40I!C9WukjBHu!RP2^;Z{{5YGvW52 z4D0XthxB2a`(=m2z*lU)ekQyPY;n61riRLo%`nEjEQx@9h8Kzoy7<(+|J^cY5^LQw zrEF6NcYn(1^6q^G2O|)e3E>h8D(nmS(p*-#OR;^RLc2hB-AJ2$l38L*IMEfzM7&6H zuuU%Q2*2w82(4h?qV)~2H2pibUnn7OwxR<901V9}euaH#5bA|vT5@Ei^1wS$%B^}* z6b_iiqIm8exPe8aXQzz0W`!Uq73BBJEH1yVd$z8fFX~+tvI!>5sN9(Ww?|>bF9ZDrut|7S&tv#F`21SA{*q2}QkJ8PU1Iw0d=Ne$?udB}g9Y;4K{( z(9V~nr9s1$4|NxO(mjnSr8MAm{uYV1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" + }, + "DeleteTest": {} +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/type-aliases.sol b/tests/e2e/solc_parsing/test_data/type-aliases.sol new file mode 100644 index 000000000..53fdaabeb --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/type-aliases.sol @@ -0,0 +1,20 @@ + +struct Z { + int x; + int y; +} + +contract OtherTest { + struct Z { + int x; + int y; + } + + function myfunc() external { + Z memory z = Z(2,3); + } +} + +contract DeleteTest { + type Z is int; +} diff --git a/tests/unit/core/test_source_mapping.py b/tests/unit/core/test_source_mapping.py index fe5335977..55eb08295 100644 --- a/tests/unit/core/test_source_mapping.py +++ b/tests/unit/core/test_source_mapping.py @@ -85,15 +85,13 @@ def test_references_user_defined_aliases(solc_binary_path): file = Path(SRC_MAPPING_TEST_ROOT, "ReferencesUserDefinedAliases.sol").as_posix() slither = Slither(file, solc=solc_path) - alias_top_level = slither.compilation_units[0].user_defined_value_types["aliasTopLevel"] + alias_top_level = slither.compilation_units[0].type_aliases["aliasTopLevel"] assert len(alias_top_level.references) == 2 lines = _sort_references_lines(alias_top_level.references) assert lines == [12, 16] alias_contract_level = ( - slither.compilation_units[0] - .contracts[0] - .file_scope.user_defined_types["C.aliasContractLevel"] + slither.compilation_units[0].contracts[0].file_scope.type_aliases["C.aliasContractLevel"] ) assert len(alias_contract_level.references) == 2 lines = _sort_references_lines(alias_contract_level.references) From 0a5b9fdec1cd408ec9c7baa67862cafe3d945171 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 8 Sep 2023 00:28:05 -0500 Subject: [PATCH 234/338] prioritize reference id in name resolution to avoid shadowing related issues --- slither/core/declarations/contract.py | 8 +++ slither/solc_parsing/declarations/contract.py | 2 + .../solc_parsing/expressions/find_variable.py | 57 ++++++++++++------- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 9b1488db3..46a548cee 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -77,6 +77,8 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods # do not contain private variables inherited from contract self._variables: Dict[str, "StateVariable"] = {} self._variables_ordered: List["StateVariable"] = [] + # Reference id -> variable declaration (only available for compact AST) + self._state_variables_by_ref_id: Dict[int, "StateVariable"] = {} self._modifiers: Dict[str, "Modifier"] = {} self._functions: Dict[str, "FunctionContract"] = {} self._linearizedBaseContracts: List[int] = [] @@ -370,6 +372,12 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods # region Variables ################################################################################### ################################################################################### + @property + def state_variables_by_ref_id(self) -> Dict[int, "StateVariable"]: + """ + Returns the state variables by reference id (only available for compact AST). + """ + return self._state_variables_by_ref_id @property def variables(self) -> List["StateVariable"]: diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 74a1cbcf0..b7fc846d0 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -357,6 +357,8 @@ class ContractSolc(CallerContextExpression): self._variables_parser.append(var_parser) assert var.name + if var_parser.reference_id is not None: + self._contract.state_variables_by_ref_id[var_parser.reference_id] = var self._contract.variables_as_dict[var.name] = var self._contract.add_variables_ordered([var]) diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 32f5afc58..f0adef1d5 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -54,10 +54,26 @@ def _find_variable_from_ref_declaration( referenced_declaration: Optional[int], all_contracts: List["Contract"], all_functions: List["Function"], + function_parser: Optional["FunctionSolc"], + contract_declarer: Optional["Contract"], ) -> Optional[Union[Contract, Function]]: + """ + Reference declarations take the highest priority, but they are not available for legacy AST. + """ if referenced_declaration is None: return None - # id of the contracts is the referenced declaration + # We look for variable declared with the referencedDeclaration attribute + if function_parser is not None: + func_variables_renamed = function_parser.variables_renamed + if referenced_declaration in func_variables_renamed: + return func_variables_renamed[referenced_declaration].underlying_variable + + if ( + contract_declarer is not None + and referenced_declaration in contract_declarer.state_variables_by_ref_id + ): + return contract_declarer.state_variables_by_ref_id[referenced_declaration] + # Ccontracts ids are the referenced declaration # This is not true for the functions, as we dont always have the referenced_declaration # But maybe we could? (TODO) for contract_candidate in all_contracts: @@ -72,14 +88,9 @@ def _find_variable_from_ref_declaration( def _find_variable_in_function_parser( var_name: str, function_parser: Optional["FunctionSolc"], - referenced_declaration: Optional[int] = None, ) -> Optional[Variable]: if function_parser is None: return None - # We look for variable declared with the referencedDeclaration attr - func_variables_renamed = function_parser.variables_renamed - if referenced_declaration and referenced_declaration in func_variables_renamed: - return func_variables_renamed[referenced_declaration].underlying_variable # If not found, check for name func_variables = function_parser.underlying_function.variables_as_dict if var_name in func_variables: @@ -365,20 +376,6 @@ def find_variable( if var_name in current_scope.user_defined_types: return current_scope.user_defined_types[var_name], False - # Use ret0/ret1 to help mypy - ret0 = _find_variable_from_ref_declaration( - referenced_declaration, direct_contracts, direct_functions - ) - if ret0: - return ret0, False - - function_parser: Optional[FunctionSolc] = ( - caller_context if isinstance(caller_context, FunctionSolc) else None - ) - ret1 = _find_variable_in_function_parser(var_name, function_parser, referenced_declaration) - if ret1: - return ret1, False - contract: Optional[Contract] = None contract_declarer: Optional[Contract] = None if isinstance(caller_context, ContractSolc): @@ -392,6 +389,24 @@ def find_variable( else: assert isinstance(underlying_func, FunctionTopLevel) + function_parser: Optional[FunctionSolc] = ( + caller_context if isinstance(caller_context, FunctionSolc) else None + ) + # Use ret0/ret1 to help mypy + ret0 = _find_variable_from_ref_declaration( + referenced_declaration, + direct_contracts, + direct_functions, + function_parser, + contract_declarer, + ) + if ret0: + return ret0, False + + ret1 = _find_variable_in_function_parser(var_name, function_parser) + if ret1: + return ret1, False + ret = _find_in_contract(var_name, contract, contract_declarer, is_super, is_identifier_path) if ret: return ret, False @@ -442,6 +457,8 @@ def find_variable( referenced_declaration, list(current_scope.contracts.values()), list(current_scope.functions), + None, + None, ) if ret: return ret, False From ddd9d6561f5583f01415930d753efc9f2acd55a4 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 8 Sep 2023 13:20:03 +0200 Subject: [PATCH 235/338] Add IR test --- tests/unit/slithir/test_data/enum_max_min.sol | 37 ++++++++++ tests/unit/slithir/test_enum.py | 67 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 tests/unit/slithir/test_data/enum_max_min.sol create mode 100644 tests/unit/slithir/test_enum.py diff --git a/tests/unit/slithir/test_data/enum_max_min.sol b/tests/unit/slithir/test_data/enum_max_min.sol new file mode 100644 index 000000000..5f5ecc342 --- /dev/null +++ b/tests/unit/slithir/test_data/enum_max_min.sol @@ -0,0 +1,37 @@ + +library Q { + enum E {a} +} + +contract Z { + enum E {a,b} +} + +contract D { + enum E {a,b,c} + + function a() public returns(uint){ + return uint(type(E).max); + } + + function b() public returns(uint){ + return uint(type(Q.E).max); + } + + function c() public returns(uint){ + return uint(type(Z.E).max); + } + + function d() public returns(uint){ + return uint(type(E).min); + } + + function e() public returns(uint){ + return uint(type(Q.E).min); + } + + function f() public returns(uint){ + return uint(type(Z.E).min); + } + +} diff --git a/tests/unit/slithir/test_enum.py b/tests/unit/slithir/test_enum.py new file mode 100644 index 000000000..4f1fc4e59 --- /dev/null +++ b/tests/unit/slithir/test_enum.py @@ -0,0 +1,67 @@ +from pathlib import Path +from slither import Slither +from slither.slithir.operations import Assignment +from slither.slithir.variables import Constant + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" + + +def test_enum_max_min(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.19") + slither = Slither(Path(TEST_DATA_DIR, "enum_max_min.sol").as_posix(), solc=solc_path) + + contract = slither.get_contract_from_name("D")[0] + + f = contract.get_function_from_full_name("a()") + # TMP_1(uint256) := 2(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 2 + ) + + f = contract.get_function_from_full_name("b()") + # TMP_4(uint256) := 0(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 0 + ) + + f = contract.get_function_from_full_name("c()") + # TMP_7(uint256) := 1(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 1 + ) + + f = contract.get_function_from_full_name("d()") + # TMP_10(uint256) := 0(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 0 + ) + + f = contract.get_function_from_full_name("e()") + # TMP_13(uint256) := 0(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 0 + ) + + f = contract.get_function_from_full_name("f()") + # TMP_16(uint256) := 0(uint256) + assignment = f.slithir_operations[1] + assert ( + isinstance(assignment, Assignment) + and isinstance(assignment.rvalue, Constant) + and assignment.rvalue.value == 0 + ) From 8d5c033fbeaea0c464bb0cfb177ab9e1124ddf3a Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:19:20 +0200 Subject: [PATCH 236/338] Improve mapping-deletion detector for nested mappings (#2084) * Fix for nested mappings * Add test --- .../detectors/statements/mapping_deletion.py | 24 +++++++++++++----- ...etection_0_4_25_MappingDeletion_sol__0.txt | 7 +++-- ...etection_0_5_16_MappingDeletion_sol__0.txt | 7 +++-- ...etection_0_6_11_MappingDeletion_sol__0.txt | 7 +++-- ...Detection_0_7_6_MappingDeletion_sol__0.txt | 7 +++-- .../0.4.25/MappingDeletion.sol | 19 +++++++++++--- .../0.4.25/MappingDeletion.sol-0.4.25.zip | Bin 4451 -> 4826 bytes .../0.5.16/MappingDeletion.sol | 12 ++++++++- .../0.5.16/MappingDeletion.sol-0.5.16.zip | Bin 4490 -> 4854 bytes .../0.6.11/MappingDeletion.sol | 12 ++++++++- .../0.6.11/MappingDeletion.sol-0.6.11.zip | Bin 4462 -> 4829 bytes .../0.7.6/MappingDeletion.sol | 12 ++++++++- .../0.7.6/MappingDeletion.sol-0.7.6.zip | Bin 4359 -> 4728 bytes 13 files changed, 86 insertions(+), 21 deletions(-) diff --git a/slither/detectors/statements/mapping_deletion.py b/slither/detectors/statements/mapping_deletion.py index 4cdac7240..0940d5a07 100644 --- a/slither/detectors/statements/mapping_deletion.py +++ b/slither/detectors/statements/mapping_deletion.py @@ -6,6 +6,7 @@ from typing import List, Tuple from slither.core.cfg.node import Node from slither.core.declarations import Structure from slither.core.declarations.contract import Contract +from slither.core.variables.variable import Variable from slither.core.declarations.function_contract import FunctionContract from slither.core.solidity_types import MappingType, UserDefinedType from slither.detectors.abstract_detector import ( @@ -69,14 +70,25 @@ The mapping `balances` is never deleted, so `remove` does not work as intended." for ir in node.irs: if isinstance(ir, Delete): value = ir.variable - if isinstance(value.type, UserDefinedType) and isinstance( - value.type.type, Structure - ): - st = value.type.type - if any(isinstance(e.type, MappingType) for e in st.elems.values()): - ret.append((f, st, node)) + MappingDeletionDetection.check_if_mapping(value, ret, f, node) + return ret + @staticmethod + def check_if_mapping( + value: Variable, + ret: List[Tuple[FunctionContract, Structure, Node]], + f: FunctionContract, + node: Node, + ): + if isinstance(value.type, UserDefinedType) and isinstance(value.type.type, Structure): + st = value.type.type + if any(isinstance(e.type, MappingType) for e in st.elems.values()): + ret.append((f, st, node)) + return + for e in st.elems.values(): + MappingDeletionDetection.check_if_mapping(e, ret, f, node) + def _detect(self) -> List[Output]: """Detect mapping deletion diff --git a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_4_25_MappingDeletion_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_4_25_MappingDeletion_sol__0.txt index 902f96668..4d47bb570 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_4_25_MappingDeletion_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_4_25_MappingDeletion_sol__0.txt @@ -1,6 +1,9 @@ +Balances.deleteNestedBalance() (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#40-42) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#17-20) which contains a mapping: + -delete nestedStackBalance (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#41) + Lib.deleteSt(Lib.MyStruct[1]) (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#5-7) which contains a mapping: -delete st[0] (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#10) -Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#28-31) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#17-20) which contains a mapping: - -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#30) +Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#35-38) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#17-20) which contains a mapping: + -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol#37) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_5_16_MappingDeletion_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_5_16_MappingDeletion_sol__0.txt index fec236e1c..88e4ac554 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_5_16_MappingDeletion_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_5_16_MappingDeletion_sol__0.txt @@ -1,6 +1,9 @@ Lib.deleteSt(Lib.MyStruct[1]) (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#5-7) which contains a mapping: -delete st[0] (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#10) -Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#29-32) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#17-20) which contains a mapping: - -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#31) +Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#35-38) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#17-20) which contains a mapping: + -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#37) + +Balances.deleteNestedBalance() (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#40-42) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#17-20) which contains a mapping: + -delete nestedStackBalance (tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol#41) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_6_11_MappingDeletion_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_6_11_MappingDeletion_sol__0.txt index 7f0372c36..4270f0d86 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_6_11_MappingDeletion_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_6_11_MappingDeletion_sol__0.txt @@ -1,6 +1,9 @@ -Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#29-32) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#17-20) which contains a mapping: - -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#31) +Balances.deleteNestedBalance() (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#40-42) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#17-20) which contains a mapping: + -delete nestedStackBalance (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#41) Lib.deleteSt(Lib.MyStruct[1]) (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#5-7) which contains a mapping: -delete st[0] (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#10) +Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#35-38) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#17-20) which contains a mapping: + -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol#37) + diff --git a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_7_6_MappingDeletion_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_7_6_MappingDeletion_sol__0.txt index f519a046f..ea6ed2dd6 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_7_6_MappingDeletion_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_MappingDeletionDetection_0_7_6_MappingDeletion_sol__0.txt @@ -1,5 +1,8 @@ -Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#29-32) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#17-20) which contains a mapping: - -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#31) +Balances.deleteNestedBalance() (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#40-42) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#17-20) which contains a mapping: + -delete nestedStackBalance (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#41) + +Balances.deleteBalance(uint256) (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#35-38) deletes Balances.BalancesStruct (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#17-20) which contains a mapping: + -delete stackBalance[idx] (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#37) Lib.deleteSt(Lib.MyStruct[1]) (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#9-11) deletes Lib.MyStruct (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#5-7) which contains a mapping: -delete st[0] (tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol#10) diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol b/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol index bedbb64a8..bcbc86c9d 100644 --- a/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol +++ b/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol @@ -6,7 +6,7 @@ library Lib{ mapping(address => uint) maps; } - function deleteSt(MyStruct[1] storage st){ + function deleteSt(MyStruct[1] storage st) internal { delete st[0]; } @@ -17,18 +17,29 @@ contract Balances { struct BalancesStruct{ address owner; mapping(address => uint) balances; - } + } + + struct NestedBalanceStruct { + BalancesStruct balanceStruct; + } mapping(uint => BalancesStruct) public stackBalance; + NestedBalanceStruct internal nestedStackBalance; + function createBalance(uint idx) public { - require(stackBalance[idx].owner == 0); - stackBalance[idx] = BalancesStruct(msg.sender); + require(stackBalance[idx].owner == address(0)); + BalancesStruct storage str = stackBalance[idx]; + str.owner = msg.sender; } function deleteBalance(uint idx) public { require(stackBalance[idx].owner == msg.sender); delete stackBalance[idx]; } + + function deleteNestedBalance() public { + delete nestedStackBalance; + } function setBalance(uint idx, address addr, uint val) public { require(stackBalance[idx].owner == msg.sender); diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol-0.4.25.zip b/tests/e2e/detectors/test_data/mapping-deletion/0.4.25/MappingDeletion.sol-0.4.25.zip index be3e13807a58aa1af11fdb342f340adc88a9755d..58859369959bfac936960954f215b5833a09526f 100644 GIT binary patch delta 4714 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 diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol b/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol index e1b608a46..bcbc86c9d 100644 --- a/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol +++ b/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol @@ -17,9 +17,15 @@ contract Balances { struct BalancesStruct{ address owner; mapping(address => uint) balances; - } + } + + struct NestedBalanceStruct { + BalancesStruct balanceStruct; + } mapping(uint => BalancesStruct) public stackBalance; + NestedBalanceStruct internal nestedStackBalance; + function createBalance(uint idx) public { require(stackBalance[idx].owner == address(0)); BalancesStruct storage str = stackBalance[idx]; @@ -30,6 +36,10 @@ contract Balances { require(stackBalance[idx].owner == msg.sender); delete stackBalance[idx]; } + + function deleteNestedBalance() public { + delete nestedStackBalance; + } function setBalance(uint idx, address addr, uint val) public { require(stackBalance[idx].owner == msg.sender); diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol-0.5.16.zip b/tests/e2e/detectors/test_data/mapping-deletion/0.5.16/MappingDeletion.sol-0.5.16.zip index 0ad84a58895f5b258c6da9782c5af54a4c8a90c0..2e578904619f0599c1f10815a5902848ac7061d6 100644 GIT binary patch delta 4742 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 l00XK304D$d00000000000Du7i0001!xe_-99}xfm005XpUMm0q diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol b/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol index e1b608a46..bcbc86c9d 100644 --- a/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol +++ b/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol @@ -17,9 +17,15 @@ contract Balances { struct BalancesStruct{ address owner; mapping(address => uint) balances; - } + } + + struct NestedBalanceStruct { + BalancesStruct balanceStruct; + } mapping(uint => BalancesStruct) public stackBalance; + NestedBalanceStruct internal nestedStackBalance; + function createBalance(uint idx) public { require(stackBalance[idx].owner == address(0)); BalancesStruct storage str = stackBalance[idx]; @@ -30,6 +36,10 @@ contract Balances { require(stackBalance[idx].owner == msg.sender); delete stackBalance[idx]; } + + function deleteNestedBalance() public { + delete nestedStackBalance; + } function setBalance(uint idx, address addr, uint val) public { require(stackBalance[idx].owner == msg.sender); diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol-0.6.11.zip b/tests/e2e/detectors/test_data/mapping-deletion/0.6.11/MappingDeletion.sol-0.6.11.zip index 5f66da061726c113304482f713b820a2633b3af7..8f532ea669ffceb1de40fa487ffbac2520a01042 100644 GIT binary patch delta 4724 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 uint) balances; - } + } + + struct NestedBalanceStruct { + BalancesStruct balanceStruct; + } mapping(uint => BalancesStruct) public stackBalance; + NestedBalanceStruct internal nestedStackBalance; + function createBalance(uint idx) public { require(stackBalance[idx].owner == address(0)); BalancesStruct storage str = stackBalance[idx]; @@ -30,6 +36,10 @@ contract Balances { require(stackBalance[idx].owner == msg.sender); delete stackBalance[idx]; } + + function deleteNestedBalance() public { + delete nestedStackBalance; + } function setBalance(uint idx, address addr, uint val) public { require(stackBalance[idx].owner == msg.sender); diff --git a/tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol-0.7.6.zip b/tests/e2e/detectors/test_data/mapping-deletion/0.7.6/MappingDeletion.sol-0.7.6.zip index 5888e0e534de961f401d61096c979e183b926d78..c685454ce649c797088054d6913880ef784de64a 100644 GIT binary patch delta 4615 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 delta 4267 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 Date: Fri, 8 Sep 2023 17:55:04 -0500 Subject: [PATCH 237/338] also support reference id for legacy AST --- slither/solc_parsing/expressions/expression_parsing.py | 9 +++++---- slither/solc_parsing/expressions/find_variable.py | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index a0bce044c..c192b4efe 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -486,13 +486,18 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression) t = None + referenced_declaration = None if caller_context.is_compact_ast: value = expression["name"] t = expression["typeDescriptions"]["typeString"] + if "referencedDeclaration" in expression: + referenced_declaration = expression["referencedDeclaration"] else: value = expression["attributes"]["value"] if "type" in expression["attributes"]: t = expression["attributes"]["type"] + if "referencedDeclaration" in expression["attributes"]: + referenced_declaration = expression["attributes"]["referencedDeclaration"] if t: found = re.findall(r"[struct|enum|function|modifier] \(([\[\] ()a-zA-Z0-9\.,_]*)\)", t) @@ -501,10 +506,6 @@ def parse_expression(expression: Dict, caller_context: CallerContextExpression) value = value + "(" + found[0] + ")" value = filter_name(value) - if "referencedDeclaration" in expression: - referenced_declaration = expression["referencedDeclaration"] - else: - referenced_declaration = None var, was_created = find_variable(value, caller_context, referenced_declaration) if was_created: var.set_offset(src, caller_context.compilation_unit) diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 6255ee51f..b7e28a891 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -63,10 +63,8 @@ def _find_variable_from_ref_declaration( if referenced_declaration is None: return None # We look for variable declared with the referencedDeclaration attribute - if function_parser is not None: - func_variables_renamed = function_parser.variables_renamed - if referenced_declaration in func_variables_renamed: - return func_variables_renamed[referenced_declaration].underlying_variable + if function_parser is not None and referenced_declaration in function_parser.variables_renamed: + return function_parser.variables_renamed[referenced_declaration].underlying_variable if ( contract_declarer is not None From 733012d15cce834aae0d56f8b96d202f285a9608 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Fri, 8 Sep 2023 21:40:58 -0400 Subject: [PATCH 238/338] issue #2083: add exceptions for i_ and s_ in the naming-conventions detector --- .../naming_convention/naming_convention.py | 22 +++++++++++++- ...ention_0_4_25_naming_convention_sol__0.txt | 12 ++++---- ...ention_0_5_16_naming_convention_sol__0.txt | 12 ++++---- ...ention_0_6_11_naming_convention_sol__0.txt | 28 +++++++++--------- ...vention_0_7_6_naming_convention_sol__0.txt | 28 +++++++++--------- .../0.4.25/naming_convention.sol | 3 +- .../0.4.25/naming_convention.sol-0.4.25.zip | Bin 3659 -> 3801 bytes ...arning_for_public_constants.sol-0.4.25.zip | Bin 1380 -> 1380 bytes .../0.5.16/naming_convention.sol | 3 +- .../0.5.16/naming_convention.sol-0.5.16.zip | Bin 3671 -> 3804 bytes ...arning_for_public_constants.sol-0.5.16.zip | Bin 1387 -> 1387 bytes .../0.6.11/naming_convention.sol | 5 +++- .../0.6.11/naming_convention.sol-0.6.11.zip | Bin 3688 -> 3930 bytes ...arning_for_public_constants.sol-0.6.11.zip | Bin 1409 -> 1409 bytes .../0.7.6/naming_convention.sol | 5 +++- .../0.7.6/naming_convention.sol-0.7.6.zip | Bin 3605 -> 3852 bytes ...warning_for_public_constants.sol-0.7.6.zip | Bin 1367 -> 1367 bytes 17 files changed, 73 insertions(+), 45 deletions(-) diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 0633799e5..904b57eac 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -45,6 +45,14 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 def is_cap_words(name: str) -> bool: return re.search("^[A-Z]([A-Za-z0-9]+)?_?$", name) is not None + @staticmethod + def is_immutable_naming(name: str) -> bool: + return re.search("^i_[a-z]([A-Za-z0-9]+)?_?$", name) is not None + + @staticmethod + def is_state_naming(name: str) -> bool: + return re.search("^s_[a-z]([A-Za-z0-9]+)?_?$", name) is not None + @staticmethod def is_mixed_case(name: str) -> bool: return re.search("^[a-z]([A-Za-z0-9]+)?_?$", name) is not None @@ -167,10 +175,22 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 results.append(res) else: - if var.visibility in ["private", "internal"]: + # first priority: check for immutable variable naming conventions + if var.is_immutable: + correct_naming = self.is_immutable_naming(var.name) + + # second priority: check for state variable naming conventions + elif self.is_state_naming(var.name): + correct_naming = True + + # third priority: check if visibility is private or internal and check for underscore mixed case + elif var.visibility in ["private", "internal"]: correct_naming = self.is_mixed_case_with_underscore(var.name) + + # fourth priority: check for mixed case naming conventions else: correct_naming = self.is_mixed_case(var.name) + if not correct_naming: info = ["Variable ", var, " is not in mixedCase\n"] diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt index e4a643678..2c05a3c40 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#71) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#71) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#60) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#61) is not in mixedCase Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.4.25 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt index 96f6aab3c..494253c35 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt @@ -1,10 +1,10 @@ Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#71) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#71) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#11) is not in mixedCase @@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#60) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#61) is not in mixedCase Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#57) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords @@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.5.16 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt index f1986fb78..e6e431fcc 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt @@ -1,32 +1,32 @@ -Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#14-16) is not in CapWords +Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#16-18) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#73) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#73) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#72) is not in mixedCase -Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#11) is not in mixedCase +Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#13) is not in mixedCase Constant naming.MY_other_CONSTANT (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES -Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#3-48) is not in CapWords +Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#3-50) is not in CapWords Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#60) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#63) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#57) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#59) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#72) is single letter l, O, or I, which should not be used -Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#23) is not in CapWords +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#25) is not in CapWords -Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#41-43) is not in mixedCase +Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#43-45) is not in mixedCase -Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#30-33) is not in mixedCase +Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#32-35) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#71) is single letter l, O, or I, which should not be used -Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#35) is not in mixedCase +Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#37) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt index b471cbfa2..d033db260 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt @@ -1,32 +1,32 @@ -Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#14-16) is not in CapWords +Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#16-18) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#73) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#73) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#72) is not in mixedCase -Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#11) is not in mixedCase +Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#13) is not in mixedCase Constant naming.MY_other_CONSTANT (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES -Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#3-48) is not in CapWords +Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#3-50) is not in CapWords Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#60) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#63) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#57) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#59) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#72) is single letter l, O, or I, which should not be used -Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#23) is not in CapWords +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#25) is not in CapWords -Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#41-43) is not in mixedCase +Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#43-45) is not in mixedCase -Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#30-33) is not in mixedCase +Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#32-35) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#71) is single letter l, O, or I, which should not be used -Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#35) is not in mixedCase +Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#37) is not in mixedCase diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol index add7867e0..3cc7197e5 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol @@ -55,7 +55,8 @@ contract T { uint private _myPrivateVar; uint internal _myInternalVar; uint public _myPublicVar; - + uint public s_myStateVar; + uint public myPublicVar; function test(uint _unused, uint _used) public returns(uint){ return _used;} diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip index fe35f0c006f2a1526c143d8def79ef54a25e15c3..a448234c6efc12d56a6f8f3b0795d137c6097df9 100644 GIT binary patch delta 3511 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 delta 3371 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip index b8c6c58c1d0b2579589ca860a0704718ac875347..10aff7711e99be35362fb893bf8c6fb9d4c08ef6 100644 GIT binary patch delta 30 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 delta 3380 zcmV-44a@S}9oHNfP)h>@KL7#%4ghDFCs#icUk{@V0023Akr@7ebWIo-1IEP96*B=1 zO5Y?bN)eiJiXb-7GY4fQ?Y#7N2~=8*IPZ5;W+6j=Vb~0(Gn3^6b~Q|~I+?s2II!%m z)8gKda6FUP!6NVLVB5))ELIk? zG$C(5c@K){wWqi=ql-89M6T050m=C=wYcP4Vaq3_k5R{eY{U>k=vyy>gtj2t8@E+3 zfq2_51hDw4ieM`T>GxVum0OYe*9X!q!)xrq;eY=VZ7Dj;?9w+mu@X2D?C66y*bB^c zyHhXK9*_SF6qX4M^~{BFRdK^zbJT4R%+x2SxO@F%-e%1ez?pQV zqT`@4tp|EGTI{byHYgN9nzE#}KKR{-|EvmsSBR7Pdg?o}&~KgQ?Em$~o18)g#ikOh za6D)Ld!OCsyn5OP(ld3}=O$?my@Ecf?UBhHo4Ox=%>C_($dGRE4G9duB)*0U+~~*c zU?}6KE{H+80@M;%Pi3)?D$|VAF0BezU31%AlXmX$4d_yzxM;X%7GtiFK$@TLS^Wfp~oO%;ovg(Z1&CKn9CTVuO(>ZNFT%p%<_Y^U_#u6!Q!DeNW_Dzi?k=mYc zbRKnSekXeO(hwr%Cq%uyhy-2b^h1cr)k(J-{L@yqDYH;2%A6~0lEdg8+p$(0V!$v8 z$g7cFFaQb~SZrj?C9xz?a&0FuaHLFFS1Me8!<9~=v*;Rlsc2LuTB22rR5O{^i$zEp zJzNsdPeg}%FmLeg%>IgG={Ow*eQnyt<@Cc19{68i_6;gCujgu|COQCX&;+))213dU zYg>BJUUYo+Y&e?#wg%}=hX=?TW}CvxG3w$iTnPQf?RDFmS*ir8`(aP2>SiHl0>xi{ zVa&XCisw0IPo-hOs__4s%YZHgs1I7faVL*UniY7UmDx~BXVw^3MF%gYeaiP5=LeZG z?+^_WKbq~o;{v(TmEh89|NeF8%~RO}dohQ9cBqvr_>0i4gallqeR9vJ51cw;SF1@% z4-*xE$9e@7hIvuN5jkc=dTI3H~Rz?#r#c*Y}@+ zZqAVlBE*K-2qJl~%{#;k2N}MbSm&VC8clE zo0MRjcaGv_3w6$>!4P~jC!uFXFnU3CZ>wevHlN3CCrqxv4$;j)KNV{7Wuz7hpY zR}Tmjeu5%zZAbqP z@8KMCCi%T`zHa@P-^ZhCWt8ovZaom>Eubk(YR1BBn)nM(ya%RNVmU2T5agY%;s!a6 zS4fA-!3$yYSZ4jz1_{pfL9N)-Jg@@7b8QS{BBU)aq#*yS&3?MM6m0l^A7Ju<7c=!& zm8B%!D9{iW@4(!|I{^!GfV1EJIdmcyh2rb9i+<)4eB@|7M9kX-%Zpxjpii>)hB2^K zTTnFY`Z;g=6i8S_J{$Gpp9*IbkZls-z0#W%jDd?$i>!sKPVaK^ zD>{yb+V#4hrj_G1chqH{r21M(Ew;mOAH}xr63**Jbhu~lft~w*sUT4^^f{)foXkfb zl-;;jc>wC0Xq-SW8O%SDl4W}|(UsUyH`W^G!m(|V()MWrt-oFxbNFd}c4+Wc*2_~R z6*QT&PDzrAJxZnV940?W^Ui>|A-W|UZ;!gCATh)E9(I6lrzfWeOP-}>WsaK{_p=o7 zrqAG-`fCdgZ6e%%&DcNi7J|gu$f%5p#)!f_IUK}fbu2JYoZ6~LudVj|MSpN+tZbPK z80P+ebjdIAC)&fjCWdo!q+EGM%Vz@J!TqC?dvT6?GbX-nRaS_^_AslV1@I<+2+NYLsDKqx!-)uXBlok z=TC|ZCIQn2@A}yEELal>?G7i>+Ru|UWi#st)%$>deFY-YC|vI;nwgY=DV~r;=FWDw z0Kz(*Db|J$%CBAjg##D&XK{SbW7VIQktT>an``eyy2z3s1nq+eZ_g{_wU$G+R$^Y$ z#9gnAoPrQlh8jZlgGuv!efsN@nP@XiL8zE}<}VG{1CC%|Y!p0Tzv(BoviI(C7L*^* zRkRy_f-HlW)8;Y6#Jkc!-w49RpWsO{Mtg|4wty4FF6oZln ze`V7Xae4$;l^Yij%-z|(A3Yklhb=C~(bragEv)i|T3~n(=DRb}p=v|$vCUl}h+5Ud ztLY`yEMT09*pj_0o6A4R)6D!-E=e9BYKZ1TmNpP+MPuZ@GGgUyff^*Ugk@{rjm#JI zCF8(O-ssJ*u?gprsojT89)O@Am&Rk_-c+G)L!$-04cIH*`DQ{Pgs7BkkO~afjS}U5 z%?7f4-GQ4>MOX~;SqzN)>=3)6wK9i4Wwb_`a78O;Na}OL+1c*~QAJ7fHkRC+aGYPH zS@Uf4JkZLkxq-D=M2klIpxZ4v!^A$YLYguVs(2ZWL(QP2*{_|NO_)jvRe4NeR21ss zCwiQ&q2MW;l5`#Ex|3zvJrnj$F5x?WfCq0%e8`)&%7e;rjc8@@^}>Hbiq73y`@dIc zxbqNr*`R6oRZs*5@Gqli*0B>X=DKKP@MmggypBH-YGM_vdr|NXxl#mWfB2JXkaTKe z@bNNbh=o+(pT*3P-L$5`sN^xN)aK2pdCC-<3VYhv)aC~$$^;x$3Bk6cPBR^UruA)U zDk?}rl=ON3h;VuE-B>(HK|7(!^z670i~QBY+t7MhY8JZ+IcQ7nO;eG39g%-dWC@cK z!)2GVHHE&fM*?X{#o+_6${4jy2Bb7OO&-Y}k!amZ9XFyGViwzcAsO(kg>J>-c>^K@ zGOeKXbj-VfBWrmC+;M~H1c26mT7Gc24WkHN0-B6pK8Go9S*#;I^c>0D#>}^hm+KO= z+2B}Rz_6g|0{zHKRS+Q`Warw1+K?V#8m3G-PsOOtTCYlM6e=wTlPvxmnv}#*#xM?i zp)|SOr1yYW$lS1+oDO|M?U^f3(b>ZWKw=j4wU(t1Mu?}=Pyq-Oqk?UJyx%_2dH|et z<9CU^>elF;OOcth&=5_Mr(vUTeFQ72Ne$S>@t7ydx(@F^aoksc^cC{$2+) zU)|y0{2OS4m^UAcCkCE>9$2@^Z)Ee6+Pp2+9&WNQKiey^a&y7~R*D`n$<}33Dtn{}tpw08mQ-0zUvh00ICG0B4yeS3eU7Uk{@V0023AlZg&Z K2I>s}0000^frvx^ diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip b/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip index 600f68386baae0809a4bfb8d720ea31aa7fef8bc..c1cc97460a84a0700770d8195d9284b6ee5a0399 100644 GIT binary patch delta 30 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 LO$O}_00000ZEgC& delta 3397 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 delta 30 kcmZqVZsg_-@MdPQXJBIBW5}GTzLA%el^IA+7G=!=09w%oO#lD@ diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol index add7867e0..94125ab78 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol @@ -8,6 +8,8 @@ contract naming { uint constant MY_CONSTANT = 1; uint constant MY_other_CONSTANT = 2; + uint public immutable i_myImutableVar = 1; + uint Var_One = 1; uint varTwo = 2; @@ -55,7 +57,8 @@ contract T { uint private _myPrivateVar; uint internal _myInternalVar; uint public _myPublicVar; - + uint public s_myStateVar; + uint public myPublicVar; function test(uint _unused, uint _used) public returns(uint){ return _used;} diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip index f1e3a8ad558be3b1d4b75b1143c720adfa1d83f2..51df40aa3d627da03687b841b413540f346ead22 100644 GIT binary patch delta 3562 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 delta 3313 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 delta 30 kcmcc4b)Abhz?+%Ho`H#hk0EoW`bOT{EX+W9@@tkH0C?yKp#T5? From 6f27239d48551cdccccc2ee2e9d4da9470180fbf Mon Sep 17 00:00:00 2001 From: Tigran Avagyan Date: Mon, 11 Sep 2023 13:10:07 +0400 Subject: [PATCH 239/338] added type annotation --- slither/solc_parsing/declarations/function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index b3821388b..6097d2304 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1103,7 +1103,7 @@ class FunctionSolc(CallerContextExpression): node = self._parse_statement(statement, node, new_scope) return node - def _update_reachability(self, node: Node): + def _update_reachability(self, node: Node) -> None: if node.is_reachable: return node.set_is_reachable(True) From d4950f7212cd323b78ed691f520f2ab5e881c6b6 Mon Sep 17 00:00:00 2001 From: judowoodo <38355190+dokzai@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:00:40 -0400 Subject: [PATCH 240/338] Change return type to UnaryType instead of UnaryOperationType (#2124) * fix: return UnaryType instead of UnaryOperationType for Unary IR operation (issue #2085) --- slither/slithir/operations/unary.py | 5 ++--- slither/visitors/slithir/expression_to_slithir.py | 10 +++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/slither/slithir/operations/unary.py b/slither/slithir/operations/unary.py index c6493921d..72e7ac63a 100644 --- a/slither/slithir/operations/unary.py +++ b/slither/slithir/operations/unary.py @@ -5,7 +5,6 @@ from enum import Enum from slither.slithir.operations.lvalue import OperationWithLValue from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue from slither.slithir.exceptions import SlithIRError -from slither.core.expressions.unary_operation import UnaryOperationType from slither.core.variables.local_variable import LocalVariable from slither.slithir.variables.constant import Constant from slither.slithir.variables.local_variable import LocalIRVariable @@ -35,7 +34,7 @@ class Unary(OperationWithLValue): self, result: Union[TemporaryVariableSSA, TemporaryVariable], variable: Union[Constant, LocalIRVariable, LocalVariable], - operation_type: UnaryOperationType, + operation_type: UnaryType, ) -> None: assert is_valid_rvalue(variable) assert is_valid_lvalue(result) @@ -53,7 +52,7 @@ class Unary(OperationWithLValue): return self._variable @property - def type(self) -> UnaryOperationType: + def type(self) -> UnaryType: return self._type @property diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index a1dadbb63..9aca7f10c 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -50,6 +50,7 @@ from slither.slithir.operations import ( Member, TypeConversion, Unary, + UnaryType, Unpack, Return, SolidityCall, @@ -109,6 +110,13 @@ _binary_to_binary = { BinaryOperationType.OROR: BinaryType.OROR, } + +_unary_to_unary = { + UnaryOperationType.BANG: UnaryType.BANG, + UnaryOperationType.TILD: UnaryType.TILD, +} + + _signed_to_unsigned = { BinaryOperationType.DIVISION_SIGNED: BinaryType.DIVISION, BinaryOperationType.MODULO_SIGNED: BinaryType.MODULO, @@ -585,7 +593,7 @@ class ExpressionToSlithIR(ExpressionVisitor): operation: Operation if expression.type in [UnaryOperationType.BANG, UnaryOperationType.TILD]: lvalue = TemporaryVariable(self._node) - operation = Unary(lvalue, value, expression.type) + operation = Unary(lvalue, value, _unary_to_unary[expression.type]) operation.set_expression(expression) self._result.append(operation) set_val(expression, lvalue) From 324cbe5a5c268dbe3a3e0408b92a5b223aef23b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:45:01 -0500 Subject: [PATCH 241/338] Bump actions/checkout from 3 to 4 (#2112) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/black.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/doctor.yml | 2 +- .github/workflows/linter.yml | 2 +- .github/workflows/pip-audit.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/pylint.yml | 2 +- .github/workflows/test.yml | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 33a1666b2..6017255b2 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b59aacd66..c1a54d4d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: - os: windows-2022 type: truffle steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 with: diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4cb1adcb1..05406d0ed 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 625cafe4f..29356c0c6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v3 - uses: actions/setup-python@v4 diff --git a/.github/workflows/doctor.yml b/.github/workflows/doctor.yml index 85d79f214..0a0eb896d 100644 --- a/.github/workflows/doctor.yml +++ b/.github/workflows/doctor.yml @@ -29,7 +29,7 @@ jobs: - os: windows-2022 python: 3.8 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 0468b07f8..5415b6d1b 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index 4fbc1a3fd..a98f6ab58 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Python uses: actions/setup-python@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b90d490df..fef0a4a2e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 8c7e7bce9..7e990371f 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3754bfd7..6b911eb92 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: type: ["unit", "integration", "tool"] python: ${{ (github.event_name == 'pull_request' && fromJSON('["3.8", "3.11"]')) || fromJSON('["3.8", "3.9", "3.10", "3.11"]') }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 with: @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.8 uses: actions/setup-python@v4 with: From 7d50891e9e80964333651b9e0927626828d12a40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:45:18 -0500 Subject: [PATCH 242/338] Bump cachix/install-nix-action from 22 to 23 (#2111) Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 22 to 23. Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1a54d4d2..f04436bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v22 + uses: cachix/install-nix-action@v23 - name: Set up cachix if: matrix.type == 'dapp' From 3147396cbf1dcf7d783b40c381878ba66e4138e3 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 11 Sep 2023 16:56:45 -0500 Subject: [PATCH 243/338] fix(convert): do not convert array type to elementary for `InitArray` (#2018) fix(convert): do not convert array type to elementary for `InitArray` --- slither/slithir/convert.py | 2 +- slither/slithir/operations/init_array.py | 2 +- slither/slithir/operations/new_array.py | 2 +- tests/unit/slithir/test_ssa_generation.py | 22 +++++++++++++++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index d40715c4f..75900f176 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1857,7 +1857,7 @@ def convert_constant_types(irs: List[Operation]) -> None: if isinstance(ir.lvalue.type.type, ElementaryType): if ir.lvalue.type.type.type in ElementaryTypeInt: for r in ir.read: - if r.type.type not in ElementaryTypeInt: + if r.type.type.type not in ElementaryTypeInt: r.set_type(ElementaryType(ir.lvalue.type.type.type)) was_changed = True diff --git a/slither/slithir/operations/init_array.py b/slither/slithir/operations/init_array.py index e0754c770..ec2a63ef0 100644 --- a/slither/slithir/operations/init_array.py +++ b/slither/slithir/operations/init_array.py @@ -44,4 +44,4 @@ class InitArray(OperationWithLValue): return f"{elem}({elem.type})" init_values = convert(self.init_values) - return f"{self.lvalue}({self.lvalue.type}) = {init_values}" + return f"{self.lvalue}({self.lvalue.type}) = {init_values}" diff --git a/slither/slithir/operations/new_array.py b/slither/slithir/operations/new_array.py index 39b989459..917bb11ee 100644 --- a/slither/slithir/operations/new_array.py +++ b/slither/slithir/operations/new_array.py @@ -33,4 +33,4 @@ class NewArray(Call, OperationWithLValue): def __str__(self): args = [str(a) for a in self.arguments] lvalue = self.lvalue - return f"{lvalue}{lvalue.type}) = new {self.array_type}({','.join(args)})" + return f"{lvalue}({lvalue.type}) = new {self.array_type}({','.join(args)})" diff --git a/tests/unit/slithir/test_ssa_generation.py b/tests/unit/slithir/test_ssa_generation.py index 3c7e84973..b8772ca61 100644 --- a/tests/unit/slithir/test_ssa_generation.py +++ b/tests/unit/slithir/test_ssa_generation.py @@ -11,7 +11,7 @@ from solc_select.solc_select import valid_version as solc_valid_version from slither import Slither from slither.core.cfg.node import Node, NodeType from slither.core.declarations import Function, Contract -from slither.core.solidity_types import ArrayType +from slither.core.solidity_types import ArrayType, ElementaryType from slither.core.variables.local_variable import LocalVariable from slither.core.variables.state_variable import StateVariable from slither.slithir.operations import ( @@ -1116,3 +1116,23 @@ def test_issue_1846_ternary_in_ternary(slither_from_source): assert node.type == NodeType.IF assert node.son_true.type == NodeType.IF assert node.son_false.type == NodeType.EXPRESSION + + +def test_issue_2016(slither_from_source): + source = """ + contract Contract { + function test() external { + int[] memory a = new int[](5); + } + } + """ + with slither_from_source(source) as slither: + c = slither.get_contract_from_name("Contract")[0] + f = c.functions[0] + operations = f.slithir_operations + new_op = operations[0] + lvalue = new_op.lvalue + lvalue_type = lvalue.type + assert isinstance(lvalue_type, ArrayType) + assert lvalue_type.type == ElementaryType("int256") + assert lvalue_type.is_dynamic From f50a126f2c8b94729d4e3ed2164199811347bce1 Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Mon, 11 Sep 2023 23:57:48 +0200 Subject: [PATCH 244/338] Improve custom error parsing with constants (#2115) * Improve custom error parsing with constants --- slither/solc_parsing/declarations/contract.py | 2 +- .../solc_parsing/declarations/custom_error.py | 9 ++++- .../solc_parsing/expressions/find_variable.py | 32 ++++++++++++++++++ .../slither_compilation_unit_solc.py | 2 +- .../custom_error-0.8.4.sol-0.8.10-compact.zip | Bin 6971 -> 8466 bytes .../custom_error-0.8.4.sol-0.8.11-compact.zip | Bin 6974 -> 8469 bytes .../custom_error-0.8.4.sol-0.8.12-compact.zip | Bin 6966 -> 8467 bytes .../custom_error-0.8.4.sol-0.8.13-compact.zip | Bin 7009 -> 8524 bytes .../custom_error-0.8.4.sol-0.8.14-compact.zip | Bin 7001 -> 8519 bytes .../custom_error-0.8.4.sol-0.8.15-compact.zip | Bin 6999 -> 8520 bytes .../custom_error-0.8.4.sol-0.8.4-compact.zip | Bin 6785 -> 8166 bytes .../custom_error-0.8.4.sol-0.8.5-compact.zip | Bin 6788 -> 8233 bytes .../custom_error-0.8.4.sol-0.8.6-compact.zip | Bin 6784 -> 8240 bytes .../custom_error-0.8.4.sol-0.8.7-compact.zip | Bin 6775 -> 8203 bytes .../custom_error-0.8.4.sol-0.8.8-compact.zip | Bin 6998 -> 8458 bytes .../custom_error-0.8.4.sol-0.8.9-compact.zip | Bin 7002 -> 8477 bytes .../test_data/custom_error-0.8.4.sol | 14 ++++++++ ...custom_error-0.8.4.sol-0.8.10-compact.json | 4 ++- ...custom_error-0.8.4.sol-0.8.11-compact.json | 4 ++- ...custom_error-0.8.4.sol-0.8.12-compact.json | 4 ++- ...custom_error-0.8.4.sol-0.8.13-compact.json | 4 ++- ...custom_error-0.8.4.sol-0.8.14-compact.json | 4 ++- ...custom_error-0.8.4.sol-0.8.15-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.4-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.5-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.6-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.7-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.8-compact.json | 4 ++- .../custom_error-0.8.4.sol-0.8.9-compact.json | 4 ++- 29 files changed, 92 insertions(+), 15 deletions(-) diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index a118b1e65..e7d2745c6 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -319,7 +319,7 @@ class ContractSolc(CallerContextExpression): ce.set_contract(self._contract) ce.set_offset(custom_error["src"], self.compilation_unit) - ce_parser = CustomErrorSolc(ce, custom_error, self._slither_parser) + ce_parser = CustomErrorSolc(ce, custom_error, self, self._slither_parser) self._contract.custom_errors_as_dict[ce.name] = ce self._custom_errors_parser.append(ce_parser) diff --git a/slither/solc_parsing/declarations/custom_error.py b/slither/solc_parsing/declarations/custom_error.py index 8cd459262..34b7ca402 100644 --- a/slither/solc_parsing/declarations/custom_error.py +++ b/slither/solc_parsing/declarations/custom_error.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING, Dict, Optional from slither.core.declarations.custom_error import CustomError from slither.core.declarations.custom_error_contract import CustomErrorContract @@ -10,6 +10,7 @@ from slither.solc_parsing.variables.local_variable import LocalVariableSolc if TYPE_CHECKING: from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc from slither.core.compilation_unit import SlitherCompilationUnit + from slither.solc_parsing.declarations.contract import ContractSolc # Part of the code was copied from the function parsing @@ -21,11 +22,13 @@ class CustomErrorSolc(CallerContextExpression): self, custom_error: CustomError, custom_error_data: dict, + contract_parser: Optional["ContractSolc"], slither_parser: "SlitherCompilationUnitSolc", ) -> None: self._slither_parser: "SlitherCompilationUnitSolc" = slither_parser self._custom_error = custom_error custom_error.name = custom_error_data["name"] + self._contract_parser = contract_parser self._params_was_analyzed = False if not self._slither_parser.is_compact_ast: @@ -56,6 +59,10 @@ class CustomErrorSolc(CallerContextExpression): if params: self._parse_params(params) + @property + def contract_parser(self) -> Optional["ContractSolc"]: + return self._contract_parser + @property def is_compact_ast(self) -> bool: return self._slither_parser.is_compact_ast diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 3bbdd268e..0a1275f41 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -3,6 +3,8 @@ from typing import TYPE_CHECKING, Optional, Union, List, Tuple from slither.core.declarations import Event, Enum, Structure from slither.core.declarations.contract import Contract from slither.core.declarations.custom_error import CustomError +from slither.core.declarations.custom_error_contract import CustomErrorContract +from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.function import Function from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_top_level import FunctionTopLevel @@ -246,6 +248,7 @@ def _find_in_contract( return None +# pylint: disable=too-many-statements def _find_variable_init( caller_context: CallerContextExpression, ) -> Tuple[List[Contract], List["Function"], FileScope,]: @@ -253,6 +256,7 @@ def _find_variable_init( from slither.solc_parsing.declarations.function import FunctionSolc from slither.solc_parsing.declarations.structure_top_level import StructureTopLevelSolc from slither.solc_parsing.variables.top_level_variable import TopLevelVariableSolc + from slither.solc_parsing.declarations.custom_error import CustomErrorSolc direct_contracts: List[Contract] direct_functions_parser: List[Function] @@ -295,6 +299,24 @@ def _find_variable_init( direct_contracts = [] direct_functions_parser = [] scope = caller_context.underlying_variable.file_scope + elif isinstance(caller_context, CustomErrorSolc): + if caller_context.contract_parser: + direct_contracts = [caller_context.contract_parser.underlying_contract] + direct_functions_parser = [ + f.underlying_function + for f in caller_context.contract_parser.functions_parser + + caller_context.contract_parser.modifiers_parser + ] + else: + # Top level custom error + direct_contracts = [] + direct_functions_parser = [] + underlying_custom_error = caller_context.underlying_custom_error + if isinstance(underlying_custom_error, CustomErrorTopLevel): + scope = underlying_custom_error.file_scope + else: + assert isinstance(underlying_custom_error, CustomErrorContract) + scope = underlying_custom_error.contract.file_scope else: raise SlitherError( f"{type(caller_context)} ({caller_context} is not valid for find_variable" @@ -343,6 +365,7 @@ def find_variable( """ from slither.solc_parsing.declarations.function import FunctionSolc from slither.solc_parsing.declarations.contract import ContractSolc + from slither.solc_parsing.declarations.custom_error import CustomErrorSolc # variable are looked from the contract declarer # functions can be shadowed, but are looked from the contract instance, rather than the contract declarer @@ -394,6 +417,15 @@ def find_variable( contract_declarer = underlying_func.contract_declarer else: assert isinstance(underlying_func, FunctionTopLevel) + elif isinstance(caller_context, CustomErrorSolc): + underlying_custom_error = caller_context.underlying_custom_error + if isinstance(underlying_custom_error, CustomErrorContract): + contract = underlying_custom_error.contract + # We check for contract variables here because _find_in_contract + # will return since in this case the contract_declarer is None + for var in contract.variables: + if var_name == var.name: + return var, False ret = _find_in_contract(var_name, contract, contract_declarer, is_super, is_identifier_path) if ret: diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index ecfecb4f0..2d04a70a6 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -326,7 +326,7 @@ class SlitherCompilationUnitSolc(CallerContextExpression): custom_error = CustomErrorTopLevel(self._compilation_unit, scope) custom_error.set_offset(top_level_data["src"], self._compilation_unit) - custom_error_parser = CustomErrorSolc(custom_error, top_level_data, self) + custom_error_parser = CustomErrorSolc(custom_error, top_level_data, None, self) scope.custom_errors.add(custom_error) self._compilation_unit.custom_errors.append(custom_error) self._custom_error_parser.append(custom_error_parser) diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.10-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.10-compact.zip index fc45cb40e298c9742ce96b9c4804bbec36ccd2d4..c88ab3209e88b25e31ca209798f56b942f2ee526 100644 GIT binary patch delta 8380 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%0AV@ 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 delta 6876 zcmV<28YAVELcTT`P)h>@KL7#%4gfB{4^?bAak7XS002VL7uvBzSm9Dw?WY*}Vi0td6p*3?h;AYX7%C#T?rz&WUE!)qD z^8$vC{1%XMhBIuO{!4%QQJ;xieWLRY{Y6>;XsUrV_hzD?ovjl71S-%3o&vDiVSHK) zo;%q}V&0DqaGCcve^XSb;`zDmGx)#iQ**5$-W{4QbuSLTuMr8x@Hj#;KM(ATq;P(a z;6eWQ@GrFL^D8e~fg7BpC|WQ6FsYKIwQfa7!h_E1$5K4>gTzBxpx(sRmAms~uIE-G zOxyr{Uwg@9%7+#%j{goFOZUFEu#J%S*yF>DIW&PNa7cMvfBVx`{HZhc>5Ly8Yb)m0 zO`?sn6l=P^T@-qtgI-G;_A=v&ROo+rt86)V3>k8lMPQ}=2B(g@eJ9^DOCHx%l2r^L2#8q4fg z{iA9a{B$!We=bs_+TOW{Ct$_eAjR11-R?Z=!nUErEiW^Ho3wl?F7;JQ6qnqfTX4Vx z81Gd>Bq(+)+sV6DN+vagUh$^Yp7#TTNokM;&lPj3^mWi$70Z8Khv^y|4sG>%dQ$EZ zEx~D&com%56E$&te9&GqIZH8ujMb;VVmte@|39Nwk0&d z?=r#X5=x91Ta{x{i>KxW`xU9fNN@qcxM(Cnvdl85{j)AbZNc*L1=&p^v@C6i+=9?F z3T6GSibGfALKS{LZ}^_rwOY2NL+#lOJs?WYi<@iWDy1T<4w;P2_MxBhMU&J>## zRYqFNf421hrx+|S9fBn~NqXfnus7dGF^!RGA1<~b4ztro8k)h^8GzP19o&Q<3arw4 zp5jFk4_3oHMrvPg{tRprqebc=C;U_o3K`0avj4B~lo3d36D7Hd%^kYA99URwX2lNS zu68OAVYz0`cFs!NwgS3VSk|GUe3pj^>@aA3f4%%O@+0SM#DIdZCI?$EvQRM0lOHp! z3y8wh@u}uI)Om?ezGIiXhI#Sg9=?s>IsP;D!4S}yJUioN2hXZprCjTZ5J|B9PSDGi zHA`s+#e-FZ8`KoaB!C!}JtGz5;ja7mmw|ukC&NxwrsFoi7-L3U;H%2BED72-aO}XR zf0dKr^#o~0lScV_-a-0}m78Z`<{U@3-IQE+1npEggs<@X5_Qef2nFLlFzjBo%n!cEh0LtH3M;c_o+SnfwlTK66%`L@S5FB4TcoD_(xiRT`+Po^Pd)gDN}JzSfA7WR zJpW^%^XN--SeIygrVD4sT?`Ac1|#kc=gIx6J-!yzt69l%Ep`d;Fr@_EyHm>Flrik<5(&@5 zhwo)fc-b_SwOa({JBuy`na;_B5>Bo>|LELKp0UV^9T0QHE4mh8Qc}e!f8G6)#T(GL zFbVZK8l2!V2?GV2CKWOKrM0ZF@VK~eGbXi3(ExTyQ#2NACWLJoR8~ew~bJ4tj33f3nU5O+lBlYd1P)#e!?O4(D91N}SsARg$+d`MEOQzA*N8 zY<{3P0sFeDfiFiOb@}L|nD@|8Qu5$Vwe@WQ+h3L4DmHA=5czI|G=ncRD=UV z;Fgu&dRnQZ@8UxwUuRS>1fL{`NM?rIuv~4Lnf+t|Iy2yAK1AE(f1&?Mh|HhYWwP3d ziV%AXga^v9&f~fBlvWd^HAc%MXfAPTOo(g}(ChHc&^533y@++IH0Oc4%EP#YhCclv z!DUoB4_DQRS_E~DZgpe-BI2Ju)Y#Cks`Df9?1K%RBsiX7Yq_E7gTZhs)D}da=wgMg z9wiM}4{2m~A`UY+f8o@|9=Y1^-wwJMBCd#P*tfB-@LmFHFF=-jV4`y2%0=pMuWMRG zm$JE(=r!%ql#yF{d&%#Cm~J#f8x#Ho5~O$(b4NDr{`Hb zCro?!@h^J<<54Xle0%8mCBsr(*Ys1u5EU zSicWeh8`^4f8lKw%D&(!6Fw#U^F$xDH#EGf^@uz&K&Hs0H2#HLaS1!0=EmrGlv=?% zH`PYZ8;bx0&pwYr+np-0iQ5|i57OFpQWTRk-{8&>joyTa=VBAR$rN>M?)8l7nsW4& zEfXJlBSp5-b+KejZ7+k{H5qz5`fdw9eQc5Ge}Rku?68?h^9pXLN>WId0Lly+69z3W3y=v~tvnzS#|Ezanae~qxE0ge>$rfN zKX)U^H8f=d=#Y=_$<~=lrULL(#m-ou%lA4L9pn(|kX#pJGpFV(GTpM7lBulWbc6_r zp0}(mgHny2)=+{k&<_SevmKAv`%3DX8D(y9e}~ItJ0m>pQD-a+eg509Oy9Dm9unW!Lo{OZQS5GYY#?&#f$@XPoj+y0Goc!bGzLd_&ip;X~zqtI4=Zqn~$1tTAyWFzL ztJJs4CaX~)2T0V2nwSOVk%8`PaW5I(R5P%%*}i!@Wid=SmlS#;m36Q9>mKTaOJMa4 ze=&4&zZK~UihL!`U@EG49-DK-*om-MlsYkhMqaFh8^qxE1zX~v&|2p2Ux1R|PS?hf zZWVn!KyTQ z-tN5~-42l24?#*vrenOdu4S$xzH>Mse^QNSf8Uu!dFToj4~b5eozb+>_;`F9-7fA| zB)q^IlL(0khA4twV)Ijrit z(&8dfL*?1I%-%J;QO2(>UkRK2!Cl6wusA(zBH4`&_~{}(jBOU=Qz^}~z&h|Ae-P*z zRNl(1(`cM=z}xFVo_6rfg1ZhJx5J+)*YoMf3;(PPHdsSHRSqw5B@c3aMgjBx!OM z_kE6$Oz-?yqUJUf8R!8)Xa&43j?e;=mZ+_jsE6)o_%}j( z)hv4|P*}!+GJ7@|U!TTo6i)?q&@+Wg09+O78fTdVg8R#a|vWap4dxlsllhS@mJ5;PMwOEoT=(nHc<;fh*N4BYa z!z4QS0}vYzcV{`4E03^>+8o@sD5;K>Eryt7xKq0fd=-vODm;D^mSkR{7xEQ-7)}2N zQ;8%$44<8Yy^jlg0ntY>R`@{zaFXrqrtAI-pzU1*Co(RGt->O7Ve_WHU?-*#PyaJS82&IBJLmWw}8~^JZ*`n!74ZBr_A)Qj# zS}Mxy54Vdc%_j;Mi>`tT-gfXXNZ!j(8e$|;V-V|Zr|z=f6NW^V%O%7O3WKPx%8?0{ z(eD$lvifTXbcQxZPZ!6euU3wO{4{r@)Bkby(V1m(hiU-N4iD#1e@|gbzkD&YKg^Ov z{Ti)ekwW(g(g5xHFlOj1`a7q4D@f!l<0H--C>osgC+q zf6`WV_T~r3i*xA|QzAe7Dy+0sf%N8hhN#>lN5_u?ZZ~A@U0(_`lE2Ba73RZBQo}=j zmGCNE4HZnJPq~!sf9ZpPI`E-h#xvQayYv*@T1hUyMTOrIfVK{Zx;&DX?@=UYF6Wtw zX~%VJl;G;XEN3yr9z8A}yE?_oe#)kT{&F;HE;HXIm^qIHt@5TP!zrHi3G#h9@m=G}5h&C^!Jyg`FjTFoX?6I(NLK0S%EBe6>`tqtzSSbO8=+ zSflMiX2rPPf0^fU-d5Zwp%+3Qv{qiUv(^DqfiP{sXKw)?@zm5s1r7WwMg;bK-};RW zLz^^8;&)ZT{Tq!bum{h$1Q6s@z8VjvyfPec{<9PcZg#p3*!sT?~CIz4rnUN$7vIv z2}wSTIA@oO$~D$mi=Vv|`vp;1?)u${Y0dcXmDzt#S4-xb7y8JdHT}y1wUp#_ZvsSv49UNVVw;JA#wYb>ZxM+6_@QjWI8P- zko`P@e{6x{t_F^P)T-=Qn+%!-TbAtsqvN=PMca%sBv?rk04|E6!>z$s?NK}!(Nb~C z4@a)F74!kWW6k{AMJI!%>{%*|SSf4i5uMjF^Y_7I+koD25I+l5woLSmOXIVOKs4CS z8hQ@vXsQrN;Ane-!h8mBnG7WJ)ZF|Aozja;f7shIWu3w3hnh*RvgWKiLw;~hWXXbU zk^$*Nxe!0W*1niB@i;edJ`bBJmTV<8vL#W}?kyj1Wqp{f*Xu`_J_A@SmzkqR);zsd zNt1J%eHZbi_Hbu2-2B!*KY^n*aZy8!UVE}SNv1s0goJyt>A=wkN+~a?>QuU_A7=s{ zf35o4_LN@Vv_Y?w;hDU(FS>m4ywVYp9T7aPF^r6sxC6}*UO;f?zun-l$CtLd9f=M3 ze^z-pA{Pbv5D|7XzK^4-(wYj1Qz&+X}*2saq*L=d8xJ+Vr*D+e^TC8A|DOr z)?)^J=>QPudaXxM%#uCpdi~Dv#IAqme?|7I<#SP=n8z~%s7}0Kh(TV-(1i|-pCHHK z#6BxKR!71z02WVZvBB=@^3RMSiT{JctS2D5XzK@OQ9QhA!s7_X^{&sOkna&Qesn^4AYf6$qzaB5ye@fEK z_7^qKo!vIQE@}@DldaaZ0v6Qr7;s{7&wbk=Sq9d3XT;4MGyQu|dDrW{bk=m1t=sqj zfd8zCY{$>{oMf&B&O`XWb^`daZR2Vu#j6}Ws4YEB{>i@UZ^S1Ww4f}gwjMvd;IIHD z-k4sVmb1^v5lHu4B-?yw8-E2>f6Pw{zc|*PSWL%|U2yc8@W-N4a{?1bdS02Y*~)

2DRvIGgz_JRZCj&|dgizjpj^Z%ok z(m5aMj*F;*dZiIg#S%J1=co9aQcv~j(9QP&ExsmZboe!U40$vV_Aw8L`M7+B>Y@9e z&FrxsBYNuxbHW;)M0jeEe>Mm4O25^SlYD(Z&|@{d+>6O^>V34!p}ProbMVuQIPq_2 zNiq5YY*0~yuoustNllKoCQx7_ryT@l=Dhv~bO{Og!tV#y=ue{L5JMVD(YaU#hh z3~>v;GXjtZb12~um0Ky6Ks&Z&j7LW!Z9kD6WaEX`$zz!H3B6PBcQv0A)*;oy^c^QW zm%y5VrY1`mlONiq`c&e(A6<`6yPHf1TjGz#kpP8wtVM)7B%y z0E#NB%zt2$Xkf;T8ifYc({FUcWD{p15KZgSQOugYc_Zg!N+shRL;r|LeAH-%PmD>Y z|2vRXHU<6RSffX)g=eZOXmVl98>Ghbt!=5^1Pmc-W%;8&UM1 z=A^IGe|}@-zlD4_+{dsEdt*$_(X2!^a+@gjT+Oon#~J2gCZ(J>5j3dU(T(SgRNC06Y>Kxw zHPzCkr!wZ%<&0Ie+hCz1W3~P#e{S0)whp#S0YFrnbNT2Oz`1+h^}Ml`asujCKZzTf$q;#CH*yw z#!FlbFIeIs&~o&2_`ib24@J6^#_>zy_G-fgk*%&heYc=znk2hBU<8mr7$r{ejgQY< z_sxMXEsE!d(*fSDZ5{l1*(2+S?aoyclv38}eH`GQj*8%<3k|d$DA7o z4lzn1hVvV`h5AAAWM7!ECv}w-J;@jazqPs1HLz^sB35(x_C}I=38s3fzdKB6d%aJIKFe-Q8+#urykB!v9hd= zBB5dM;lA1(E1N6D4lIim^PA4hu&B~;*0s17fswYMY2SV|5mSP zt3t!KE;L!;o+|j#Q6TnrP&-CGniN!BszHhpF}4iHO<~_xVJsCp8_|wHS5DEf!LEq!BSe`Nv=7=0SGofd+op92u%q+jZkA!vbS4Gd;;ii{Z5SA4M6mk1Z|a_uBT@si+RkUzLuEBogrqvULvxrcC;CAT$Ex%e ztRJ?p+{82FSLkFF>46OLf5PjLDU1aJcE)4cXj2eBPP^e@lA}X4f zN9|Ll%TlfocP2GAM+00025i$%Qv diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.12-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.12-compact.zip index c72629231a104fb261b14668088a959ca8ac3876..11e9f5c76912eceddbba4a1cba15d3ddb2c1778b 100644 GIT binary patch delta 8381 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

T< zN^01@9nPwlOVZ0ie~`GKxzB;s&ZZ_zL8MQY`EluJ!slecG;TE$;HhExS9?2=G`d=A zfmx^LQdG}bVg{ee(dM;kA%>`j%Q}9aIQ~576K0})*y8{vBdLQ)?i_U<+DyFo>zpSi zqO0%dA_PG98{UYE_F?sexhc(?LN$(;We0t9|5M~$|7(AYfB3!QKkwgGa>+C;U{gNw zY)L1M6Q{fAPZ}%+z4-g|rE9l?01p=cI;gOIPN1E{)rD$`L0Qd)1n|a;LM_@CaY1)d z6Szn3yE2h+_}9{KV7R%ZC7>3LL_<-O8thNpM#m>!=MrA zHrKvcwNfsIB+z^+k;m1(*Qb;pJ;g0vk9N5Fqc1dt-h(`j#eR{>7$}uo?g61hUiBld zwhbdAS`}UtgA{QNN1ZmI)QeeIJH8qPQbRPVh~A{&~L?$5AaK+{fp_O{BN`eRD)Z~BNcMlUFlsH zOVzvle;6ILdI(d6OyI6;2Gi%;7Wi!igN#E%Y_}S*) zJ_PRUwY#m!qXw9GE{yH&N7F!#n2}MZGoPAJr65rRGPz-#*Mau-I&fupoEQ>|2QQA~~Pa)bz7NZf=Y=u>?FL=bMA zOa7L*yo5d9tK}bZ@k4{Slg~blMY)!;U1n4c^$O1z>6g4$h}btpZ!@WSu_NHZM~-TQ zP7VvS!;YEGmdm!J(-o;1$1F4JdW3(Fe?r&qUV0Agin#qhy!z2eIE72qB#J$31`d89!uSuM;y&bxWyov6n%Jh8&>zy-C(dM&2$YyB9LFEjF2 z>7qIDa;<19WDJcXN;?xIiv>LFms9=5$A)Pfbx5>jJfDw2az$;Hu~3<%dUo9BAferN zJtuYWhV+vTxI@Q6#(0#ZYM_*ZZrGl=dzXk=^6VmpLtwy(F4$1LG|AiEe+&hh{_1)l z$+?c6iSculk-Wqn6}-WPI~DJ}QZe?sjP*-5MM;+358&iIU{HINmsG;Nv8}Xd@^7o| zN_$hpGwq;#lR+#o+|4Y_WJl=_nEd-SVJLHQRxjw>Ok2-TD=dNV1zyA*JwSQi6*4)) zm~KUSa@+Q%A?jIW2(IZne^kou%9PfZl4;?$mg9`ixoh4G>EXZPz?hE^Bay4GsJ*0b zB;^R;AJ?r7vuMZ;#H^Tc?wdQuwUby0l;aJ@vYR@NfU1HZ6HiBN|8i>yBoNxrK+afH z_O6}-3g7D~;-iALDL|QS*t!DQ14x`g|MMc7rcg@(0zU&k00ICG5CErxC09C&OC4Px T003kH0h8kzO$MbP00000_D@JE delta 6874 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�^)Dj4cI?#gjQfSIgHf zBH5nXgUS%^M)1koqrpfUdwBs1$fR@0>zhzwt!R#*4~e=0<291MPZ)mYVT{2COpO{S^e|1}r;im8%Xw8U3VOwQ#Or0sWw=a|pJK`)$`E zI(oK=1+v?DoHQ#-r^RR#mYq|nSEyG{I^ib8qDe@k$waaOe{4pye-VFt&Lo^MUBUG# zNBzVJs6+VF362W}&^a7C+WjGct&r4vD!C>1a-2YSq--f9t{}lUD&C~I2uwbmEgW65 zoZ5w?;+*PK{!uhN2MzEZ)BI62+jj1_m#>h4Y;;Qo`#B()^Nyf*Z@X-XRZ1n16Kf7J z@KSh+04-S$H0Y|lQsgbTwF&|!M4CzZPB-qbK`P41Wt?Y(V3vpxG|5KY^8Lo9NQWxA z5YoXtX|2rZ4UE&v{Rr?9P)h*%WA`5;XO^BMpE F000Z;YR3Qo diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.14-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.14-compact.zip index e36f5b94e5e637d30c007a838d1973a3a475b88e..fcb0fd1f45962d39dcf8be4b010550efca795f17 100644 GIT binary patch delta 8433 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 T002w_0h0zBO$ON@00000;gfrz delta 6903 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 diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.15-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.15-compact.zip index 1023ab1d451e7a788da134fe9f6f28db15da28bc..2050e256abc724b188f0f6edbd200ca617362366 100644 GIT binary patch delta 8434 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 diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.4-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.4-compact.zip index 5ecf2b037a0580e075113579ca1b9152131a8eb1..d31650594ca8b604757ce2c0b3d26b27eb30d257 100644 GIT binary patch delta 8082 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 delta 6699 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�_+*>%wDr&Zv96WNyp+$P{uiTV<1k!o zJR#`?jtm0SJJSI&Z7(=agR)w#Xn*V^+8nbZm-~r?4d>@V58i3N@Rm1v6*g7u+{?{6 z_VSTJ3DQ?{PX7QxXA|i<;m22c`p*+dT?8+NTy-p@wt=ukKbeGDyGmt$UrZx63zOE! zVUnIk^JTg}>Z>}A?RRQUu=nyd0Ux}QMd%$x zn3}!46R~4|LR+7DyYk+D@X@^Tc@pI&!^u~qk9Gi@LoRtS%+IDojp+^^y~$FUj2^!) zK)r3nCPIu%ubypPZ4&PPL+I&QFV#M6DujQ~hZTAw9RJ}@ov$|DbN4tdH?gqW6@#G1 z20c-cv`v!QdYRC_U>9cDC$2GInIBx9mamCjuAEyEKSH9iO-!DD*vtvZuZ)cxYp%i} z6EYF`kKC>VyB(1G9*jv@lqmv0!AwkcjSmMkzzU9caH4_Y9XW1Z&9`$0ZJDBP_16If zZgUyM%K=Qq3@KezCf%tTOHF%mQJCbxj*%{V0*TlRkz?{u=ufTd0%mWhc&|iM#lViH z=JQ3PnBIYWJt3igf;PbnP9?ntq1IhL7P8pY6m01?n8yxw!~}ADWO&k2mW?laZuO%;P|dV4e#6{@=91ZO zes)By`SsR+?P>2;@o9{Vvq|uXa5}dtrZgO=p^}von%%C(fS6EN{cUw6yb8mnwRB8z z+2zNcEoKvubb&Pzt6KASlvSI%bdn@=N4oG4(fB2=^N z(RIRqAbFU>+|vfFp^aRjaV|yK;B<&l)>VdW=6beu(M|rEw{;ub=dYyPtXVSC8Tb#VV=l6#Vh?#K2^wNPS`2L@iiulSt;R-3&?J_)}GjEu+^#K)bUMGKpBMeUL# z4cSRuvjaqC(dhdU<#0?-EUm(86ktz>Y!%Mna=X)dU?nK4?=mfWtlG3!1k3R101uKm z8@TuS*2AvM+wo=d3BCG4r?*J|BNO|7fn#p?l%NeGxHgk{y!oSVPt=vo72K?HkpWAw zqBI8cZVVW{p_1~1%7df%&SqU(T)4J}__9%?x-?8{l2VCKTbpp(F3^K^G`$>yhuKzBK^Z9xFU4sXIoTcXj^9?M}}Qdvi?SnC>8+;-=jXtfnH!LQ&XP+}Cz z^b*woE{O?TI9=IlzD0`AZJ|(#wuU-FYKk&HqkSU%9knT6)|LtWYykso6zmtHLrWmygAw zXt0WhHkuyBALbJ-d7e3c6S!20b$?8EDN#|)rdG2yY*7}2@FN_?kJw?W)!s*S#vWUx zZ&wl`zE;`KJ5fdTB6I#PPG6vDvcJsyPXqZ&S3&VQTD5Jy(_ivHb_|le|M$9|?odks z0zU&k00ICG03E*%Rn?6<(#shD0Nuv`04e|g00000000000Du9Lq8~m66B+;j007FA B_9_4X diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.5-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.5-compact.zip index 357554c09b7ecd8eb677f0f235c36a6942571751..a5551ea0946a88a0436d0630601a326dd204ef28 100644 GIT binary patch delta 8150 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 delta 6699 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 DLBQsn delta 6706 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 I8UO$Q0PtJ)_W%F@ diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.7-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.7-compact.zip index 51828bce7f7ce019e01f805587051bafd85e344e..95f411a302a4cd64fad7edab9931aed31b20412a 100644 GIT binary patch delta 8113 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 LP6nMH00000l}Ed+ delta 6673 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 delta 6900 zcmV@KL7#%4ges(4^`!zK%bx*006(s0FfD3e=;Aj+Jwj4=zZs9 z#Q1EOe;UGIJ<;{TF>VL7uvBzSm9Dw?WY*}Vi0td6p*3?h;AYX7%C#T?rz&WUE!)qD z^8$vC{1%XMhBIuO{!4%QQJoSvlnW{R7ueiuZKocgO~P_I+d}B&P44` z*D=#TE++nOhKK9;e??Xef<@BL#Af3Kq5uSe=ViO3Xp>P3ewYO!LepOErKYkd>7?1I zl=bJOc5wFEtpA(Lc#^Sf)NUSi173cQipiLSNM)|MM zZ)Lx(BtFw^f+l9HFi1^NOWGlh-)SDn_%J-A3j$JoV5#j^e?i>e!MD1~h=o@*2pq0f z@p??d=FM{U%BT7h4te6M@5W{SxPAdM`iWKPDn_O{oOj76Zo3ud`uR2;YVDCBo%3vB zmmHfa36s{R5dy`C5+GQXIXElq3|hT}&>cgEc>esZ#@(kYAWd3=+TVqR-c$mTeMmm4 zTw}Q8`O5>0f0a^3xsDt}rx+lAVaYc-+j&&4<5&0-X_sQ9YXxL8h2mKX{q%%(`^B`8 z9qBPQ6E#t;z-56Dq^0h1`HiPH&sSMO8>Z{B&$4Qad}SgG=tGMNIA?nx4zBpp3j-^%I}9wBIQw2qiBxp!O~`K-J*n);=&!B4adb6;~gFb zdl}@+s^4Z?r_KyLdg&H0Ou#0|J_yas=LZ6D`8Im$Uw_i1mXk(Gl&24(Ck5EZe%xf9 z*ag#>e?T&_!=l6?W4ugl(j9Mb>W&Vz_tfxl_#*J*WtBH`gn2)6Kfs8_p-MYYOSo$1 zw+g!jSLU6Cp*Tpw7jKz+71=Jvu?@#$q&Kk-x%iN~_JyUWfeEjwMDvyxd2ER8Uaf+l zht}8{n{T;&W~-h0>cEbm`w%W=Aa|7>_fu!jf3e_-I)x(}yn*<6;h{~v|1}wlO7@V= z!QWhIvxtUsV$V3;9zaW}254^y8>^t+rNbtottzNdkGOGtb~hl#GVr$i)q;y*h?=sY zPPT6%w(CjPHVW@}G47PUC4L3t2yn|W4n{P(u%g6d^k+hrYBT(>>$&S^%JaIb!Qn=*sgT3oNCWZ2dJY}^6F`?;bRTOEeX zwV1N@otXz0fYmE_P_(;2n1IgvjRRaYe*rJz*G;mTfhqCY(scq-WK8&tJ)23HhQR$* z{;NPx;Hxo%_pE=}3cB0Xd@}reS1;?-z2+^vPe9@p0^5#wK$&;JkiffQgXn@6bQ_9A z`=((WcV+fk#r%=rOEPM-)1|UeYb6Cy|3)ft+TcUj`;DtB^!J(-OHj6Ldgmi*e--%z zMLsbbP3xw|=et^~3Al``5c{`BV2czV|C2{K$1+&4?#{XO?KI2};#;^e@Fbkht5^Nl z=aI@ToK)Fg`;)9aq~m2B#-jif1HH9RIr^MAosfk~PtslE$z$>7R1a<| z*7)2=QNnfyw#sBIx3o`3T@vJ!U!JPcQs3(x!DsqNmb%0A+?KlYgMz|IP=D`l4Sf^a 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 diff --git a/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.9-compact.zip b/tests/e2e/solc_parsing/test_data/compile/custom_error-0.8.4.sol-0.8.9-compact.zip index 17e75201852bd073a1beed505d96dd2903106cfb..f407956184a49c87c554bf5c509821b5b6f22d15 100644 GIT binary patch delta 8391 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 delta 6904 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 diff --git a/tests/e2e/solc_parsing/test_data/custom_error-0.8.4.sol b/tests/e2e/solc_parsing/test_data/custom_error-0.8.4.sol index 4e1e388fb..e638b8d41 100644 --- a/tests/e2e/solc_parsing/test_data/custom_error-0.8.4.sol +++ b/tests/e2e/solc_parsing/test_data/custom_error-0.8.4.sol @@ -8,13 +8,19 @@ struct St{ uint v; } +uint256 constant MAX = 5; + error ErrorSimple(); error ErrorWithArgs(uint, uint); error ErrorWithStruct(St s); +error ErrorWithConst(uint256[MAX]); contract VendingMachine is I { + uint256 constant CMAX = 10; + error CErrorWithConst(uint256[CMAX]); + function err0() public { revert ErrorSimple(); } @@ -32,6 +38,14 @@ contract VendingMachine is I { function err4() public { revert ErrorWithEnum(SomeEnum.ONE); } + function err5(uint256[MAX] calldata a) public { + revert ErrorWithConst(a); + } + function err6(uint256[CMAX] calldata a) public { + revert CErrorWithConst(a); + } + + } contract A{ diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.10-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.10-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.10-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.11-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.11-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.12-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.12-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.13-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.13-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.14-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.14-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.15-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.15-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.4-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.4-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.4-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.4-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.5-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.5-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.5-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.5-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.6-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.6-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.6-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.6-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.7-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.7-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.7-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.7-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.8-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.8-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" diff --git a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.9-compact.json b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.9-compact.json index 9020c8d52..0707fa149 100644 --- a/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.9-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/custom_error-0.8.4.sol-0.8.9-compact.json @@ -5,7 +5,9 @@ "err1()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err2()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "err3()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "err4()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err5(uint256[5])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "err6(uint256[10])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" }, "A": { "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" From f1f4e5b4a5539e29cf2a52771753b719ec328253 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Tue, 12 Sep 2023 00:01:33 +0200 Subject: [PATCH 245/338] Add detailed assert info for echidna (#2105) Add assert span info to echidna printer --- slither/printers/guidance/echidna.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 25e0968cd..73a9c5619 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -126,15 +126,24 @@ def _extract_constant_functions(slither: SlitherCore) -> Dict[str, List[str]]: return ret -def _extract_assert(slither: SlitherCore) -> Dict[str, List[str]]: - ret: Dict[str, List[str]] = {} +def _extract_assert(slither: SlitherCore) -> Dict[str, Dict[str, List[Dict]]]: + """ + Return the list of contract -> function name -> List(source mapping of the assert)) + + Args: + slither: + + Returns: + + """ + ret: Dict[str, Dict[str, List[Dict]]] = {} for contract in slither.contracts: - functions_using_assert = [] + functions_using_assert: Dict[str, List[Dict]] = defaultdict(list) for f in contract.functions_entry_points: - for v in f.all_solidity_calls(): - if v == SolidityFunction("assert(bool)"): - functions_using_assert.append(_get_name(f)) - break + for node in f.all_nodes(): + if SolidityFunction("assert(bool)") in node.solidity_calls and node.source_mapping: + func_name = _get_name(f) + functions_using_assert[func_name].append(node.source_mapping.to_json()) if functions_using_assert: ret[contract.name] = functions_using_assert return ret From cc9e65fe13f7219cb5e24799287194c0da85b7e4 Mon Sep 17 00:00:00 2001 From: Kevin Clancy Date: Tue, 12 Sep 2023 06:44:48 -0700 Subject: [PATCH 246/338] fix: reorder named arguments to match declaration order (#1949) Store names list in call operations and expressions. Reorder named arguments to match declaration order. A function call with explicitly named parameters, of the form f({argName1: arg1, ...}), may list the parameters in an order different from that of the function's declaration. In this case, the IR should reorder the arguments to match the function declaration order before generating IR. This PR implements named argument reordering for the following forms of function calls: - struct constructors (most important) - static internal calls For the following forms of function calls, the order of the declaration arguments is not directly available during IR generation, so the PR did not implement reordering for them: - external calls (HighLevelCall) - library calls - event calls The get_declared_param_names function returns None for these unimplemented call forms. --- slither/core/expressions/call_expression.py | 37 +++++++- slither/slithir/convert.py | 91 ++++++++++++++++++- slither/slithir/operations/call.py | 18 +++- slither/slithir/operations/high_level_call.py | 9 +- slither/slithir/operations/internal_call.py | 10 +- slither/slithir/operations/new_contract.py | 13 ++- slither/slithir/operations/new_structure.py | 11 ++- slither/slithir/tmp_operations/tmp_call.py | 19 +++- slither/slithir/utils/ssa.py | 15 ++- .../expressions/expression_parsing.py | 3 +- .../visitors/slithir/expression_to_slithir.py | 8 +- tests/unit/slithir/test_argument_reorder.py | 65 +++++++++++++ .../test_internal_call_reorder.sol | 8 ++ .../test_struct_constructor.sol | 11 +++ 14 files changed, 298 insertions(+), 20 deletions(-) create mode 100644 tests/unit/slithir/test_argument_reorder.py create mode 100644 tests/unit/slithir/test_data/argument_reorder/test_internal_call_reorder.sol create mode 100644 tests/unit/slithir/test_data/argument_reorder/test_struct_constructor.sol diff --git a/slither/core/expressions/call_expression.py b/slither/core/expressions/call_expression.py index 6708dda7e..ec2b2cfce 100644 --- a/slither/core/expressions/call_expression.py +++ b/slither/core/expressions/call_expression.py @@ -4,12 +4,32 @@ from slither.core.expressions.expression import Expression class CallExpression(Expression): # pylint: disable=too-many-instance-attributes - def __init__(self, called: Expression, arguments: List[Any], type_call: str) -> None: + def __init__( + self, + called: Expression, + arguments: List[Any], + type_call: str, + names: Optional[List[str]] = None, + ) -> None: + """ + #### Parameters + called - + The expression denoting the function to be called + arguments - + List of argument expressions + type_call - + A string formatting of the called function's return type + names - + For calls with named fields, list fields in call order. + For calls without named fields, None. + """ assert isinstance(called, Expression) + assert (names is None) or isinstance(names, list) super().__init__() self._called: Expression = called self._arguments: List[Expression] = arguments self._type_call: str = type_call + self._names: Optional[List[str]] = names # gas and value are only available if the syntax is {gas: , value: } # For the .gas().value(), the member are considered as function call # And converted later to the correct info (convert.py) @@ -17,6 +37,14 @@ class CallExpression(Expression): # pylint: disable=too-many-instance-attribute self._value: Optional[Expression] = None self._salt: Optional[Expression] = None + @property + def names(self) -> Optional[List[str]]: + """ + For calls with named fields, list fields in call order. + For calls without named fields, None. + """ + return self._names + @property def call_value(self) -> Optional[Expression]: return self._value @@ -62,4 +90,9 @@ class CallExpression(Expression): # pylint: disable=too-many-instance-attribute if gas or value or salt: options = [gas, value, salt] txt += "{" + ",".join([o for o in options if o != ""]) + "}" - return txt + "(" + ",".join([str(a) for a in self._arguments]) + ")" + args = ( + "{" + ",".join([f"{n}:{str(a)}" for (a, n) in zip(self._arguments, self._names)]) + "}" + if self._names is not None + else ",".join([str(a) for a in self._arguments]) + ) + return txt + "(" + args + ")" diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 75900f176..4cb508fae 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -385,6 +385,70 @@ def integrate_value_gas(result: List[Operation]) -> List[Operation]: ################################################################################### +def get_declared_param_names( + ins: Union[ + NewStructure, + NewContract, + InternalCall, + LibraryCall, + HighLevelCall, + InternalDynamicCall, + EventCall, + ] +) -> Optional[List[str]]: + """ + Given a call operation, return the list of parameter names, in the order + listed in the function declaration. + #### Parameters + ins - + The call instruction + #### Possible Returns + List[str] - + A list of the parameters in declaration order + None - + Workaround: Unable to obtain list of parameters in declaration order + """ + if isinstance(ins, NewStructure): + return [x.name for x in ins.structure.elems_ordered if not isinstance(x.type, MappingType)] + if isinstance(ins, (InternalCall, LibraryCall, HighLevelCall)): + if isinstance(ins.function, Function): + return [p.name for p in ins.function.parameters] + return None + if isinstance(ins, InternalDynamicCall): + return [p.name for p in ins.function_type.params] + + assert isinstance(ins, (EventCall, NewContract)) + return None + + +def reorder_arguments( + args: List[Variable], call_names: List[str], decl_names: List[str] +) -> List[Variable]: + """ + Reorder named struct constructor arguments so that they match struct declaration ordering rather + than call ordering + E.g. for `struct S { int x; int y; }` we reorder `S({y : 2, x : 3})` to `S(3, 2)` + #### Parameters + args - + Arguments to constructor call, in call order + names - + Parameter names in call order + decl_names - + Parameter names in declaration order + #### Returns + Reordered arguments to constructor call, now in declaration order + """ + assert len(args) == len(call_names) + assert len(call_names) == len(decl_names) + + args_ret = [] + for n in decl_names: + ind = call_names.index(n) + args_ret.append(args[ind]) + + return args_ret + + def propagate_type_and_convert_call(result: List[Operation], node: "Node") -> List[Operation]: """ Propagate the types variables and convert tmp call to real call operation @@ -434,6 +498,23 @@ def propagate_type_and_convert_call(result: List[Operation], node: "Node") -> Li if ins.call_id in calls_gas and isinstance(ins, (HighLevelCall, InternalDynamicCall)): ins.call_gas = calls_gas[ins.call_id] + if isinstance(ins, Call) and (ins.names is not None): + assert isinstance( + ins, + ( + NewStructure, + NewContract, + InternalCall, + LibraryCall, + HighLevelCall, + InternalDynamicCall, + EventCall, + ), + ) + decl_param_names = get_declared_param_names(ins) + if decl_param_names is not None: + call_data = reorder_arguments(call_data, ins.names, decl_param_names) + if isinstance(ins, (Call, NewContract, NewStructure)): # We might have stored some arguments for libraries if ins.arguments: @@ -855,7 +936,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, if isinstance(ins.ori.variable_left, Contract): st = ins.ori.variable_left.get_structure_from_name(ins.ori.variable_right) if st: - op = NewStructure(st, ins.lvalue) + op = NewStructure(st, ins.lvalue, names=ins.names) op.set_expression(ins.expression) op.call_id = ins.call_id return op @@ -892,6 +973,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, ins.nbr_arguments, ins.lvalue, ins.type_call, + names=ins.names, ) libcall.set_expression(ins.expression) libcall.call_id = ins.call_id @@ -950,6 +1032,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, len(lib_func.parameters), ins.lvalue, "d", + names=ins.names, ) lib_call.set_expression(ins.expression) lib_call.set_node(ins.node) @@ -1031,6 +1114,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, ins.nbr_arguments, ins.lvalue, ins.type_call, + names=ins.names, ) msgcall.call_id = ins.call_id @@ -1082,7 +1166,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, return n if isinstance(ins.called, Structure): - op = NewStructure(ins.called, ins.lvalue) + op = NewStructure(ins.called, ins.lvalue, names=ins.names) op.set_expression(ins.expression) op.call_id = ins.call_id op.set_expression(ins.expression) @@ -1106,7 +1190,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, if len(ins.called.constructor.parameters) != ins.nbr_arguments: return Nop() internalcall = InternalCall( - ins.called.constructor, ins.nbr_arguments, ins.lvalue, ins.type_call + ins.called.constructor, ins.nbr_arguments, ins.lvalue, ins.type_call, ins.names ) internalcall.call_id = ins.call_id internalcall.set_expression(ins.expression) @@ -1440,6 +1524,7 @@ def look_for_library_or_top_level( ir.nbr_arguments, ir.lvalue, ir.type_call, + names=ir.names, ) lib_call.set_expression(ir.expression) lib_call.set_node(ir.node) diff --git a/slither/slithir/operations/call.py b/slither/slithir/operations/call.py index 816c56e1d..a4f9f6d72 100644 --- a/slither/slithir/operations/call.py +++ b/slither/slithir/operations/call.py @@ -6,9 +6,25 @@ from slither.slithir.operations.operation import Operation class Call(Operation): - def __init__(self) -> None: + def __init__(self, names: Optional[List[str]] = None) -> None: + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ + assert (names is None) or isinstance(names, list) super().__init__() self._arguments: List[Variable] = [] + self._names = names + + @property + def names(self) -> Optional[List[str]]: + """ + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ + return self._names @property def arguments(self) -> List[Variable]: diff --git a/slither/slithir/operations/high_level_call.py b/slither/slithir/operations/high_level_call.py index 5d654fc80..c60443f19 100644 --- a/slither/slithir/operations/high_level_call.py +++ b/slither/slithir/operations/high_level_call.py @@ -28,11 +28,18 @@ class HighLevelCall(Call, OperationWithLValue): nbr_arguments: int, result: Optional[Union[TemporaryVariable, TupleVariable, TemporaryVariableSSA]], type_call: str, + names: Optional[List[str]] = None, ) -> None: + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ assert isinstance(function_name, Constant) assert is_valid_lvalue(result) or result is None self._check_destination(destination) - super().__init__() + super().__init__(names=names) # Contract is only possible for library call, which inherits from highlevelcall self._destination: Union[Variable, SolidityVariable, Contract] = destination # type: ignore self._function_name = function_name diff --git a/slither/slithir/operations/internal_call.py b/slither/slithir/operations/internal_call.py index 1983b885f..06e75136e 100644 --- a/slither/slithir/operations/internal_call.py +++ b/slither/slithir/operations/internal_call.py @@ -20,8 +20,16 @@ class InternalCall(Call, OperationWithLValue): # pylint: disable=too-many-insta Union[TupleVariableSSA, TemporaryVariableSSA, TupleVariable, TemporaryVariable] ], type_call: str, + names: Optional[List[str]] = None, ) -> None: - super().__init__() + # pylint: disable=too-many-arguments + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ + super().__init__(names=names) self._contract_name = "" if isinstance(function, Function): self._function: Optional[Function] = function diff --git a/slither/slithir/operations/new_contract.py b/slither/slithir/operations/new_contract.py index 518a097cb..9ed00b1ac 100644 --- a/slither/slithir/operations/new_contract.py +++ b/slither/slithir/operations/new_contract.py @@ -12,11 +12,20 @@ from slither.slithir.variables.temporary_ssa import TemporaryVariableSSA class NewContract(Call, OperationWithLValue): # pylint: disable=too-many-instance-attributes def __init__( - self, contract_name: Constant, lvalue: Union[TemporaryVariableSSA, TemporaryVariable] + self, + contract_name: Constant, + lvalue: Union[TemporaryVariableSSA, TemporaryVariable], + names: Optional[List[str]] = None, ) -> None: + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ assert isinstance(contract_name, Constant) assert is_valid_lvalue(lvalue) - super().__init__() + super().__init__(names=names) self._contract_name = contract_name # todo create analyze to add the contract instance self._lvalue = lvalue diff --git a/slither/slithir/operations/new_structure.py b/slither/slithir/operations/new_structure.py index c50cd6a3e..2aaba28ff 100644 --- a/slither/slithir/operations/new_structure.py +++ b/slither/slithir/operations/new_structure.py @@ -1,4 +1,4 @@ -from typing import List, Union +from typing import List, Optional, Union from slither.slithir.operations.call import Call from slither.slithir.operations.lvalue import OperationWithLValue @@ -17,8 +17,15 @@ class NewStructure(Call, OperationWithLValue): self, structure: StructureContract, lvalue: Union[TemporaryVariableSSA, TemporaryVariable], + names: Optional[List[str]] = None, ) -> None: - super().__init__() + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ + super().__init__(names=names) assert isinstance(structure, Structure) assert is_valid_lvalue(lvalue) self._structure = structure diff --git a/slither/slithir/tmp_operations/tmp_call.py b/slither/slithir/tmp_operations/tmp_call.py index 2137ebd81..a7bd614c7 100644 --- a/slither/slithir/tmp_operations/tmp_call.py +++ b/slither/slithir/tmp_operations/tmp_call.py @@ -1,4 +1,4 @@ -from typing import Optional, Union +from typing import List, Optional, Union from slither.core.declarations import ( Event, @@ -25,7 +25,15 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu nbr_arguments: int, result: Union[TupleVariable, TemporaryVariable], type_call: str, + names: Optional[List[str]] = None, ) -> None: + # pylint: disable=too-many-arguments + """ + #### Parameters + names - + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ assert isinstance( called, ( @@ -42,6 +50,7 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu self._called = called self._nbr_arguments = nbr_arguments self._type_call = type_call + self._names = names self._lvalue = result self._ori = None # self._callid = None @@ -49,6 +58,14 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu self._value = None self._salt = None + @property + def names(self) -> Optional[List[str]]: + """ + For calls of the form f({argName1 : arg1, ...}), the names of parameters listed in call order. + Otherwise, None. + """ + return self._names + @property def call_value(self): return self._value diff --git a/slither/slithir/utils/ssa.py b/slither/slithir/utils/ssa.py index 4c958798b..ef908820e 100644 --- a/slither/slithir/utils/ssa.py +++ b/slither/slithir/utils/ssa.py @@ -735,12 +735,17 @@ def copy_ir(ir: Operation, *instances) -> Operation: destination = get_variable(ir, lambda x: x.destination, *instances) function_name = ir.function_name nbr_arguments = ir.nbr_arguments + names = ir.names lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call if isinstance(ir, LibraryCall): - new_ir = LibraryCall(destination, function_name, nbr_arguments, lvalue, type_call) + new_ir = LibraryCall( + destination, function_name, nbr_arguments, lvalue, type_call, names=names + ) else: - new_ir = HighLevelCall(destination, function_name, nbr_arguments, lvalue, type_call) + new_ir = HighLevelCall( + destination, function_name, nbr_arguments, lvalue, type_call, names=names + ) new_ir.call_id = ir.call_id new_ir.call_value = get_variable(ir, lambda x: x.call_value, *instances) new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances) @@ -761,7 +766,8 @@ def copy_ir(ir: Operation, *instances) -> Operation: nbr_arguments = ir.nbr_arguments lvalue = get_variable(ir, lambda x: x.lvalue, *instances) type_call = ir.type_call - new_ir = InternalCall(function, nbr_arguments, lvalue, type_call) + names = ir.names + new_ir = InternalCall(function, nbr_arguments, lvalue, type_call, names=names) new_ir.arguments = get_arguments(ir, *instances) return new_ir if isinstance(ir, InternalDynamicCall): @@ -811,7 +817,8 @@ def copy_ir(ir: Operation, *instances) -> Operation: if isinstance(ir, NewStructure): structure = ir.structure lvalue = get_variable(ir, lambda x: x.lvalue, *instances) - new_ir = NewStructure(structure, lvalue) + names = ir.names + new_ir = NewStructure(structure, lvalue, names=names) new_ir.arguments = get_arguments(ir, *instances) return new_ir if isinstance(ir, Nop): diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index a0bce044c..74ff593c7 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -179,7 +179,8 @@ def parse_call( sp = SuperCallExpression(called, arguments, type_return) sp.set_offset(expression["src"], caller_context.compilation_unit) return sp - call_expression = CallExpression(called, arguments, type_return) + names = expression["names"] if "names" in expression and len(expression["names"]) > 0 else None + call_expression = CallExpression(called, arguments, type_return, names=names) call_expression.set_offset(src, caller_context.compilation_unit) # Only available if the syntax {gas:, value:} was used diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 9aca7f10c..534b157c3 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -312,7 +312,9 @@ class ExpressionToSlithIR(ExpressionVisitor): val = TupleVariable(self._node) else: val = TemporaryVariable(self._node) - internal_call = InternalCall(called, len(args), val, expression.type_call) + internal_call = InternalCall( + called, len(args), val, expression.type_call, names=expression.names + ) internal_call.set_expression(expression) self._result.append(internal_call) set_val(expression, val) @@ -381,7 +383,9 @@ class ExpressionToSlithIR(ExpressionVisitor): else: val = TemporaryVariable(self._node) - message_call = TmpCall(called, len(args), val, expression.type_call) + message_call = TmpCall( + called, len(args), val, expression.type_call, names=expression.names + ) message_call.set_expression(expression) # Gas/value are only accessible here if the syntax {gas: , value: } # Is used over .gas().value() diff --git a/tests/unit/slithir/test_argument_reorder.py b/tests/unit/slithir/test_argument_reorder.py new file mode 100644 index 000000000..12f5bd7f2 --- /dev/null +++ b/tests/unit/slithir/test_argument_reorder.py @@ -0,0 +1,65 @@ +from pathlib import Path + +from slither import Slither +from slither.slithir.operations.internal_call import InternalCall +from slither.slithir.operations.new_structure import NewStructure +from slither.slithir.variables.constant import Constant + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" +ARG_REORDER_TEST_ROOT = Path(TEST_DATA_DIR, "argument_reorder") + + +def test_struct_constructor_reorder(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.15") + slither = Slither( + Path(ARG_REORDER_TEST_ROOT, "test_struct_constructor.sol").as_posix(), solc=solc_path + ) + + operations = slither.contracts[0].functions[0].slithir_operations + constructor_calls = [x for x in operations if isinstance(x, NewStructure)] + assert len(constructor_calls) == 2 + + # Arguments to first call are 2, 3 + assert ( + isinstance(constructor_calls[0].arguments[0], Constant) + and constructor_calls[0].arguments[0].value == 2 + ) + assert ( + isinstance(constructor_calls[0].arguments[1], Constant) + and constructor_calls[0].arguments[1].value == 3 + ) + + # Arguments to second call are 5, 4 (note the reversed order) + assert ( + isinstance(constructor_calls[1].arguments[0], Constant) + and constructor_calls[1].arguments[0].value == 5 + ) + assert ( + isinstance(constructor_calls[1].arguments[1], Constant) + and constructor_calls[1].arguments[1].value == 4 + ) + + +def test_internal_call_reorder(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.15") + slither = Slither( + Path(ARG_REORDER_TEST_ROOT, "test_internal_call_reorder.sol").as_posix(), solc=solc_path + ) + + operations = slither.contracts[0].functions[1].slithir_operations + internal_calls = [x for x in operations if isinstance(x, InternalCall)] + assert len(internal_calls) == 1 + + # Arguments to call are 3, true, 5 + assert ( + isinstance(internal_calls[0].arguments[0], Constant) + and internal_calls[0].arguments[0].value == 3 + ) + assert ( + isinstance(internal_calls[0].arguments[1], Constant) + and internal_calls[0].arguments[1].value is True + ) + assert ( + isinstance(internal_calls[0].arguments[2], Constant) + and internal_calls[0].arguments[2].value == 5 + ) diff --git a/tests/unit/slithir/test_data/argument_reorder/test_internal_call_reorder.sol b/tests/unit/slithir/test_data/argument_reorder/test_internal_call_reorder.sol new file mode 100644 index 000000000..4c4f658da --- /dev/null +++ b/tests/unit/slithir/test_data/argument_reorder/test_internal_call_reorder.sol @@ -0,0 +1,8 @@ +contract InternalCallReorderTest { + function internal_func(uint256 a, bool b, uint256 c) internal { + } + + function caller() external { + internal_func({a: 3, c: 5, b: true}); + } +} diff --git a/tests/unit/slithir/test_data/argument_reorder/test_struct_constructor.sol b/tests/unit/slithir/test_data/argument_reorder/test_struct_constructor.sol new file mode 100644 index 000000000..05dbb50b0 --- /dev/null +++ b/tests/unit/slithir/test_data/argument_reorder/test_struct_constructor.sol @@ -0,0 +1,11 @@ +contract StructConstructorTest { + struct S { + int x; + int y; + } + + function test() external { + S memory p = S({x: 2, y: 3}); + S memory q = S({y: 4, x: 5}); + } +} From cd000a4eea72f2d5ff33dd919faab8ba59508d5f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 13 Sep 2023 09:10:31 -0500 Subject: [PATCH 247/338] add tests --- .../name_resolution/shadowing_compact.sol | 8 ++++ .../shadowing_legacy_post_0_5_0.sol | 8 ++++ .../shadowing_legacy_pre_0_5_0.sol | 8 ++++ tests/unit/core/test_name_resolution.py | 45 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 tests/unit/core/test_data/name_resolution/shadowing_compact.sol create mode 100644 tests/unit/core/test_data/name_resolution/shadowing_legacy_post_0_5_0.sol create mode 100644 tests/unit/core/test_data/name_resolution/shadowing_legacy_pre_0_5_0.sol create mode 100644 tests/unit/core/test_name_resolution.py diff --git a/tests/unit/core/test_data/name_resolution/shadowing_compact.sol b/tests/unit/core/test_data/name_resolution/shadowing_compact.sol new file mode 100644 index 000000000..c96130ae9 --- /dev/null +++ b/tests/unit/core/test_data/name_resolution/shadowing_compact.sol @@ -0,0 +1,8 @@ +pragma solidity 0.8.0; +contract B { + uint public x = 21; + function a() public { + uint u = 2 * x; + uint x; + } +} \ No newline at end of file diff --git a/tests/unit/core/test_data/name_resolution/shadowing_legacy_post_0_5_0.sol b/tests/unit/core/test_data/name_resolution/shadowing_legacy_post_0_5_0.sol new file mode 100644 index 000000000..4a7e3a47f --- /dev/null +++ b/tests/unit/core/test_data/name_resolution/shadowing_legacy_post_0_5_0.sol @@ -0,0 +1,8 @@ +pragma solidity 0.5.0; +contract B { + uint public x = 21; + function a() public { + uint u = 2 * x; + uint x; + } +} \ No newline at end of file diff --git a/tests/unit/core/test_data/name_resolution/shadowing_legacy_pre_0_5_0.sol b/tests/unit/core/test_data/name_resolution/shadowing_legacy_pre_0_5_0.sol new file mode 100644 index 000000000..e523fd2fd --- /dev/null +++ b/tests/unit/core/test_data/name_resolution/shadowing_legacy_pre_0_5_0.sol @@ -0,0 +1,8 @@ +pragma solidity 0.4.12; +contract B { + uint public x = 21; + function a() public { + uint u = 2 * x; + uint x; + } +} diff --git a/tests/unit/core/test_name_resolution.py b/tests/unit/core/test_name_resolution.py new file mode 100644 index 000000000..8756baaba --- /dev/null +++ b/tests/unit/core/test_name_resolution.py @@ -0,0 +1,45 @@ +from pathlib import Path + +from slither import Slither + + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" +NAME_RESOLUTION_TEST_ROOT = Path(TEST_DATA_DIR, "name_resolution") + + +def _sort_references_lines(refs: list) -> list: + return sorted([ref.lines[0] for ref in refs]) + + +def test_name_resolution_compact(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.0") + slither = Slither( + Path(NAME_RESOLUTION_TEST_ROOT, "shadowing_compact.sol").as_posix(), solc=solc_path + ) + contract = slither.get_contract_from_name("B")[0] + x = contract.get_state_variable_from_name("x") + assert _sort_references_lines(x.references) == [5] + + +def test_name_resolution_legacy_post_0_5_0(solc_binary_path) -> None: + solc_path = solc_binary_path("0.5.0") + slither = Slither( + Path(NAME_RESOLUTION_TEST_ROOT, "shadowing_legacy_post_0_5_0.sol").as_posix(), + solc=solc_path, + ) + contract = slither.get_contract_from_name("B")[0] + x = contract.get_state_variable_from_name("x") + assert _sort_references_lines(x.references) == [5] + + +def test_name_resolution_legacy_pre_0_5_0(solc_binary_path) -> None: + solc_path = solc_binary_path("0.4.12") + slither = Slither( + Path(NAME_RESOLUTION_TEST_ROOT, "shadowing_legacy_pre_0_5_0.sol").as_posix(), + solc=solc_path, + force_legacy=True, + ) + contract = slither.get_contract_from_name("B")[0] + function = contract.get_function_from_signature("a()") + x = function.get_local_variable_from_name("x") + assert _sort_references_lines(x.references) == [5] From 4053c9b9e35949f1293f6d824aafbaed8381f44e Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 15 Sep 2023 11:10:12 +0200 Subject: [PATCH 248/338] minor improvements --- slither/core/variables/__init__.py | 6 + slither/printers/summary/ck.py | 3 +- slither/printers/summary/halstead.py | 3 +- slither/printers/summary/martin.py | 3 +- slither/utils/ck.py | 9 +- slither/utils/encoding.py | 202 +++++++++++++++++++++ slither/utils/halstead.py | 22 ++- slither/utils/martin.py | 12 +- slither/utils/upgradeability.py | 254 ++------------------------- 9 files changed, 252 insertions(+), 262 deletions(-) create mode 100644 slither/utils/encoding.py diff --git a/slither/core/variables/__init__.py b/slither/core/variables/__init__.py index 638f0f3a4..53872853a 100644 --- a/slither/core/variables/__init__.py +++ b/slither/core/variables/__init__.py @@ -1,2 +1,8 @@ from .state_variable import StateVariable from .variable import Variable +from .local_variable_init_from_tuple import LocalVariableInitFromTuple +from .local_variable import LocalVariable +from .top_level_variable import TopLevelVariable +from .event_variable import EventVariable +from .function_type_variable import FunctionTypeVariable +from .structure_variable import StructureVariable diff --git a/slither/printers/summary/ck.py b/slither/printers/summary/ck.py index f7a851039..78da23756 100644 --- a/slither/printers/summary/ck.py +++ b/slither/printers/summary/ck.py @@ -32,6 +32,7 @@ """ from slither.printers.abstract_printer import AbstractPrinter from slither.utils.ck import CKMetrics +from slither.utils.output import Output class CK(AbstractPrinter): @@ -40,7 +41,7 @@ class CK(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#ck" - def output(self, _filename): + def output(self, _filename: str) -> Output: if len(self.contracts) == 0: return self.generate_output("No contract found") diff --git a/slither/printers/summary/halstead.py b/slither/printers/summary/halstead.py index 8144e467f..d3c3557db 100644 --- a/slither/printers/summary/halstead.py +++ b/slither/printers/summary/halstead.py @@ -25,6 +25,7 @@ """ from slither.printers.abstract_printer import AbstractPrinter from slither.utils.halstead import HalsteadMetrics +from slither.utils.output import Output class Halstead(AbstractPrinter): @@ -33,7 +34,7 @@ class Halstead(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#halstead" - def output(self, _filename): + def output(self, _filename: str) -> Output: if len(self.contracts) == 0: return self.generate_output("No contract found") diff --git a/slither/printers/summary/martin.py b/slither/printers/summary/martin.py index c49e63fcb..a0f1bbfcb 100644 --- a/slither/printers/summary/martin.py +++ b/slither/printers/summary/martin.py @@ -11,6 +11,7 @@ """ from slither.printers.abstract_printer import AbstractPrinter from slither.utils.martin import MartinMetrics +from slither.utils.output import Output class Martin(AbstractPrinter): @@ -19,7 +20,7 @@ class Martin(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#martin" - def output(self, _filename): + def output(self, _filename: str) -> Output: if len(self.contracts) == 0: return self.generate_output("No contract found") diff --git a/slither/utils/ck.py b/slither/utils/ck.py index 7b0d1afd9..ffba663ad 100644 --- a/slither/utils/ck.py +++ b/slither/utils/ck.py @@ -110,7 +110,7 @@ class CKContractMetrics: dit: int = 0 cbo: int = 0 - def __post_init__(self): + def __post_init__(self) -> None: if not hasattr(self.contract, "functions"): return self.count_variables() @@ -123,7 +123,7 @@ class CKContractMetrics: # pylint: disable=too-many-locals # pylint: disable=too-many-branches - def calculate_metrics(self): + def calculate_metrics(self) -> None: """Calculate the metrics for a contract""" rfc = self.public # initialize with public getter count for func in self.contract.functions: @@ -186,7 +186,7 @@ class CKContractMetrics: self.ext_calls += len(external_calls) self.rfc = rfc - def count_variables(self): + def count_variables(self) -> None: """Count the number of variables in a contract""" state_variable_count = 0 constant_count = 0 @@ -302,7 +302,7 @@ class CKMetrics: ("Core", "core", CORE_KEYS), ) - def __post_init__(self): + def __post_init__(self) -> None: martin_metrics = MartinMetrics(self.contracts).contract_metrics dependents = { inherited.name: { @@ -323,6 +323,7 @@ class CKMetrics: for contract in self.contracts } + subtitle = "" # Update each section for (title, attr, keys) in self.SECTIONS: if attr == "core": diff --git a/slither/utils/encoding.py b/slither/utils/encoding.py new file mode 100644 index 000000000..288b58150 --- /dev/null +++ b/slither/utils/encoding.py @@ -0,0 +1,202 @@ +from typing import Union + +from slither.core import variables +from slither.core.declarations import ( + SolidityVariable, + SolidityVariableComposed, + Structure, + Enum, + Contract, +) +from slither.core import solidity_types +from slither.slithir import operations +from slither.slithir import variables as SlitherIRVariable + + +# pylint: disable=too-many-branches +def ntype(_type: Union[solidity_types.Type, str]) -> str: + if isinstance(_type, solidity_types.ElementaryType): + _type = str(_type) + elif isinstance(_type, solidity_types.ArrayType): + if isinstance(_type.type, solidity_types.ElementaryType): + _type = str(_type) + else: + _type = "user_defined_array" + elif isinstance(_type, Structure): + _type = str(_type) + elif isinstance(_type, Enum): + _type = str(_type) + elif isinstance(_type, solidity_types.MappingType): + _type = str(_type) + elif isinstance(_type, solidity_types.UserDefinedType): + if isinstance(_type.type, Contract): + _type = f"contract({_type.type.name})" + elif isinstance(_type.type, Structure): + _type = f"struct({_type.type.name})" + elif isinstance(_type.type, Enum): + _type = f"enum({_type.type.name})" + else: + _type = str(_type) + + _type = _type.replace(" memory", "") + _type = _type.replace(" storage ref", "") + + if "struct" in _type: + return "struct" + if "enum" in _type: + return "enum" + if "tuple" in _type: + return "tuple" + if "contract" in _type: + return "contract" + if "mapping" in _type: + return "mapping" + return _type.replace(" ", "_") + + +# pylint: disable=too-many-branches +def encode_var_for_compare(var: Union[variables.Variable, SolidityVariable]) -> str: + + # variables + if isinstance(var, SlitherIRVariable.Constant): + return f"constant({ntype(var.type)},{var.value})" + if isinstance(var, SolidityVariableComposed): + return f"solidity_variable_composed({var.name})" + if isinstance(var, SolidityVariable): + return f"solidity_variable{var.name}" + if isinstance(var, SlitherIRVariable.TemporaryVariable): + return "temporary_variable" + if isinstance(var, SlitherIRVariable.ReferenceVariable): + return f"reference({ntype(var.type)})" + if isinstance(var, variables.LocalVariable): + return f"local_solc_variable({ntype(var.type)},{var.location})" + if isinstance(var, variables.StateVariable): + if not (var.is_constant or var.is_immutable): + try: + slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) + except KeyError: + slot = var.name + else: + slot = var.name + return f"state_solc_variable({ntype(var.type)},{slot})" + if isinstance(var, variables.LocalVariableInitFromTuple): + return "local_variable_init_tuple" + if isinstance(var, SlitherIRVariable.TupleVariable): + return "tuple_variable" + + # default + return "" + + +# pylint: disable=too-many-branches +def encode_ir_for_upgradeability_compare(ir: operations.Operation) -> str: + # operations + if isinstance(ir, operations.Assignment): + return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" + if isinstance(ir, operations.Index): + return f"index({ntype(ir.variable_right.type)})" + if isinstance(ir, operations.Member): + return "member" # .format(ntype(ir._type)) + if isinstance(ir, operations.Length): + return "length" + if isinstance(ir, operations.Binary): + return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})" + if isinstance(ir, operations.Unary): + return f"unary({str(ir.type)})" + if isinstance(ir, operations.Condition): + return f"condition({encode_var_for_compare(ir.value)})" + if isinstance(ir, operations.NewStructure): + return "new_structure" + if isinstance(ir, operations.NewContract): + return "new_contract" + if isinstance(ir, operations.NewArray): + return f"new_array({ntype(ir.array_type)})" + if isinstance(ir, operations.NewElementaryType): + return f"new_elementary({ntype(ir.type)})" + if isinstance(ir, operations.Delete): + return f"delete({encode_var_for_compare(ir.lvalue)},{encode_var_for_compare(ir.variable)})" + if isinstance(ir, operations.SolidityCall): + return f"solidity_call({ir.function.full_name})" + if isinstance(ir, operations.InternalCall): + return f"internal_call({ntype(ir.type_call)})" + if isinstance(ir, operations.EventCall): # is this useful? + return "event" + if isinstance(ir, operations.LibraryCall): + return "library_call" + if isinstance(ir, operations.InternalDynamicCall): + return "internal_dynamic_call" + if isinstance(ir, operations.HighLevelCall): # TODO: improve + return "high_level_call" + if isinstance(ir, operations.LowLevelCall): # TODO: improve + return "low_level_call" + if isinstance(ir, operations.TypeConversion): + return f"type_conversion({ntype(ir.type)})" + if isinstance(ir, operations.Return): # this can be improved using values + return "return" # .format(ntype(ir.type)) + if isinstance(ir, operations.Transfer): + return f"transfer({encode_var_for_compare(ir.call_value)})" + if isinstance(ir, operations.Send): + return f"send({encode_var_for_compare(ir.call_value)})" + if isinstance(ir, operations.Unpack): # TODO: improve + return "unpack" + if isinstance(ir, operations.InitArray): # TODO: improve + return "init_array" + + # default + return "" + + +def encode_ir_for_halstead(ir: operations.Operation) -> str: + # operations + if isinstance(ir, operations.Assignment): + return "assignment" + if isinstance(ir, operations.Index): + return "index" + if isinstance(ir, operations.Member): + return "member" # .format(ntype(ir._type)) + if isinstance(ir, operations.Length): + return "length" + if isinstance(ir, operations.Binary): + return f"binary({str(ir.type)})" + if isinstance(ir, operations.Unary): + return f"unary({str(ir.type)})" + if isinstance(ir, operations.Condition): + return f"condition({encode_var_for_compare(ir.value)})" + if isinstance(ir, operations.NewStructure): + return "new_structure" + if isinstance(ir, operations.NewContract): + return "new_contract" + if isinstance(ir, operations.NewArray): + return f"new_array({ntype(ir.array_type)})" + if isinstance(ir, operations.NewElementaryType): + return f"new_elementary({ntype(ir.type)})" + if isinstance(ir, operations.Delete): + return "delete" + if isinstance(ir, operations.SolidityCall): + return f"solidity_call({ir.function.full_name})" + if isinstance(ir, operations.InternalCall): + return f"internal_call({ntype(ir.type_call)})" + if isinstance(ir, operations.EventCall): # is this useful? + return "event" + if isinstance(ir, operations.LibraryCall): + return "library_call" + if isinstance(ir, operations.InternalDynamicCall): + return "internal_dynamic_call" + if isinstance(ir, operations.HighLevelCall): # TODO: improve + return "high_level_call" + if isinstance(ir, operations.LowLevelCall): # TODO: improve + return "low_level_call" + if isinstance(ir, operations.TypeConversion): + return f"type_conversion({ntype(ir.type)})" + if isinstance(ir, operations.Return): # this can be improved using values + return "return" # .format(ntype(ir.type)) + if isinstance(ir, operations.Transfer): + return "transfer" + if isinstance(ir, operations.Send): + return "send" + if isinstance(ir, operations.Unpack): # TODO: improve + return "unpack" + if isinstance(ir, operations.InitArray): # TODO: improve + return "init_array" + # default + raise NotImplementedError(f"encode_ir_for_halstead: {ir}") diff --git a/slither/utils/halstead.py b/slither/utils/halstead.py index 64dd1f6a1..9ec952e48 100644 --- a/slither/utils/halstead.py +++ b/slither/utils/halstead.py @@ -25,13 +25,17 @@ """ import math +from collections import OrderedDict from dataclasses import dataclass, field from typing import Tuple, List, Dict -from collections import OrderedDict + from slither.core.declarations import Contract from slither.slithir.variables.temporary import TemporaryVariable +from slither.utils.encoding import encode_ir_for_halstead from slither.utils.myprettytable import make_pretty_table, MyPrettyTable -from slither.utils.upgradeability import encode_ir_for_halstead + + +# pylint: disable=too-many-branches @dataclass @@ -55,7 +59,7 @@ class HalsteadContractMetrics: T: float = 0 B: float = 0 - def __post_init__(self): + def __post_init__(self) -> None: """Operators and operands can be passed in as constructor args to avoid computing them based on the contract. Useful for computing metrics for ALL_CONTRACTS""" @@ -85,7 +89,7 @@ class HalsteadContractMetrics: } ) - def populate_operators_and_operands(self): + def populate_operators_and_operands(self) -> None: """Populate the operators and operands lists.""" operators = [] operands = [] @@ -104,7 +108,7 @@ class HalsteadContractMetrics: self.all_operators.extend(operators) self.all_operands.extend(operands) - def compute_metrics(self, all_operators=None, all_operands=None): + def compute_metrics(self, all_operators=None, all_operands=None) -> None: """Compute the Halstead metrics.""" if all_operators is None: all_operators = self.all_operators @@ -183,17 +187,17 @@ class HalsteadMetrics: ("Extended 2/2", "extended2", EXTENDED2_KEYS), ) - def __post_init__(self): + def __post_init__(self) -> None: # Compute the metrics for each contract and for all contracts. self.update_contract_metrics() self.add_all_contracts_metrics() self.update_reporting_sections() - def update_contract_metrics(self): + def update_contract_metrics(self) -> None: for contract in self.contracts: self.contract_metrics[contract.name] = HalsteadContractMetrics(contract=contract) - def add_all_contracts_metrics(self): + def add_all_contracts_metrics(self) -> None: # If there are more than 1 contract, compute the metrics for all contracts. if len(self.contracts) <= 1: return @@ -211,7 +215,7 @@ class HalsteadMetrics: None, all_operators=all_operators, all_operands=all_operands ) - def update_reporting_sections(self): + def update_reporting_sections(self) -> None: # Create the table and text for each section. data = { contract.name: self.contract_metrics[contract.name].to_dict() diff --git a/slither/utils/martin.py b/slither/utils/martin.py index fb62a4c58..c336227fd 100644 --- a/slither/utils/martin.py +++ b/slither/utils/martin.py @@ -26,12 +26,12 @@ class MartinContractMetrics: i: float = 0.0 d: float = 0.0 - def __post_init__(self): + def __post_init__(self) -> None: if self.ce + self.ca > 0: self.i = float(self.ce / (self.ce + self.ca)) self.d = float(abs(self.i - self.abstractness)) - def to_dict(self): + def to_dict(self) -> Dict: return { "Dependents": self.ca, "Dependencies": self.ce, @@ -65,12 +65,12 @@ class MartinMetrics: ) SECTIONS: Tuple[Tuple[str, str, Tuple[str]]] = (("Core", "core", CORE_KEYS),) - def __post_init__(self): + def __post_init__(self) -> None: self.update_abstractness() self.update_coupling() self.update_reporting_sections() - def update_reporting_sections(self): + def update_reporting_sections(self) -> None: # Create the table and text for each section. data = { contract.name: self.contract_metrics[contract.name].to_dict() @@ -98,7 +98,7 @@ class MartinMetrics: SectionInfo(title=section_title, pretty_table=pretty_table, txt=txt), ) - def update_abstractness(self) -> float: + def update_abstractness(self) -> None: abstract_contract_count = 0 for c in self.contracts: if not c.is_fully_implemented: @@ -106,7 +106,7 @@ class MartinMetrics: self.abstractness = float(abstract_contract_count / len(self.contracts)) # pylint: disable=too-many-branches - def update_coupling(self) -> Dict: + def update_coupling(self) -> None: dependencies = {} for contract in self.contracts: external_calls = [] diff --git a/slither/utils/upgradeability.py b/slither/utils/upgradeability.py index 5cc3dba08..bbb253175 100644 --- a/slither/utils/upgradeability.py +++ b/slither/utils/upgradeability.py @@ -1,66 +1,28 @@ -from typing import Optional, Tuple, List, Union +from typing import Optional, Tuple, List + +from slither.analyses.data_dependency.data_dependency import get_dependencies +from slither.core.cfg.node import Node, NodeType from slither.core.declarations import ( Contract, - Structure, - Enum, - SolidityVariableComposed, - SolidityVariable, Function, ) -from slither.core.solidity_types import ( - Type, - ElementaryType, - ArrayType, - MappingType, - UserDefinedType, -) -from slither.core.variables.local_variable import LocalVariable -from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple -from slither.core.variables.state_variable import StateVariable -from slither.analyses.data_dependency.data_dependency import get_dependencies -from slither.core.variables.variable import Variable from slither.core.expressions import ( Literal, Identifier, CallExpression, AssignmentOperation, ) -from slither.core.cfg.node import Node, NodeType +from slither.core.solidity_types import ( + ElementaryType, +) +from slither.core.variables.local_variable import LocalVariable +from slither.core.variables.state_variable import StateVariable +from slither.core.variables.variable import Variable from slither.slithir.operations import ( - Operation, - Assignment, - Index, - Member, - Length, - Binary, - Unary, - Condition, - NewArray, - NewStructure, - NewContract, - NewElementaryType, - SolidityCall, - Delete, - EventCall, - LibraryCall, - InternalDynamicCall, - HighLevelCall, LowLevelCall, - TypeConversion, - Return, - Transfer, - Send, - Unpack, - InitArray, - InternalCall, -) -from slither.slithir.variables import ( - TemporaryVariable, - TupleVariable, - Constant, - ReferenceVariable, ) from slither.tools.read_storage.read_storage import SlotInfo, SlitherReadStorage +from slither.utils.encoding import encode_ir_for_upgradeability_compare class TaintedExternalContract: @@ -385,201 +347,13 @@ def is_function_modified(f1: Function, f2: Function) -> bool: if len(node_f1.irs) != len(node_f2.irs): return True for i, ir in enumerate(node_f1.irs): - if encode_ir_for_compare(ir) != encode_ir_for_compare(node_f2.irs[i]): + if encode_ir_for_upgradeability_compare(ir) != encode_ir_for_upgradeability_compare( + node_f2.irs[i] + ): return True return False -# pylint: disable=too-many-branches -def ntype(_type: Union[Type, str]) -> str: - if isinstance(_type, ElementaryType): - _type = str(_type) - elif isinstance(_type, ArrayType): - if isinstance(_type.type, ElementaryType): - _type = str(_type) - else: - _type = "user_defined_array" - elif isinstance(_type, Structure): - _type = str(_type) - elif isinstance(_type, Enum): - _type = str(_type) - elif isinstance(_type, MappingType): - _type = str(_type) - elif isinstance(_type, UserDefinedType): - if isinstance(_type.type, Contract): - _type = f"contract({_type.type.name})" - elif isinstance(_type.type, Structure): - _type = f"struct({_type.type.name})" - elif isinstance(_type.type, Enum): - _type = f"enum({_type.type.name})" - else: - _type = str(_type) - - _type = _type.replace(" memory", "") - _type = _type.replace(" storage ref", "") - - if "struct" in _type: - return "struct" - if "enum" in _type: - return "enum" - if "tuple" in _type: - return "tuple" - if "contract" in _type: - return "contract" - if "mapping" in _type: - return "mapping" - return _type.replace(" ", "_") - - -# pylint: disable=too-many-branches -def encode_ir_for_compare(ir: Operation) -> str: - # operations - if isinstance(ir, Assignment): - return f"({encode_var_for_compare(ir.lvalue)}):=({encode_var_for_compare(ir.rvalue)})" - if isinstance(ir, Index): - return f"index({ntype(ir.variable_right.type)})" - if isinstance(ir, Member): - return "member" # .format(ntype(ir._type)) - if isinstance(ir, Length): - return "length" - if isinstance(ir, Binary): - return f"binary({encode_var_for_compare(ir.variable_left)}{ir.type}{encode_var_for_compare(ir.variable_right)})" - if isinstance(ir, Unary): - return f"unary({str(ir.type)})" - if isinstance(ir, Condition): - return f"condition({encode_var_for_compare(ir.value)})" - if isinstance(ir, NewStructure): - return "new_structure" - if isinstance(ir, NewContract): - return "new_contract" - if isinstance(ir, NewArray): - return f"new_array({ntype(ir.array_type)})" - if isinstance(ir, NewElementaryType): - return f"new_elementary({ntype(ir.type)})" - if isinstance(ir, Delete): - return f"delete({encode_var_for_compare(ir.lvalue)},{encode_var_for_compare(ir.variable)})" - if isinstance(ir, SolidityCall): - return f"solidity_call({ir.function.full_name})" - if isinstance(ir, InternalCall): - return f"internal_call({ntype(ir.type_call)})" - if isinstance(ir, EventCall): # is this useful? - return "event" - if isinstance(ir, LibraryCall): - return "library_call" - if isinstance(ir, InternalDynamicCall): - return "internal_dynamic_call" - if isinstance(ir, HighLevelCall): # TODO: improve - return "high_level_call" - if isinstance(ir, LowLevelCall): # TODO: improve - return "low_level_call" - if isinstance(ir, TypeConversion): - return f"type_conversion({ntype(ir.type)})" - if isinstance(ir, Return): # this can be improved using values - return "return" # .format(ntype(ir.type)) - if isinstance(ir, Transfer): - return f"transfer({encode_var_for_compare(ir.call_value)})" - if isinstance(ir, Send): - return f"send({encode_var_for_compare(ir.call_value)})" - if isinstance(ir, Unpack): # TODO: improve - return "unpack" - if isinstance(ir, InitArray): # TODO: improve - return "init_array" - - # default - return "" - - -# pylint: disable=too-many-branches -def encode_ir_for_halstead(ir: Operation) -> str: - # operations - if isinstance(ir, Assignment): - return "assignment" - if isinstance(ir, Index): - return "index" - if isinstance(ir, Member): - return "member" # .format(ntype(ir._type)) - if isinstance(ir, Length): - return "length" - if isinstance(ir, Binary): - return f"binary({str(ir.type)})" - if isinstance(ir, Unary): - return f"unary({str(ir.type)})" - if isinstance(ir, Condition): - return f"condition({encode_var_for_compare(ir.value)})" - if isinstance(ir, NewStructure): - return "new_structure" - if isinstance(ir, NewContract): - return "new_contract" - if isinstance(ir, NewArray): - return f"new_array({ntype(ir.array_type)})" - if isinstance(ir, NewElementaryType): - return f"new_elementary({ntype(ir.type)})" - if isinstance(ir, Delete): - return "delete" - if isinstance(ir, SolidityCall): - return f"solidity_call({ir.function.full_name})" - if isinstance(ir, InternalCall): - return f"internal_call({ntype(ir.type_call)})" - if isinstance(ir, EventCall): # is this useful? - return "event" - if isinstance(ir, LibraryCall): - return "library_call" - if isinstance(ir, InternalDynamicCall): - return "internal_dynamic_call" - if isinstance(ir, HighLevelCall): # TODO: improve - return "high_level_call" - if isinstance(ir, LowLevelCall): # TODO: improve - return "low_level_call" - if isinstance(ir, TypeConversion): - return f"type_conversion({ntype(ir.type)})" - if isinstance(ir, Return): # this can be improved using values - return "return" # .format(ntype(ir.type)) - if isinstance(ir, Transfer): - return "transfer" - if isinstance(ir, Send): - return "send" - if isinstance(ir, Unpack): # TODO: improve - return "unpack" - if isinstance(ir, InitArray): # TODO: improve - return "init_array" - # default - raise NotImplementedError(f"encode_ir_for_halstead: {ir}") - - -# pylint: disable=too-many-branches -def encode_var_for_compare(var: Variable) -> str: - - # variables - if isinstance(var, Constant): - return f"constant({ntype(var.type)},{var.value})" - if isinstance(var, SolidityVariableComposed): - return f"solidity_variable_composed({var.name})" - if isinstance(var, SolidityVariable): - return f"solidity_variable{var.name}" - if isinstance(var, TemporaryVariable): - return "temporary_variable" - if isinstance(var, ReferenceVariable): - return f"reference({ntype(var.type)})" - if isinstance(var, LocalVariable): - return f"local_solc_variable({ntype(var.type)},{var.location})" - if isinstance(var, StateVariable): - if not (var.is_constant or var.is_immutable): - try: - slot, _ = var.contract.compilation_unit.storage_layout_of(var.contract, var) - except KeyError: - slot = var.name - else: - slot = var.name - return f"state_solc_variable({ntype(var.type)},{slot})" - if isinstance(var, LocalVariableInitFromTuple): - return "local_variable_init_tuple" - if isinstance(var, TupleVariable): - return "tuple_variable" - - # default - return "" - - def get_proxy_implementation_slot(proxy: Contract) -> Optional[SlotInfo]: """ Gets information about the storage slot where a proxy's implementation address is stored. From c8bd72ed9fd00f8d42c8b1de3419a2d1bdc779b7 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 15 Sep 2023 11:16:32 +0200 Subject: [PATCH 249/338] Fix circular dep --- slither/core/variables/local_variable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/core/variables/local_variable.py b/slither/core/variables/local_variable.py index 427f00408..9baf80445 100644 --- a/slither/core/variables/local_variable.py +++ b/slither/core/variables/local_variable.py @@ -2,7 +2,6 @@ from typing import Optional, TYPE_CHECKING from slither.core.variables.variable import Variable from slither.core.solidity_types.user_defined_type import UserDefinedType -from slither.core.solidity_types.array_type import ArrayType from slither.core.solidity_types.mapping_type import MappingType from slither.core.solidity_types.elementary_type import ElementaryType @@ -51,6 +50,9 @@ class LocalVariable(Variable): Returns: (bool) """ + # pylint: disable=import-outside-toplevel + from slither.core.solidity_types.array_type import ArrayType + if self.location == "memory": return False if self.location == "calldata": From bcbe4ffe93ab0c1968c2f212d5b7d437126339b7 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 15 Sep 2023 11:30:47 +0200 Subject: [PATCH 250/338] Update ci_test_printers.sh --- scripts/ci_test_printers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci_test_printers.sh b/scripts/ci_test_printers.sh index e7310700e..3306c134e 100755 --- a/scripts/ci_test_printers.sh +++ b/scripts/ci_test_printers.sh @@ -5,7 +5,7 @@ cd tests/e2e/solc_parsing/test_data/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,halstead,human-summary,inheritance,inheritance-graph,loc,martin,slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration" +ALL_PRINTERS="cfg,constructor-calls,contract-summary,data-dependency,echidna,function-id,function-summary,modifiers,call-graph,halstead,human-summary,inheritance,inheritance-graph,loc,martin,slithir,slithir-ssa,vars-and-auth,require,variable-order,declaration,ck" # Only test 0.5.17 to limit test time for file in *0.5.17-compact.zip; do From f07d506b4a5ded16f996233cf0885090c6c8fd94 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Fri, 15 Sep 2023 20:12:48 -0400 Subject: [PATCH 251/338] Check s_ and i_ naming convention for private and internal only --- .../naming_convention/naming_convention.py | 15 +++----- ...ention_0_4_25_naming_convention_sol__0.txt | 16 +++++---- ...ention_0_5_16_naming_convention_sol__0.txt | 16 +++++---- ...ention_0_6_11_naming_convention_sol__0.txt | 32 ++++++++++-------- ...vention_0_7_6_naming_convention_sol__0.txt | 32 ++++++++++-------- .../0.4.25/naming_convention.sol | 2 ++ .../0.4.25/naming_convention.sol-0.4.25.zip | Bin 3801 -> 3818 bytes ...arning_for_public_constants.sol-0.4.25.zip | Bin 1380 -> 1378 bytes .../0.5.16/naming_convention.sol | 2 ++ .../0.5.16/naming_convention.sol-0.5.16.zip | Bin 3804 -> 3836 bytes ...arning_for_public_constants.sol-0.5.16.zip | Bin 1387 -> 1385 bytes .../0.6.11/naming_convention.sol | 3 ++ .../0.6.11/naming_convention.sol-0.6.11.zip | Bin 3930 -> 4024 bytes ...arning_for_public_constants.sol-0.6.11.zip | Bin 1409 -> 1407 bytes .../0.7.6/naming_convention.sol | 3 ++ .../0.7.6/naming_convention.sol-0.7.6.zip | Bin 3852 -> 3951 bytes ...warning_for_public_constants.sol-0.7.6.zip | Bin 1367 -> 1365 bytes 17 files changed, 68 insertions(+), 53 deletions(-) diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 904b57eac..1e10b5543 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -175,19 +175,12 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 results.append(res) else: - # first priority: check for immutable variable naming conventions - if var.is_immutable: - correct_naming = self.is_immutable_naming(var.name) + if var.visibility in ["private", "internal"]: + correct_naming = self.is_mixed_case_with_underscore(var.name) or self.is_state_naming(var.name) - # second priority: check for state variable naming conventions - elif self.is_state_naming(var.name): - correct_naming = True + if not correct_naming and var.is_immutable: + correct_naming = self.is_immutable_naming(var.name) - # third priority: check if visibility is private or internal and check for underscore mixed case - elif var.visibility in ["private", "internal"]: - correct_naming = self.is_mixed_case_with_underscore(var.name) - - # fourth priority: check for mixed case naming conventions else: correct_naming = self.is_mixed_case(var.name) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt index 2c05a3c40..2b64ccac1 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt @@ -1,10 +1,12 @@ +Variable T.s_myStateVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#60) is not in mixedCase + Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#71) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#73) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#71) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#73) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#72) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#11) is not in mixedCase @@ -14,11 +16,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#61) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#63) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#57) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#59) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#72) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords @@ -26,7 +28,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.4.25 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#71) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt index 494253c35..057be1d0c 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt @@ -1,10 +1,12 @@ +Variable T.s_myStateVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#60) is not in mixedCase + Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#14-16) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#71) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#73) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#71) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#73) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#72) is not in mixedCase Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#11) is not in mixedCase @@ -14,11 +16,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_c Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#61) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#63) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#57) is not in mixedCase +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#59) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is single letter l, O, or I, which should not be used +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#72) is single letter l, O, or I, which should not be used Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords @@ -26,7 +28,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.5.16 Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#30-33) is not in mixedCase -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#71) is single letter l, O, or I, which should not be used Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#35) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt index e6e431fcc..035b01623 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt @@ -1,32 +1,36 @@ -Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#16-18) is not in CapWords +Variable T.s_myStateVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#63) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#73) is not in mixedCase +Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#17-19) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#73) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#76) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#72) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#76) is single letter l, O, or I, which should not be used -Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#13) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#75) is not in mixedCase + +Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#14) is not in mixedCase Constant naming.MY_other_CONSTANT (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES -Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#3-50) is not in CapWords +Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#3-51) is not in CapWords Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#63) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#66) is not in mixedCase + +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#62) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#59) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#75) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#72) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#26) is not in CapWords -Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#25) is not in CapWords +Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#44-46) is not in mixedCase -Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#43-45) is not in mixedCase +Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#33-36) is not in mixedCase -Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#32-35) is not in mixedCase +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#74) is single letter l, O, or I, which should not be used -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#71) is single letter l, O, or I, which should not be used +Variable naming.i_myImutableVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#11) is not in mixedCase -Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#37) is not in mixedCase +Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#38) is not in mixedCase diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt index d033db260..5e446f156 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt @@ -1,32 +1,36 @@ -Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#16-18) is not in CapWords +Variable T.s_myStateVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#63) is not in mixedCase -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#73) is not in mixedCase +Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#17-19) is not in CapWords -Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#73) is single letter l, O, or I, which should not be used +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#76) is not in mixedCase -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#72) is not in mixedCase +Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#76) is single letter l, O, or I, which should not be used -Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#13) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#75) is not in mixedCase + +Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#14) is not in mixedCase Constant naming.MY_other_CONSTANT (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES -Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#3-50) is not in CapWords +Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#3-51) is not in CapWords Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#6) is not in CapWords -Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#63) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#66) is not in mixedCase + +Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#62) is not in mixedCase -Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#59) is not in mixedCase +Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#75) is single letter l, O, or I, which should not be used -Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#72) is single letter l, O, or I, which should not be used +Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#26) is not in CapWords -Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#25) is not in CapWords +Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#44-46) is not in mixedCase -Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#43-45) is not in mixedCase +Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#33-36) is not in mixedCase -Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#32-35) is not in mixedCase +Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#74) is single letter l, O, or I, which should not be used -Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#71) is single letter l, O, or I, which should not be used +Variable naming.i_myImutableVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#11) is not in mixedCase -Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#37) is not in mixedCase +Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#38) is not in mixedCase diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol index 3cc7197e5..4dcfb1760 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol @@ -53,7 +53,9 @@ contract Test { contract T { uint private _myPrivateVar; + uint private s_myPrivateVar; uint internal _myInternalVar; + uint internal s_myInternalVar; uint public _myPublicVar; uint public s_myStateVar; uint public myPublicVar; diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip index a448234c6efc12d56a6f8f3b0795d137c6097df9..be41a722754565bfd8472ecda649c8023fe1c9b0 100644 GIT binary patch delta 3528 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip index 10aff7711e99be35362fb893bf8c6fb9d4c08ef6..75ba539c315119154831fbb974dc2bcf50938fd9 100644 GIT binary patch delta 139 zcmaFD^@vM2z?+%Ho`H#hkHKJ}e)x0w61hnmh1*z?BYN!wcXs9+?OuQT!xILTuKzQC zikV~_w$EyBJ)eAcLZ-{-!_^5-S4%nBUbm}?-R;}f{b2dGjLlI}ZNHdGe3M@nbuDBQ-9s>yfw`Gq@+4q4xb_^o~Z_m(w5&kDtTpK3+(>(V-M=YW8!{UE+V@LvESCB7dLj3E`xl~| j-#AQiO25Sazwn{$K!7(RlRX2PO_TqyB(S|?VE_UE!lOG` diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol index 3cc7197e5..4dcfb1760 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol @@ -53,7 +53,9 @@ contract Test { contract T { uint private _myPrivateVar; + uint private s_myPrivateVar; uint internal _myInternalVar; + uint internal s_myInternalVar; uint public _myPublicVar; uint public s_myStateVar; uint public myPublicVar; diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip index 44c8707eeb2b417fac50f9a367eccfe2de96d252..52071feef049d2b5719a80688a54f9a794935c77 100644 GIT binary patch delta 3546 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip b/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip index c1cc97460a84a0700770d8195d9284b6ee5a0399..adf409d405ecfee66965b3152b71955dd5e8a3c8 100644 GIT binary patch delta 167 zcmaFO^^!|Cz?+%Ho`H#hkHKJ}et4nJ=De93g}Yhm&&0UDmyvoUcHnt{1ItcrPSz~J z{W&uh{PGA}UaPZcQ^b}BpG$YHzgDIFX7h`W>2?eMHEx;MsS!7G!`TI4u{*+E6o!Al z@^9zi?&I6%|G!ir-5=o1$YjreW)lko!(4s_26F}kXkY}f^Cru)y0N_j$}=zk0MJoA A`~Uy| delta 167 zcmaFK^_ojKz?+%Ho`H#hk73msjqt=>vu@7bDBR6bfBN5x4feMT+R_alOq67KSaQhw z&D-*AoT|T@ZrdH4`-jib&8zB=r&%^v@Djl<>__L{PMz~Z?lI5ZS_aMOKNF{VG+M>7 zX_(Em3qRHF74ZK{$(@V721~j`^7#QaAGccGlAV32nkUd$N)r0K=P?muK0KhRk A3;+NC diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol index 94125ab78..7d81c3954 100644 --- a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol +++ b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol @@ -9,6 +9,7 @@ contract naming { uint constant MY_other_CONSTANT = 2; uint public immutable i_myImutableVar = 1; + uint private immutable i_myPrivateImutableVar = 1; uint Var_One = 1; uint varTwo = 2; @@ -55,7 +56,9 @@ contract Test { contract T { uint private _myPrivateVar; + uint private s_myPrivateVar; uint internal _myInternalVar; + uint internal s_myInternalVar; uint public _myPublicVar; uint public s_myStateVar; uint public myPublicVar; diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip index 86ce8485c735b311c8de39cc2663f7500ea34900..d46a8569c0593a4ec0a50b693c66f7c8af729d14 100644 GIT binary patch delta 3755 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip index 9cf6fe45063f87430f0ad7a12f9b030453f68d1a..bed78289e56ef3f5908f4435662a4a36bc1e0d75 100644 GIT binary patch delta 152 zcmZqV{?8>H;LXfp&%ngM$6&BfKm6JDr`qdT7#Mc&GccG>He|Kh7@EM6GDUlq+o2gh zm#?)=-02%wex$nIeVM!5(!~n7Z+Ue@jkYITC@M=mx#Y{%Nv4J6C#LSu5@Rvwb<1Qr u@K8|Bk-c4NYSGR`rm|u delta 154 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

`SzWTGfhTHsW5sLi>79FwcE zRZ3MV!e~F#-jfmbuVP3z&S_+M8-}NMImsoDz{GZyCoZgAduOL8VHC#$!+ZI~j=|iV zxlM89hqotV!M0G+0Q-S**+JoZrDi1@$KHE?0tF1*CxPeLk}VzldAklb@eT}4W{Z;$ zAACM-5)T$q{XH$gFas6mv@r6lskB@HW@RtFVkfnV(arzTT{jJ!N?al`+k|9DS-azU zeB+swb7BbZ&)cYki-Kix!sKITtCuV6Lz#};-=1W?#X1vIVe<&2okWR&>-IuUQ?Xuu zmfu>+jxVwQ^6*WgQnTsgPKL`+wU7QRdK#z<(Uh|=oMnH)Ud1qqqL zs#E7dj_@r0H0ebWl3loaCcHd}Y)Ko8mw7I`21MA0+UE z2o~@TevKw9TT4J&Hk7X^Kk~|1DKHq;IUaRqG2A&m*|i>r8{ZQ2jrS9w0-pl91j-2j zURr=NHl17H$HE+>#fF@~wkgf}H5_*Cu$4oNzgo5E7Fc38Z8qQ(#uae=OM@f_5 z{gFDPJKl#*LK8u+Vj?kEBTCn)F))s^J*Lp3mz4rRe_z&a!g4o)vg3#@e~4wtTt$HiOFM<4~D#m&soo)(VGa`x4A`+;dIb!VSa!Ls{*U)j8<(mFU; zQ_HV6@++r9-{h`frk3aRm>N4LJt8upC{4&u*lOiZsRkggxY$b+DKA@ zt(8ISxZ`gMFhs@(HYh(Qr8#c}u0^r+Em z7$KDd;eeN`+x8%TqGy6j#G+t9j{8+4DG&xF6dNa(bwS?@^?W;keoJ%SGTmh0Z`HuO zdKy8$4dd>uDjX-Fn;?OQz(il5>V8eeZ!fZ=@5RbZtg-0V_SVjeFN4Vp~;G|G=}Z=uk@m0zUvh h00ICG05730SGz9y>bnjA06C45xeiSR0uKNH008g*{DlAj delta 3570 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 diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip b/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip index 8caf6ecf2fdd994d985c73bb4f2847eb9c71d560..e2697df8906ba02a14d43a104fff0b469ff6984d 100644 GIT binary patch delta 141 zcmcc4b(Kpvz?+%Ho`H#hkHKJ}e)vk=GQrl3!sRTf*PDOlEs}J0n4UZ*+k3ge5gph1 zm2;n0WS8sY{ZE{%`%#QjUZ?J_zHj6Q$BB!J&E;2X|2xPbYxnfSqAf@N@-_+zPL(*Q jbnLXqRN3$U&s4AG3-D%SvS&cEY4S&w1h!i&3_t(?0v|Os delta 143 zcmcc0b)8E%z?+%Ho`H#hk73msjc{v`GM@I0!sRUK=hcpglyk4no6NYbM|h9mp+$L5 z4_ti|t)|?3Oh>k7rczGBr|R|bm2Z>X_@7;p|2pTGX7v`{LjSmf46C%fZmM(CHB7D9 lpk4fO`P)+(|Npl$T2%#jGcwsTpxHI~Jxc=H9To;4005YlHlY9j From b116728bc117f0911f187556eae6c9f101218c00 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Fri, 15 Sep 2023 20:31:48 -0400 Subject: [PATCH 252/338] Follow linter --- slither/detectors/naming_convention/naming_convention.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 1e10b5543..85e1a6a65 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -176,7 +176,9 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 else: if var.visibility in ["private", "internal"]: - correct_naming = self.is_mixed_case_with_underscore(var.name) or self.is_state_naming(var.name) + correct_naming = self.is_mixed_case_with_underscore( + var.name + ) or self.is_state_naming(var.name) if not correct_naming and var.is_immutable: correct_naming = self.is_immutable_naming(var.name) From 72f0837ef0214aa5ee19bb5a13f7e6831f8c3605 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 15:30:25 -0500 Subject: [PATCH 253/338] Bump docker/setup-buildx-action from 2 to 3 (#2132) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 05406d0ed..8a950c022 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -23,7 +23,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 id: buildx with: install: true From a234e34858d1e540e4823ee76d35f82bbc789688 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 15:30:35 -0500 Subject: [PATCH 254/338] Bump docker/build-push-action from 4 to 5 (#2133) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8a950c022..2bc826de4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Docker Build and Push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: platforms: linux/amd64,linux/arm64/v8,linux/arm/v7 target: final From 1f6b7bfded90df505e43e943032c75f6fdde66c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 15:30:45 -0500 Subject: [PATCH 255/338] Bump docker/setup-qemu-action from 2 to 3 (#2134) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 2bc826de4..215c5e1ad 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 0501fefa459691557e16be812de4783f3f96749c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 15:30:54 -0500 Subject: [PATCH 256/338] Bump docker/login-action from 2 to 3 (#2135) Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 215c5e1ad..e0e303ed8 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -40,7 +40,7 @@ jobs: type=edge - name: GitHub Container Registry Login - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} From cc9e0a568e5b1e25eb43b57cdc624945c9fee822 Mon Sep 17 00:00:00 2001 From: Simone Date: Fri, 29 Sep 2023 17:41:52 +0200 Subject: [PATCH 257/338] Fix parsing super call expression --- slither/solc_parsing/expressions/expression_parsing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/solc_parsing/expressions/expression_parsing.py b/slither/solc_parsing/expressions/expression_parsing.py index 74ff593c7..4ed896ed9 100644 --- a/slither/solc_parsing/expressions/expression_parsing.py +++ b/slither/solc_parsing/expressions/expression_parsing.py @@ -175,7 +175,7 @@ def parse_call( called = parse_expression(children[0], caller_context) arguments = [parse_expression(a, caller_context) for a in children[1::]] - if isinstance(called, SuperCallExpression): + if isinstance(called, SuperIdentifier): sp = SuperCallExpression(called, arguments, type_return) sp.set_offset(expression["src"], caller_context.compilation_unit) return sp From 838680bed7720df3800eb167835fb9b80ee16a04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 09:29:34 -0500 Subject: [PATCH 258/338] Bump sigstore/gh-action-sigstore-python from 2.0.1 to 2.1.0 (#2154) Bumps [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) from 2.0.1 to 2.1.0. - [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases) - [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/v2.0.1...v2.1.0) --- updated-dependencies: - dependency-name: sigstore/gh-action-sigstore-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fef0a4a2e..7b4d61e89 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,7 +47,7 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.8.10 - name: sign - uses: sigstore/gh-action-sigstore-python@v2.0.1 + uses: sigstore/gh-action-sigstore-python@v2.1.0 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true From c31faa0df5eee5ab928db0998b0a1676deda69b3 Mon Sep 17 00:00:00 2001 From: Jeff Schroeder Date: Wed, 4 Oct 2023 01:03:59 +0000 Subject: [PATCH 259/338] Fix a typo in the help text --- slither/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/__main__.py b/slither/__main__.py index d9201a90d..c63920036 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -442,7 +442,7 @@ def parse_args( group_checklist.add_argument( "--checklist-limit", - help="Limite the number of results per detector in the markdown file", + help="Limit the number of results per detector in the markdown file", action="store", default="", ) From 700794971ba6bb1d905c6de171331dbd265619e3 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 5 Oct 2023 14:27:28 +0200 Subject: [PATCH 260/338] Release 2 new detectors --- slither/detectors/all_detectors.py | 2 + .../detectors/assembly/incorrect_return.py | 91 ++++++++++++++++++ .../assembly/return_instead_of_leave.py | 64 ++++++++++++ ...tReturn_0_8_10_incorrect_return_sol__0.txt | 4 + ...OfLeave_0_8_10_incorrect_return_sol__0.txt | 2 + .../0.8.10/incorrect_return.sol | 36 +++++++ .../0.8.10/incorrect_return.sol-0.8.10.zip | Bin 0 -> 2892 bytes .../return-leave/0.8.10/incorrect_return.sol | 8 ++ .../0.8.10/incorrect_return.sol-0.8.10.zip | Bin 0 -> 1445 bytes tests/e2e/detectors/test_detectors.py | 10 ++ tests/e2e/solc_parsing/test_ast_parsing.py | 8 +- 11 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 slither/detectors/assembly/incorrect_return.py create mode 100644 slither/detectors/assembly/return_instead_of_leave.py create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_IncorrectReturn_0_8_10_incorrect_return_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_ReturnInsteadOfLeave_0_8_10_incorrect_return_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol create mode 100644 tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol-0.8.10.zip create mode 100644 tests/e2e/detectors/test_data/return-leave/0.8.10/incorrect_return.sol create mode 100644 tests/e2e/detectors/test_data/return-leave/0.8.10/incorrect_return.sol-0.8.10.zip diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index 57f44bc56..4a111bb64 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -92,3 +92,5 @@ from .functions.cyclomatic_complexity import CyclomaticComplexity from .operations.cache_array_length import CacheArrayLength from .statements.incorrect_using_for import IncorrectUsingFor from .operations.encode_packed import EncodePackedCollision +from .assembly.incorrect_return import IncorrectReturn +from .assembly.return_instead_of_leave import ReturnInsteadOfLeave diff --git a/slither/detectors/assembly/incorrect_return.py b/slither/detectors/assembly/incorrect_return.py new file mode 100644 index 000000000..dc1868e64 --- /dev/null +++ b/slither/detectors/assembly/incorrect_return.py @@ -0,0 +1,91 @@ +from typing import List, Optional + +from slither.core.declarations import SolidityFunction, Function +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.slithir.operations import SolidityCall +from slither.utils.output import Output + + +def _assembly_node(function: Function) -> Optional[SolidityCall]: + """ + Check if there is a node that use return in assembly + + Args: + function: + + Returns: + + """ + + for ir in function.all_slithir_operations(): + if isinstance(ir, SolidityCall) and ir.function == SolidityFunction( + "return(uint256,uint256)" + ): + return ir + return None + + +class IncorrectReturn(AbstractDetector): + """ + Check for cases where a return(a,b) is used in an assembly function + """ + + ARGUMENT = "incorrect-return" + HELP = "If a `return` is incorrectly used in assembly mode." + IMPACT = DetectorClassification.HIGH + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + + WIKI_TITLE = "Incorrect return in assembly" + WIKI_DESCRIPTION = "Detect if `return` in an assembly block halts unexpectedly the execution." + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract C { + function f() internal returns (uint a, uint b) { + assembly { + return (5, 6) + } + } + + function g() returns (bool){ + f(); + return true; + } +} +``` +The return statement in `f` will cause execution in `g` to halt. +The function will return 6 bytes starting from offset 5, instead of returning a boolean.""" + + WIKI_RECOMMENDATION = "Use the `leave` statement." + + # pylint: disable=too-many-nested-blocks + def _detect(self) -> List[Output]: + results: List[Output] = [] + for c in self.contracts: + for f in c.functions_declared: + + for node in f.nodes: + if node.sons: + for function_called in node.internal_calls: + if isinstance(function_called, Function): + found = _assembly_node(function_called) + if found: + + info: DETECTOR_INFO = [ + f, + " calls ", + function_called, + " which halt the execution ", + found.node, + "\n", + ] + json = self.generate_result(info) + + results.append(json) + + return results diff --git a/slither/detectors/assembly/return_instead_of_leave.py b/slither/detectors/assembly/return_instead_of_leave.py new file mode 100644 index 000000000..74c377d40 --- /dev/null +++ b/slither/detectors/assembly/return_instead_of_leave.py @@ -0,0 +1,64 @@ +from typing import List + +from slither.core.declarations import SolidityFunction, Function +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.slithir.operations import SolidityCall +from slither.utils.output import Output + + +class ReturnInsteadOfLeave(AbstractDetector): + """ + Check for cases where a return(a,b) is used in an assembly function that also returns two variables + """ + + ARGUMENT = "return-leave" + HELP = "If a `return` is used instead of a `leave`." + IMPACT = DetectorClassification.HIGH + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + + WIKI_TITLE = "Return instead of leave in assembly" + WIKI_DESCRIPTION = "Detect if a `return` is used where a `leave` should be used." + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract C { + function f() internal returns (uint a, uint b) { + assembly { + return (5, 6) + } + } + +} +``` +The function will halt the execution, instead of returning a two uint.""" + + WIKI_RECOMMENDATION = "Use the `leave` statement." + + def _check_function(self, f: Function) -> List[Output]: + results: List[Output] = [] + + for node in f.nodes: + for ir in node.irs: + if isinstance(ir, SolidityCall) and ir.function == SolidityFunction( + "return(uint256,uint256)" + ): + info: DETECTOR_INFO = [f, " contains an incorrect call to return: ", node, "\n"] + json = self.generate_result(info) + + results.append(json) + return results + + def _detect(self) -> List[Output]: + results: List[Output] = [] + for c in self.contracts: + for f in c.functions_declared: + + if len(f.returns) == 2 and f.contains_assembly: + results += self._check_function(f) + + return results diff --git a/tests/e2e/detectors/snapshots/detectors__detector_IncorrectReturn_0_8_10_incorrect_return_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_IncorrectReturn_0_8_10_incorrect_return_sol__0.txt new file mode 100644 index 000000000..5d87cd932 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_IncorrectReturn_0_8_10_incorrect_return_sol__0.txt @@ -0,0 +1,4 @@ +C.bad1() (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#21-24) calls C.indirect() (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#17-19) which halt the execution return(uint256,uint256)(5,6) (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#4) + +C.bad0() (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#8-11) calls C.internal_return() (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#2-6) which halt the execution return(uint256,uint256)(5,6) (tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol#4) + diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ReturnInsteadOfLeave_0_8_10_incorrect_return_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ReturnInsteadOfLeave_0_8_10_incorrect_return_sol__0.txt new file mode 100644 index 000000000..28f579f81 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_ReturnInsteadOfLeave_0_8_10_incorrect_return_sol__0.txt @@ -0,0 +1,2 @@ +C.f() (tests/e2e/detectors/test_data/return-leave/0.8.10/incorrect_return.sol#3-7) contains an incorrect call to return: return(uint256,uint256)(5,6) (tests/e2e/detectors/test_data/return-leave/0.8.10/incorrect_return.sol#5) + diff --git a/tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol b/tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol new file mode 100644 index 000000000..e81a747ba --- /dev/null +++ b/tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol @@ -0,0 +1,36 @@ +contract C { + function internal_return() internal{ + assembly { + return (5, 6) + } + } + + function bad0() public returns (bool){ + internal_return(); + return true; + } + + function indirect2() internal { + internal_return(); + } + + function indirect() internal { + indirect2(); + } + + function bad1() public returns (bool){ + indirect(); + return true; + } + + function good0() public{ + // Dont report if there is no following operation + internal_return(); + } + + function good1() public returns (uint a, uint b){ + assembly { + return (5, 6) + } + } +} \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol-0.8.10.zip b/tests/e2e/detectors/test_data/incorrect-return/0.8.10/incorrect_return.sol-0.8.10.zip new file mode 100644 index 0000000000000000000000000000000000000000..2491a10a6554d40be21373fc9f7eeb55ceb9f46e GIT binary patch literal 2892 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py index 6fc04e4e1..9ca1bfcde 100644 --- a/tests/e2e/detectors/test_detectors.py +++ b/tests/e2e/detectors/test_detectors.py @@ -1654,6 +1654,16 @@ ALL_TESTS = [ "encode_packed_collision.sol", "0.7.6", ), + Test( + all_detectors.IncorrectReturn, + "incorrect_return.sol", + "0.8.10", + ), + Test( + all_detectors.ReturnInsteadOfLeave, + "incorrect_return.sol", + "0.8.10", + ), ] GENERIC_PATH = "/GENERIC_PATH" diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index 2da4cf1e2..37f6d7274 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -4,13 +4,13 @@ import re import sys from pathlib import Path from typing import List, Dict, Tuple -from packaging.version import parse as parse_version -import pytest + +from crytic_compile import CryticCompile, save_to_zip +from crytic_compile.utils.zip import load_from_zip from deepdiff import DeepDiff +from packaging.version import parse as parse_version from solc_select.solc_select import install_artifacts as install_solc_versions from solc_select.solc_select import installed_versions as get_installed_solc_versions -from crytic_compile import CryticCompile, save_to_zip -from crytic_compile.utils.zip import load_from_zip from slither import Slither from slither.printers.guidance.echidna import Echidna From 561a6f88d01ba4f3478dc12c74a63ed9b70f336c Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 5 Oct 2023 15:01:35 +0200 Subject: [PATCH 261/338] Update slither/detectors/assembly/incorrect_return.py Co-authored-by: alpharush <0xalpharush@protonmail.com> --- slither/detectors/assembly/incorrect_return.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/assembly/incorrect_return.py b/slither/detectors/assembly/incorrect_return.py index dc1868e64..f5f0a98d9 100644 --- a/slither/detectors/assembly/incorrect_return.py +++ b/slither/detectors/assembly/incorrect_return.py @@ -67,7 +67,7 @@ The function will return 6 bytes starting from offset 5, instead of returning a def _detect(self) -> List[Output]: results: List[Output] = [] for c in self.contracts: - for f in c.functions_declared: + for f in c.functions_and_modifiers_declared: for node in f.nodes: if node.sons: From 1cdb2022cbe778fbe7d0a021a0f1241aceb11c14 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Thu, 5 Oct 2023 22:54:10 -0400 Subject: [PATCH 262/338] address issue #2127 and allow function parameter name to be empty when casting to string --- slither/core/variables/variable.py | 1 - .../test_contract_data/test_contract_data.sol | 5 +++++ tests/e2e/compilation/test_resolution.py | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/e2e/compilation/test_data/test_contract_data/test_contract_data.sol diff --git a/slither/core/variables/variable.py b/slither/core/variables/variable.py index 2b777e672..1afcc4757 100644 --- a/slither/core/variables/variable.py +++ b/slither/core/variables/variable.py @@ -179,5 +179,4 @@ class Variable(SourceMapping): return f'{name}({",".join(parameters)})' def __str__(self) -> str: - assert self._name return self._name diff --git a/tests/e2e/compilation/test_data/test_contract_data/test_contract_data.sol b/tests/e2e/compilation/test_data/test_contract_data/test_contract_data.sol new file mode 100644 index 000000000..a99001da3 --- /dev/null +++ b/tests/e2e/compilation/test_data/test_contract_data/test_contract_data.sol @@ -0,0 +1,5 @@ +contract TestSlither { + function testFunction(uint256 param1, uint256, address param3) public { + + } +} \ No newline at end of file diff --git a/tests/e2e/compilation/test_resolution.py b/tests/e2e/compilation/test_resolution.py index 71edaa143..479e87d4a 100644 --- a/tests/e2e/compilation/test_resolution.py +++ b/tests/e2e/compilation/test_resolution.py @@ -43,3 +43,18 @@ def test_cycle(solc_binary_path) -> None: solc_path = solc_binary_path("0.8.0") slither = Slither(Path(TEST_DATA_DIR, "test_cyclic_import", "a.sol").as_posix(), solc=solc_path) _run_all_detectors(slither) + + +def test_contract_function_parameter(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.0") + standard_json = SolcStandardJson() + standard_json.add_source_file( + Path(TEST_DATA_DIR, "test_contract_data", "test_contract_data.sol").as_posix() + ) + compilation = CryticCompile(standard_json, solc=solc_path) + slither = Slither(compilation) + contract = slither.contracts[0] + + for function in contract.functions: + for parameter in function.parameters: + str(parameter) From 8feb4943d9a5e8bba3435544e4e2277fa63a9809 Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Fri, 6 Oct 2023 10:43:15 -0400 Subject: [PATCH 263/338] Update test to assert expected parameter names --- tests/e2e/compilation/test_resolution.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/e2e/compilation/test_resolution.py b/tests/e2e/compilation/test_resolution.py index 479e87d4a..af7cbe2c7 100644 --- a/tests/e2e/compilation/test_resolution.py +++ b/tests/e2e/compilation/test_resolution.py @@ -54,7 +54,9 @@ def test_contract_function_parameter(solc_binary_path) -> None: compilation = CryticCompile(standard_json, solc=solc_path) slither = Slither(compilation) contract = slither.contracts[0] + function = contract.functions[0] + parameters = function.parameters - for function in contract.functions: - for parameter in function.parameters: - str(parameter) + assert (parameters[0].name == 'param1') + assert (parameters[1].name == '') + assert (parameters[2].name == 'param3') From e11580f188f3a786f5df07ba24f8fa98c3793dae Mon Sep 17 00:00:00 2001 From: Judy Wu Date: Sat, 7 Oct 2023 23:44:01 -0400 Subject: [PATCH 264/338] fix: resolve state variable access in inherited internal functions from derived contracts, closes #1654 --- slither/solc_parsing/yul/parse_yul.py | 2 +- .../test_data/assembly_storage_slot.sol | 18 +++++++++ .../slithir/test_yul_parser_assembly_slot.py | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/unit/slithir/test_data/assembly_storage_slot.sol create mode 100644 tests/unit/slithir/test_yul_parser_assembly_slot.py diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 8657947ea..cf942ea59 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -748,7 +748,7 @@ def parse_yul_function_call(root: YulScope, node: YulNode, ast: Dict) -> Optiona def _check_for_state_variable_name(root: YulScope, potential_name: str) -> Optional[Identifier]: root_function = root.function if isinstance(root_function, FunctionContract): - var = root_function.contract.get_state_variable_from_name(potential_name) + var = root_function.contract_declarer.get_state_variable_from_name(potential_name) if var: return Identifier(var) return None diff --git a/tests/unit/slithir/test_data/assembly_storage_slot.sol b/tests/unit/slithir/test_data/assembly_storage_slot.sol new file mode 100644 index 000000000..244f24fe6 --- /dev/null +++ b/tests/unit/slithir/test_data/assembly_storage_slot.sol @@ -0,0 +1,18 @@ +contract YYY { + mapping(address => uint256) private _counters; + function _getPackedBucketGlobalState(uint256 bucketId) internal view returns (uint256 packedGlobalState) { + assembly { + mstore(0x0, bucketId) + mstore(0x20, _counters.slot) + let slot := keccak256(0x0, 0x40) + packedGlobalState := sload(slot) + } + } +} + + +contract XXX is YYY { + function getPackedBucketGlobalState(uint256 bucketId) external { + _getPackedBucketGlobalState(bucketId); + } +} \ No newline at end of file diff --git a/tests/unit/slithir/test_yul_parser_assembly_slot.py b/tests/unit/slithir/test_yul_parser_assembly_slot.py new file mode 100644 index 000000000..d1bb5bb40 --- /dev/null +++ b/tests/unit/slithir/test_yul_parser_assembly_slot.py @@ -0,0 +1,39 @@ +from pathlib import Path +from slither import Slither + +from slither.core.expressions import CallExpression +from slither.core.expressions.identifier import Identifier +from slither.core.expressions.literal import Literal +from slither.core.variables.state_variable import StateVariable +from slither.core.variables.local_variable import LocalVariable + + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" + + +def test_yul_parser_assembly_slot(solc_binary_path) -> None: + # mstore(0x0, bucketId) + # mstore(0x20, _counters.slot) + data = { + '0x0': 'bucketId', + '0x20': '_counters' + } + + solc_path = solc_binary_path("0.8.18") + slither = Slither(Path(TEST_DATA_DIR, "assembly_storage_slot.sol").as_posix(), solc=solc_path) + + contract = slither.get_contract_from_name('XXX')[0] + func = contract.get_function_from_full_name('getPackedBucketGlobalState(uint256)') + calls = [node.expression for node in func.all_nodes() if node.expression and 'mstore' in str(node.expression)] + + for call in calls: + assert isinstance(call, CallExpression) + memory_location = call.arguments[0] + value = call.arguments[1] + assert isinstance(memory_location, Literal) + assert isinstance(value, Identifier) + assert value.value.name == data[memory_location.value] + if value.value.name == '_counters': + assert isinstance(value.value, StateVariable) + elif value.value.name == 'bucketId': + assert isinstance(value.value, LocalVariable) From 4d738ec358c394d7cf7d056d0095ce2673f50166 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 11 Oct 2023 09:56:10 +0200 Subject: [PATCH 265/338] Minor --- slither/detectors/assembly/return_instead_of_leave.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/slither/detectors/assembly/return_instead_of_leave.py b/slither/detectors/assembly/return_instead_of_leave.py index 74c377d40..a1591d834 100644 --- a/slither/detectors/assembly/return_instead_of_leave.py +++ b/slither/detectors/assembly/return_instead_of_leave.py @@ -58,7 +58,11 @@ The function will halt the execution, instead of returning a two uint.""" for c in self.contracts: for f in c.functions_declared: - if len(f.returns) == 2 and f.contains_assembly: + if ( + len(f.returns) == 2 + and f.contains_assembly + and f.visibility not in ["public", "external"] + ): results += self._check_function(f) return results From f7ab4a734fb93433eca7afa4e867acafbeb05605 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 11 Oct 2023 10:12:41 +0200 Subject: [PATCH 266/338] Add incorrect-exp detector --- slither/detectors/operations/incorrect_exp.py | 0 ...onentiation_0_7_6_incorrect_exp_sol__0.txt | 9 ++++++ .../incorrect-exp/0.7.6/incorrect_exp.sol | 30 ++++++++++++++++++ .../0.7.6/incorrect_exp.sol-0.7.6.zip | Bin 0 -> 2473 bytes 4 files changed, 39 insertions(+) create mode 100644 slither/detectors/operations/incorrect_exp.py create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_IncorrectOperatorExponentiation_0_7_6_incorrect_exp_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol create mode 100644 tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol-0.7.6.zip diff --git a/slither/detectors/operations/incorrect_exp.py b/slither/detectors/operations/incorrect_exp.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e/detectors/snapshots/detectors__detector_IncorrectOperatorExponentiation_0_7_6_incorrect_exp_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_IncorrectOperatorExponentiation_0_7_6_incorrect_exp_sol__0.txt new file mode 100644 index 000000000..458dd3bdc --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_IncorrectOperatorExponentiation_0_7_6_incorrect_exp_sol__0.txt @@ -0,0 +1,9 @@ +Test.bad1() (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#9-12) has bitwise-xor operator ^ instead of the exponentiation operator **: + - UINT_MAX = 2 ^ 256 - 1 (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#10) + +Test.bad0(uint256) (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#5-7) has bitwise-xor operator ^ instead of the exponentiation operator **: + - a ^ 2 (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#6) + +Derived.slitherConstructorVariables() (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#30) has bitwise-xor operator ^ instead of the exponentiation operator **: + - my_var = 2 ^ 256 - 1 (tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol#3) + diff --git a/tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol b/tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol new file mode 100644 index 000000000..b930ee5c1 --- /dev/null +++ b/tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol @@ -0,0 +1,30 @@ +contract Test { + + uint my_var = 2 ^ 256-1; + + function bad0(uint a) internal returns (uint) { + return a^2; + } + + function bad1() internal returns (uint) { + uint UINT_MAX = 2^256-1; + return UINT_MAX; + } + + /* Correct exponentiation operator */ + function good0(uint a) internal returns (uint) { + return a**2; + } + + /* Neither operand is a constant */ + function good1(uint a) internal returns (uint) { + return a^a; + } + + /* The constant operand 0xff in hex typically means bitwise xor */ + function good2(uint a) internal returns (uint) { + return a^0xff; + } +} + +contract Derived is Test {} diff --git a/tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol-0.7.6.zip b/tests/e2e/detectors/test_data/incorrect-exp/0.7.6/incorrect_exp.sol-0.7.6.zip new file mode 100644 index 0000000000000000000000000000000000000000..c6fea01511ee4ecf31db7b382c3ca0f81ef8bd15 GIT binary patch literal 2473 zcma);`8U)H1IE80#!|+f7=|$n*~z|4Mac-mMY0YivKz~_G_sGx*hSYi3Af>52-$VZ zmUZk)MpE`QveR4d@9#P9^Zf8R&pFQ@@G(WvGw1?zz-2%ajk21?2^5}z03g~30N?-s zJo0w-!QrsZ0S?$;Us-=2&)@XH1vp@E&Tfx_u(Iy{KHkg>7Xdo}hyVcX_;^>PQzbvr z@IamBrQ8nhNANbG*d(*7I>HnFExZc5tA(F|rHkV~MlaLp;je?<-aOxsjfTl}^s>-t zUqr-no=ivx42eD3RF{{h7|4x0u0MU(@a!X`poZ9=ZhDxN!92n_;}W#BMNUXsec^bE z#fu|Xn&`Kleyu<%PBN1usF!TSz(a80d%mR5qHGGLSKPjW)o?J^2nW#P5_*+Syx(uE4Z7ec(nf3?Y`oDLXNx8+Ey!MU?w+rKBIzp5@Eq5U7-;Ub1f)G8U54_02*F|7zJKra3|~b`zgTGEkVZ zC7t&F*wo&wWcMeo!Ly<}h2&J&n&au0KX-^(I6Se@F-P2Rrl5+nSvQW|WYC?pv{Nsi z2*gsWpNgtd{iFuh__QY_nTYTC(0^a%>~E)GlP8GTQ^6;6q`MTGj&OzQxuh zl$YpUaj$NSNA7EqnckDMEw@GgnM?7lYh7G2o;dFZp}y_PsQq?%Bv`pP>dhKWEVCL^&ATIw;={?s)hmzm<ort6JLG7eTx=o7pz}Bq_UqKY_c&e0HJoFWQcoew-`U=26qbI7i_oF!yRMN((lVirZ{TO4}6JDWv%)Bs#<>PZ>102Sq z%TfT|)yQpy+M9C;PR%vkOYO1Q3+A?uA3W{6`ubgwd#7uwqg}WVw?oXIyth(43s;(j z@Dfs z5{83?1#{6eT;xY;f}k0cA@c7z3^$zceB~&phNun@bKDx-L_aC8;Gip8_-xR#q!Cv> z2h#q)cXtVzG!{EaiJE2jk$eij{^@S2k|^)l$I(IT2-M5+s1VkT?DoiySqwUKajJf& zXj>lk2ZXoPZHr6`Hl4HRUl-b-=a`b2*d|oO@Kli}r~8*<_&yw2ps6Pu*l5w4Mos+| zN*x>AHC&)?&-oU$+sR1O$v*Ao{wB8>Bc9|dG~qO<&|Z>7%=W*PZ@g4uQ|>nHEFB4^ zeuiPn?h z@j&7xSR|D0umM`S!n)Z49SLCk7V6csKI~{{Qt;D7(P8aHHt4m-0GraKUGEWW`d!{& zW;lx7Lp{7>UGGh!Kcn|DeN7g{<|s6+iGbhydFL^ha~OFoHw{q`9z57Fg6@}_qw%x) zx1e6mUGG!TVu~v|!HUI6J$2y1oP>Kl%cfNYmS#AD?{yq)$IWMicDUYd@*e%F{ZtVx zbmd_D==|WWGif_?3_l2JC_FTCK6Q{zZPFDQUlo$ciqi(t1lgxmk}nr9BEzGFpQF zBnQ$nQ1DtwfB0Q#EZ%pWw+-~u{fDou?X3-Q+hr2!GTyEsfPOtgP90;+F|D~rUriNy zoJO%z(n=(C5v(%aERZJ%rNsk0oraPVn-MxNabK?C1=PZC0(lcFC`a_(uu`}kE; zLY5uC+TH`gpBGxgGovbx@Ivf7bBSxm%0J+`NFT7|00t4_xcY(s-6r0 literal 0 HcmV?d00001 From 4d1d32b63fd06eeba69af35cd64680bfa2338167 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 11 Oct 2023 10:22:27 +0200 Subject: [PATCH 267/338] Add tautological-compare --- slither/detectors/all_detectors.py | 2 + slither/detectors/operations/incorrect_exp.py | 93 ++++++++++++++++++ .../statements/tautological_compare.py | 69 +++++++++++++ .../tautological-compare/0.8.20/compare.sol | 6 ++ .../0.8.20/compare.sol-0.8.20.zip | Bin 0 -> 2032 bytes tests/e2e/detectors/test_detectors.py | 10 ++ 6 files changed, 180 insertions(+) create mode 100644 slither/detectors/statements/tautological_compare.py create mode 100644 tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol create mode 100644 tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol-0.8.20.zip diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index 4a111bb64..97622f887 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -94,3 +94,5 @@ from .statements.incorrect_using_for import IncorrectUsingFor from .operations.encode_packed import EncodePackedCollision from .assembly.incorrect_return import IncorrectReturn from .assembly.return_instead_of_leave import ReturnInsteadOfLeave +from .operations.incorrect_exp import IncorrectOperatorExponentiation +from .statements.tautological_compare import TautologicalCompare diff --git a/slither/detectors/operations/incorrect_exp.py b/slither/detectors/operations/incorrect_exp.py index e69de29bb..6188f5cb1 100644 --- a/slither/detectors/operations/incorrect_exp.py +++ b/slither/detectors/operations/incorrect_exp.py @@ -0,0 +1,93 @@ +""" +Module detecting incorrect operator usage for exponentiation where bitwise xor '^' is used instead of '**' +""" +from typing import Tuple, List, Union + +from slither.core.cfg.node import Node +from slither.core.declarations import Contract, Function +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.slithir.operations import Binary, BinaryType, Operation +from slither.slithir.utils.utils import RVALUE +from slither.slithir.variables.constant import Constant +from slither.utils.output import Output + + +def _is_constant_candidate(var: Union[RVALUE, Function]) -> bool: + """ + Check if the variable is a constant. + Do not consider variable that are expressed with hexadecimal. + Something like 2^0xf is likely to be a correct bitwise operator + :param var: + :return: + """ + return isinstance(var, Constant) and not var.original_value.startswith("0x") + + +def _is_bitwise_xor_on_constant(ir: Operation) -> bool: + return ( + isinstance(ir, Binary) + and ir.type == BinaryType.CARET + and (_is_constant_candidate(ir.variable_left) or _is_constant_candidate(ir.variable_right)) + ) + + +def _detect_incorrect_operator(contract: Contract) -> List[Tuple[Function, Node]]: + ret: List[Tuple[Function, Node]] = [] + f: Function + for f in contract.functions + contract.modifiers: # type:ignore + # Heuristic: look for binary expressions with ^ operator where at least one of the operands is a constant, and + # the constant is not in hex, because hex typically is used with bitwise xor and not exponentiation + nodes = [node for node in f.nodes for ir in node.irs if _is_bitwise_xor_on_constant(ir)] + for node in nodes: + ret.append((f, node)) + return ret + + +# pylint: disable=too-few-public-methods +class IncorrectOperatorExponentiation(AbstractDetector): + """ + Incorrect operator usage of bitwise xor mistaking it for exponentiation + """ + + ARGUMENT = "incorrect-exp" + HELP = "Incorrect exponentiation" + IMPACT = DetectorClassification.HIGH + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation" + + WIKI_TITLE = "Incorrect exponentiation" + WIKI_DESCRIPTION = "Detect use of bitwise `xor ^` instead of exponential `**`" + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract Bug{ + uint UINT_MAX = 2^256 - 1; + ... +} +``` +Alice deploys a contract in which `UINT_MAX` incorrectly uses `^` operator instead of `**` for exponentiation""" + + WIKI_RECOMMENDATION = "Use the correct operator `**` for exponentiation." + + def _detect(self) -> List[Output]: + """Detect the incorrect operator usage for exponentiation where bitwise xor ^ is used instead of ** + + Returns: + list: (function, node) + """ + results: List[Output] = [] + for c in self.compilation_unit.contracts_derived: + res = _detect_incorrect_operator(c) + for (func, node) in res: + info: DETECTOR_INFO = [ + func, + " has bitwise-xor operator ^ instead of the exponentiation operator **: \n", + ] + info += ["\t - ", node, "\n"] + results.append(self.generate_result(info)) + + return results diff --git a/slither/detectors/statements/tautological_compare.py b/slither/detectors/statements/tautological_compare.py new file mode 100644 index 000000000..0dc34b582 --- /dev/null +++ b/slither/detectors/statements/tautological_compare.py @@ -0,0 +1,69 @@ +from typing import List +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.slithir.operations import ( + Binary, + BinaryType, +) + +from slither.core.declarations import Function +from slither.utils.output import Output + + +class TautologicalCompare(AbstractDetector): + """ + Same variable comparison detector + """ + + ARGUMENT = "tautological-compare" + HELP = "Comparing a variable to itself always returns true or false, depending on comparison" + IMPACT = DetectorClassification.MEDIUM + CONFIDENCE = DetectorClassification.HIGH + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#tautological-compare" + + WIKI_TITLE = "Tautological compare" + WIKI_DESCRIPTION = "A variable compared to itself is probably an error as it will always return `true` for `==`, `>=`, `<=` and always `false` for `<`, `>` and `!=`." + WIKI_EXPLOIT_SCENARIO = """ +```solidity + function check(uint a) external returns(bool){ + return (a >= a); + } +``` +`check` always return true.""" + + WIKI_RECOMMENDATION = "Remove comparison or compare to different value." + + def _check_function(self, f: Function) -> List[Output]: + affected_nodes = set() + for node in f.nodes: + for ir in node.irs: + if isinstance(ir, Binary): + if ir.type in [ + BinaryType.GREATER, + BinaryType.GREATER_EQUAL, + BinaryType.LESS, + BinaryType.LESS_EQUAL, + BinaryType.EQUAL, + BinaryType.NOT_EQUAL, + ]: + if ir.variable_left == ir.variable_right: + affected_nodes.add(node) + + results = [] + for n in affected_nodes: + info: DETECTOR_INFO = [f, " compares a variable to itself:\n\t", n, "\n"] + res = self.generate_result(info) + results.append(res) + return results + + def _detect(self): + results = [] + + for f in self.compilation_unit.functions_and_modifiers: + results.extend(self._check_function(f)) + + return results diff --git a/tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol b/tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol new file mode 100644 index 000000000..ede2f0fc1 --- /dev/null +++ b/tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol @@ -0,0 +1,6 @@ + +contract A{ + function check(uint a) external returns(bool){ + return (a >= a); + } +} \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol-0.8.20.zip b/tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol-0.8.20.zip new file mode 100644 index 0000000000000000000000000000000000000000..05b78fad0871c604d79bcb87bb5f0eeedc3d9cea GIT binary patch literal 2032 zcmai#Ydq5n1IPb!zvQ|~mSgS;F_(o!ZiUX!TneqR4(58yZA3)I*$fpO#By1YCYR){ z4JnkJL<%7?xuhl6i5XAldH;N#-|xlu&F}5+^F<*Ag{%MpKpME}hV&F8q}*yfd%1_&G*s*XOiGzt+spL^@-{RJuC?U zOW|W=dETh@(Ls&iWpfy;frU3%KGpG*H;lXJ;86DmMT}pba9fAb#e5Hm9%^zgfToc6 zeu~N2E1ww0{(@Ps42^Yf$2D|g#9y@4MDs+O|Fqn^VRM^E%HH&T%5_aPyWHNNZp00m zZ<*6Hk!ly;mRU&1!COHSR6i-ogDY_>CkmXh+ov7f)iHCqp?-W&2c-%d|4fZ%Uq2Iv zGg>Np8MtwB$PTSkW?6KI8RY2P;b)T|hYQgcOpQ^(EO5EVxBj7>u zD^itIwwv>j0A9^c};AP!!gw z5|^os{ZO)YdnoVH=Ymad?uJe=?UI*914S{~?{*j(D>Op-w z4FVU-y+7=BCxGVM1^ih*KfqcDtFjKL`!0g?UOoALyjH52UfP-uH*`bYyBG-i#-M^ZG#jhJB8@bFWJTTW?R7irU|p`e^th7~%27IX7MGOUX+_HD?x&A4`=n-X2}f3#oc9*a~C44wG(|jA`6S0dhJb%-AwTKH;3K-A6dyZ}lT? ztGRHH0s9s-$gR*pw`y`hfhY-bRV|+No>DX-=hXMOjKPdYjiIS~mz1kVH@dczo%JK1 zXMy&j3Jq(i6{qcU*0bug!bU2Q?Dm<(i>UJ5io2+>eaS`aFr{z7PGiwG{-6p<)LeXt z6Ca-m|5WEn|LsU+t&dX;0U_soyn<1m#pPbGzehz`usV<9Njov;&}b`f2=3%tQ|(nO zartbkKD75Jjh)ctP>?JhZg*WPU7lt6BQNKNx-31ZqtaN}WQV_z+4%E?$BVThMNal7 z0oB!)0BrB{iu+~4-oqB%yl+(;uM(Vs(V-$ArROA*DhQ_8e)Bc5v4E6kr^yJx%=eFF zs&!scO_ZpgLx2N=ZhF7SbvV}=u*4gW5DXYHT)Jf*=xN#!G1B{GsX0FW2;l@}j+tO$ z8N-?0?lU$0=NmXE`A6uiS1#~!@Na9meU&L9aXf*c;&^u)Rjy}Xq3>5V5i9aXE{;BS z+>9m`?yCki2b64uFSAhZl z)TnTxb<0|q6I`z(P5QtaO7vL*FW=xBC2fF1b#YUbAy~}B38exy*OGajmTit|-%7*n zRIdB)U)3N_e-=<$hln;z*&Q-_9ahu0R@QX5ME((#oc>@@07a8Bt(<^qkNO zwpC1Ble02@3dL(SmJ2+CxnA2ox#GT03uP^j`&wT=@ar^c<4!#n=`~Y_E5VLn!7H&O zxS1*@(hQ1OT9}z_L$5OjGz?gf)bKE;vT)aek~}R5C!s{xW33bqx}(|v+nukvBg%QY zk;HXQ(2ud5bL(W08`xaC=}_BtjqPZIZnsgs2>Q(qFe$$_V@k z#=(Q>^(XF=15FMz5cWLGd^Rbzwe1JU_N+VxUy;+2k*1PSxPFzdH@R;9I1xN)h(0gW z>hY+B#Ay0HiPxPheus=?A5KU0w{`7gzA5mX;k*w>$+YVYNTU$rl!M>(7I@X7X)%>0IU=`u< z6}c5DKG=N08qNfNeZ}14t6ig_kRSmo!T+t}Uq=3KQb7OW|Hv7I6c+h+2KrU!U(EjH HbpZGeo!!Aw literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py index 9ca1bfcde..99e9095ff 100644 --- a/tests/e2e/detectors/test_detectors.py +++ b/tests/e2e/detectors/test_detectors.py @@ -1664,6 +1664,16 @@ ALL_TESTS = [ "incorrect_return.sol", "0.8.10", ), + Test( + all_detectors.IncorrectOperatorExponentiation, + "incorrect_exp.sol", + "0.7.6", + ), + Test( + all_detectors.TautologicalCompare, + "compare.sol", + "0.8.20", + ), ] GENERIC_PATH = "/GENERIC_PATH" From 538539ba9e9eb97a3ffbba87e181cb8118d40df7 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 11 Oct 2023 10:32:42 +0200 Subject: [PATCH 268/338] Add return-bomb detector --- slither/detectors/all_detectors.py | 1 + slither/detectors/statements/return_bomb.py | 123 ++++++++++++++++++ ...r_ReturnBomb_0_8_20_return_bomb_sol__0.txt | 5 + ...tologicalCompare_0_8_20_compare_sol__0.txt | 3 + .../return-bomb/0.8.20/return_bomb.sol | 57 ++++++++ .../0.8.20/return_bomb.sol-0.8.20.zip | Bin 0 -> 7966 bytes tests/e2e/detectors/test_detectors.py | 5 + 7 files changed, 194 insertions(+) create mode 100644 slither/detectors/statements/return_bomb.py create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_ReturnBomb_0_8_20_return_bomb_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_TautologicalCompare_0_8_20_compare_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol create mode 100644 tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol-0.8.20.zip diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index 97622f887..fab9562d2 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -96,3 +96,4 @@ from .assembly.incorrect_return import IncorrectReturn from .assembly.return_instead_of_leave import ReturnInsteadOfLeave from .operations.incorrect_exp import IncorrectOperatorExponentiation from .statements.tautological_compare import TautologicalCompare +from .statements.return_bomb import ReturnBomb diff --git a/slither/detectors/statements/return_bomb.py b/slither/detectors/statements/return_bomb.py new file mode 100644 index 000000000..8b6cd07a2 --- /dev/null +++ b/slither/detectors/statements/return_bomb.py @@ -0,0 +1,123 @@ +from typing import List + +from slither.core.cfg.node import Node +from slither.core.declarations import Contract +from slither.core.declarations.function import Function +from slither.core.solidity_types import Type +from slither.detectors.abstract_detector import ( + AbstractDetector, + DetectorClassification, + DETECTOR_INFO, +) +from slither.slithir.operations import LowLevelCall, HighLevelCall +from slither.analyses.data_dependency.data_dependency import is_tainted +from slither.utils.output import Output + + +class ReturnBomb(AbstractDetector): + + ARGUMENT = "return-bomb" + HELP = "A low level callee may consume all callers gas unexpectedly." + IMPACT = DetectorClassification.LOW + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#return-bomb" + + WIKI_TITLE = "Return Bomb" + WIKI_DESCRIPTION = "A low level callee may consume all callers gas unexpectedly." + WIKI_EXPLOIT_SCENARIO = """ +```solidity +//Modified from https://github.com/nomad-xyz/ExcessivelySafeCall +contract BadGuy { + function youveActivateMyTrapCard() external pure returns (bytes memory) { + assembly{ + revert(0, 1000000) + } + } +} + +contract Mark { + function oops(address badGuy) public{ + bool success; + bytes memory ret; + + // Mark pays a lot of gas for this copy + //(success, ret) = badGuy.call{gas:10000}( + (success, ret) = badGuy.call( + abi.encodeWithSelector( + BadGuy.youveActivateMyTrapCard.selector + ) + ); + + // Mark may OOG here, preventing local state changes + //importantCleanup(); + } +} + +``` +After Mark calls BadGuy bytes are copied from returndata to memory, the memory expansion cost is paid. This means that when using a standard solidity call, the callee can "returnbomb" the caller, imposing an arbitrary gas cost. +Callee unexpectedly makes the caller OOG. +""" + + WIKI_RECOMMENDATION = "Avoid unlimited implicit decoding of returndata." + + @staticmethod + def is_dynamic_type(ty: Type) -> bool: + # ty.is_dynamic ? + name = str(ty) + if "[]" in name or name in ("bytes", "string"): + return True + return False + + def get_nodes_for_function(self, function: Function, contract: Contract) -> List[Node]: + nodes = [] + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, (HighLevelCall, LowLevelCall)): + if not is_tainted(ir.destination, contract): # type:ignore + # Only interested if the target address is controlled/tainted + continue + + if isinstance(ir, HighLevelCall) and isinstance(ir.function, Function): + # in normal highlevel calls return bombs are _possible_ + # if the return type is dynamic and the caller tries to copy and decode large data + has_dyn = False + if ir.function.return_type: + has_dyn = any( + self.is_dynamic_type(ty) for ty in ir.function.return_type + ) + + if not has_dyn: + continue + + # If a gas budget was specified then the + # user may not know about the return bomb + if ir.call_gas is None: + # if a gas budget was NOT specified then the caller + # may already suspect the call may spend all gas? + continue + + nodes.append(node) + # TODO: check that there is some state change after the call + + return nodes + + def _detect(self) -> List[Output]: + results = [] + + for contract in self.compilation_unit.contracts: + for function in contract.functions_declared: + nodes = self.get_nodes_for_function(function, contract) + if nodes: + info: DETECTOR_INFO = [ + function, + " tries to limit the gas of an external call that controls implicit decoding\n", + ] + + for node in sorted(nodes, key=lambda x: x.node_id): + info += ["\t", node, "\n"] + + res = self.generate_result(info) + results.append(res) + + return results diff --git a/tests/e2e/detectors/snapshots/detectors__detector_ReturnBomb_0_8_20_return_bomb_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_ReturnBomb_0_8_20_return_bomb_sol__0.txt new file mode 100644 index 000000000..f53b5233f --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_ReturnBomb_0_8_20_return_bomb_sol__0.txt @@ -0,0 +1,5 @@ +Mark.oops(address) (tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol#31-55) tries to limit the gas of an external call that controls implicit decoding + ret1 = BadGuy(badGuy).fbad{gas: 2000}() (tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol#42) + (x,str) = BadGuy(badGuy).fbad1{gas: 2000}() (tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol#44) + (success,ret) = badGuy.call{gas: 10000}(abi.encodeWithSelector(BadGuy.llbad.selector)) (tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol#47-51) + diff --git a/tests/e2e/detectors/snapshots/detectors__detector_TautologicalCompare_0_8_20_compare_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_TautologicalCompare_0_8_20_compare_sol__0.txt new file mode 100644 index 000000000..76685043c --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_TautologicalCompare_0_8_20_compare_sol__0.txt @@ -0,0 +1,3 @@ +A.check(uint256) (tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol#3-5) compares a variable to itself: + (a >= a) (tests/e2e/detectors/test_data/tautological-compare/0.8.20/compare.sol#4) + diff --git a/tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol b/tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol new file mode 100644 index 000000000..76413fdca --- /dev/null +++ b/tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol @@ -0,0 +1,57 @@ +contract BadGuy { + function llbad() external pure returns (bytes memory) { + assembly{ + revert(0, 1000000) + } + } + + function fgood() external payable returns (uint){ + assembly{ + return(0, 1000000) + } + } + + function fbad() external payable returns (uint[] memory){ + assembly{ + return(0, 1000000) + } + } + + function fbad1() external payable returns (uint, string memory){ + assembly{ + return(0, 1000000) + } + } + + +} + +contract Mark { + + function oops(address badGuy) public{ + bool success; + string memory str; + bytes memory ret; + uint x; + uint[] memory ret1; + + x = BadGuy(badGuy).fgood{gas:2000}(); + + ret1 = BadGuy(badGuy).fbad(); //good (no gas specified) + + ret1 = BadGuy(badGuy).fbad{gas:2000}(); + + (x, str) = BadGuy(badGuy).fbad1{gas:2000}(); + + // Mark pays a lot of gas for this copy 😬😬😬 + (success, ret) = badGuy.call{gas:10000}( + abi.encodeWithSelector( + BadGuy.llbad.selector + ) + ); + + // Mark may OOG here, preventing local state changes + //importantCleanup(); + } +} + diff --git a/tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol-0.8.20.zip b/tests/e2e/detectors/test_data/return-bomb/0.8.20/return_bomb.sol-0.8.20.zip new file mode 100644 index 0000000000000000000000000000000000000000..4c10ea6fea0dfc804d3fef44769721e1be8d5765 GIT binary patch literal 7966 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 Date: Thu, 12 Oct 2023 14:47:31 +0200 Subject: [PATCH 269/338] Minor improvements --- slither/__main__.py | 19 ++++++++++ slither/core/slither_core.py | 22 +++++++++++ slither/utils/command_line.py | 2 + slither/utils/sarif.py | 71 +++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 slither/utils/sarif.py diff --git a/slither/__main__.py b/slither/__main__.py index c63920036..f4fca5493 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -79,6 +79,11 @@ def process_single( ast = "--ast-json" slither = Slither(target, ast_format=ast, **vars(args)) + if args.sarif_input: + slither.sarif_input = args.sarif_input + if args.sarif_triage: + slither.sarif_triage = args.sarif_triage + return _process(slither, detector_classes, printer_classes) @@ -469,6 +474,20 @@ def parse_args( default=defaults_flag_in_config["sarif"], ) + group_misc.add_argument( + "--sarif-input", + help="Sarif input (beta)", + action="store", + default=defaults_flag_in_config["sarif_input"], + ) + + group_misc.add_argument( + "--sarif-triage", + help="Sarif triage (beta)", + action="store", + default=defaults_flag_in_config["sarif_triage"], + ) + group_misc.add_argument( "--json-types", help="Comma-separated list of result types to output to JSON, defaults to " diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 798008707..e6bbef8ff 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -21,6 +21,7 @@ from slither.core.declarations.top_level import TopLevel from slither.core.source_mapping.source_mapping import SourceMapping, Source from slither.slithir.variables import Constant from slither.utils.colors import red +from slither.utils.sarif import read_triage_info from slither.utils.source_mapping import get_definition, get_references, get_implementation logger = logging.getLogger("Slither") @@ -48,6 +49,10 @@ class SlitherCore(Context): self._source_code_to_line: Optional[Dict[str, List[str]]] = None self._previous_results_filename: str = "slither.db.json" + + # TODO: add cli flag to set these variables + self.sarif_input: str = "export.sarif" + self.sarif_triage: str = "export.sarif.sarifexplorer" self._results_to_hide: List = [] self._previous_results: List = [] # From triaged result @@ -444,6 +449,8 @@ class SlitherCore(Context): return True def load_previous_results(self) -> None: + self.load_previous_results_from_sarif() + filename = self._previous_results_filename try: if os.path.isfile(filename): @@ -453,9 +460,24 @@ class SlitherCore(Context): for r in self._previous_results: if "id" in r: self._previous_results_ids.add(r["id"]) + except json.decoder.JSONDecodeError: logger.error(red(f"Impossible to decode {filename}. Consider removing the file")) + def load_previous_results_from_sarif(self) -> None: + sarif = pathlib.Path(self.sarif_input) + triage = pathlib.Path(self.sarif_triage) + + if not sarif.exists(): + return + if not triage.exists(): + return + + triaged = read_triage_info(sarif, triage) + + for id_triaged in triaged: + self._previous_results_ids.add(id_triaged) + def write_results_to_hide(self) -> None: if not self._results_to_hide: return diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 082472582..6c50fcab9 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -68,6 +68,8 @@ defaults_flag_in_config = { "zip_type": "lzma", "show_ignored_findings": False, "no_fail": False, + "sarif_input": "export.sarif", + "sarif_triage": "export.sarif.sarifexplorer", **DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, } diff --git a/slither/utils/sarif.py b/slither/utils/sarif.py new file mode 100644 index 000000000..600ac35c7 --- /dev/null +++ b/slither/utils/sarif.py @@ -0,0 +1,71 @@ +""" +Various utils for sarif/vscode +""" +import json +from pathlib import Path +from typing import List, Dict, Optional, Tuple, Any + + +def _parse_index(key: str) -> Optional[Tuple[int, int]]: + if key.count(":") != 2: + return None + + try: + run = int(key[key.find(":") + 1 : key.rfind(":")]) + index = int(key[key.rfind(":") + 1 :]) + return run, index + except ValueError: + return None + + +def _get_indexes(path_to_triage: Path) -> List[Tuple[int, int]]: + try: + with open(path_to_triage, encoding="utf8") as file_desc: + triage = json.load(file_desc) + except json.decoder.JSONDecodeError: + return [] + + resultIdToNotes: Dict[str, Dict] = triage.get("resultIdToNotes", {}) + + indexes: List[Tuple[int, int]] = [] + for key, data in resultIdToNotes.items(): + if "status" in data and data["status"] == 1: + parsed = _parse_index(key) + if parsed: + indexes.append(parsed) + + return indexes + + +def read_triage_info(path_to_sarif: Path, path_to_triage: Path) -> List[str]: + try: + with open(path_to_sarif, encoding="utf8") as file_desc: + sarif = json.load(file_desc) + except json.decoder.JSONDecodeError: + return [] + + runs: List[Dict[str, Any]] = sarif.get("runs", []) + + # Don't support multiple runs for now + if len(runs) != 1: + return [] + + run_results: List[Dict] = runs[0].get("results", []) + + indexes = _get_indexes(path_to_triage) + + ids: List[str] = [] + for run, index in indexes: + + # We dont support multiple runs for now + if run != 0: + continue + try: + elem = run_results[index] + except KeyError: + continue + if "partialFingerprints" in elem: + if "id" in elem["partialFingerprints"]: + ids.append(elem["partialFingerprints"]["id"]) + + return ids From 37d714bb0cf798d91c497a07e0ad2bbade5e33c9 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 12 Oct 2023 15:52:55 +0200 Subject: [PATCH 270/338] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 905470920..16aa80568 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( "prettytable>=3.3.0", "pycryptodome>=3.4.6", # "crytic-compile>=0.3.1,<0.4.0", - "crytic-compile@git+https://github.com/crytic/crytic-compile.git@feat/vyper-standard-json#egg=crytic-compile", + "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", "web3>=6.0.0", "eth-abi>=4.0.0", "eth-typing>=3.0.0", From 98da04fb06bd3018995bce6136440919354a4140 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 12 Oct 2023 16:01:19 +0200 Subject: [PATCH 271/338] Minor --- slither/core/variables/variable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/slither/core/variables/variable.py b/slither/core/variables/variable.py index 1afcc4757..f9ef19024 100644 --- a/slither/core/variables/variable.py +++ b/slither/core/variables/variable.py @@ -179,4 +179,6 @@ class Variable(SourceMapping): return f'{name}({",".join(parameters)})' def __str__(self) -> str: + if self._name is None: + return "" return self._name From 4a8385813f0cf9df945fc8519090d8e8923cf9f4 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 12 Oct 2023 16:11:21 +0200 Subject: [PATCH 272/338] fix CI --- tests/unit/slithir/test_ssa_generation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/slithir/test_ssa_generation.py b/tests/unit/slithir/test_ssa_generation.py index 688c0a5fb..1ecf82a2d 100644 --- a/tests/unit/slithir/test_ssa_generation.py +++ b/tests/unit/slithir/test_ssa_generation.py @@ -1118,7 +1118,7 @@ def test_issue_1846_ternary_in_ternary(slither_from_solidity_source): assert node.son_false.type == NodeType.EXPRESSION -def test_issue_2016(slither_from_source): +def test_issue_2016(slither_from_solidity_source): source = """ contract Contract { function test() external { @@ -1126,7 +1126,7 @@ def test_issue_2016(slither_from_source): } } """ - with slither_from_source(source) as slither: + with slither_from_solidity_source(source) as slither: c = slither.get_contract_from_name("Contract")[0] f = c.functions[0] operations = f.slithir_operations From 2a7e514a5d2db8276c6bef675e137a3cbf92a780 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Thu, 12 Oct 2023 16:24:41 +0200 Subject: [PATCH 273/338] Fix snapshot --- .../snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt | 2 +- .../ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt | 2 +- .../snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt | 2 +- .../snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt index 3c6eaec3e..1f973fcdb 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_c__0.txt @@ -8,7 +8,7 @@ EXPRESSION: user_shares = () IRs: -user_shares(uint256[10]) = []"]; +user_shares(uint256[10]) = []"]; 1->2; 2[label="Node Type: EXPRESSION 2 diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt index 9b7768a6b..4719d9926 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_builtins_test_builtins__0.txt @@ -66,7 +66,7 @@ i = slice()(msg.data,0,32) IRs: TMP_1(None) = SOLIDITY_CALL slice()(msg.data,0,32) -i(bytes[32]) = ['TMP_1(None)']"]; +i(bytes[32]) = ['TMP_1(None)']"]; 8->9; 9[label="Node Type: NEW VARIABLE 9 diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt index c1f5f2f13..9e35f147e 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_for2_for_loop__0.txt @@ -8,7 +8,7 @@ EXPRESSION: _strategies = strategies IRs: -_strategies(address[3]) = ['strategies(address[3])']"]; +_strategies(address[3]) = ['strategies(address[3])']"]; 1->2; 2[label="Node Type: BEGIN_LOOP 2 "]; diff --git a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt index 15a091f26..ac4917822 100644 --- a/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt +++ b/tests/e2e/vyper_parsing/snapshots/ast_parsing__vyper_cfgir_initarry_coins__0.txt @@ -10,7 +10,7 @@ EXPRESSION: IRs: TMP_2 = CONVERT BORROWED_TOKEN to address TMP_3 = CONVERT COLLATERAL_TOKEN to address -TMP_4(address[2]) = ['TMP_2(address)', 'TMP_3(address)'] +TMP_4(address[2]) = ['TMP_2(address)', 'TMP_3(address)'] REF_0(address) -> TMP_4[i] RETURN REF_0"]; } From 73f2dc6989242398297cddd7876aefaa4b945181 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 10:28:46 +0200 Subject: [PATCH 274/338] Revert #1984 --- slither/core/dominators/utils.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index 77ff22611..eb20ef00c 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -9,16 +9,21 @@ if TYPE_CHECKING: def intersection_predecessor(node: "Node") -> Set["Node"]: if not node.fathers: return set() - if not any(father.is_reachable for father in node.fathers): - return set() - - ret = set() - for pred in node.fathers: - ret = ret.union(pred.dominators) - for pred in node.fathers: - if pred.is_reachable: - ret = ret.intersection(pred.dominators) + # Revert PR1984 + ret = node.fathers[0].dominators + for pred in node.fathers[1:]: + ret = ret.intersection(pred.dominators) + # if not any(father.is_reachable for father in node.fathers): + # return set() + # + # ret = set() + # for pred in node.fathers: + # ret = ret.union(pred.dominators) + # + # for pred in node.fathers: + # if pred.is_reachable: + # ret = ret.intersection(pred.dominators) return ret @@ -91,8 +96,9 @@ def compute_dominance_frontier(nodes: List["Node"]) -> None: for node in nodes: if len(node.fathers) >= 2: for father in node.fathers: - if not father.is_reachable: - continue + # Revert PR1984 + # if not father.is_reachable: + # continue runner = father # Corner case: if there is a if without else # we need to add update the conditional node From c551d4b098540c9eaaf0f4d6741c95d0e8c9b6b5 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 11:14:07 +0200 Subject: [PATCH 275/338] Improvements --- slither/visitors/slithir/expression_to_slithir.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 145a868e0..931dc82ae 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -14,7 +14,7 @@ from slither.core.declarations import ( Enum, SolidityImportPlaceHolder, Import, - Structure + Structure, ) from slither.core.expressions import ( AssignmentOperation, @@ -639,8 +639,8 @@ class ExpressionToSlithIR(ExpressionVisitor): set_val(expression, scope.enums[elem]) return True - if elem in scope.user_defined_types: - set_val(expression, scope.user_defined_types[elem]) + if elem in scope.type_aliases: + set_val(expression, scope.type_aliases[elem]) return True for import_directive in scope.imports: From b2650895c47563e8541ced3ff232e29e79712d35 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 11:27:10 +0200 Subject: [PATCH 276/338] fix pylint --- slither/slither.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/slither/slither.py b/slither/slither.py index 773ab9f74..747d2207e 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -50,7 +50,9 @@ def _update_file_scopes(candidates: ValuesView[FileScope]): learned_something = False -class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes +class Slither( + SlitherCore +): # pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: """ Args: From dea0483e82599e088680f72cd468f7e363057cf2 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 11:32:38 +0200 Subject: [PATCH 277/338] Fix merge --- slither/printers/guidance/echidna.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 67745c6ba..7a0332949 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -125,18 +125,18 @@ def _extract_constant_functions(contracts) -> Dict[str, List[str]]: return ret -def _extract_assert(slither: SlitherCore) -> Dict[str, Dict[str, List[Dict]]]: +def _extract_assert(contracts: List[Contract]) -> Dict[str, Dict[str, List[Dict]]]: """ Return the list of contract -> function name -> List(source mapping of the assert)) Args: - slither: + contracts: list of contracts Returns: """ ret: Dict[str, Dict[str, List[Dict]]] = {} - for contract in slither.contracts: + for contract in contracts: functions_using_assert: Dict[str, List[Dict]] = defaultdict(list) for f in contract.functions_entry_points: for node in f.all_nodes(): From 1437b01f4b92c6ed50ea9fc647e1f2653760a533 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 11:38:55 +0200 Subject: [PATCH 278/338] Add missing type import --- slither/printers/guidance/echidna.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 7a0332949..1acd4051f 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -4,7 +4,7 @@ from typing import Dict, List, Set, Tuple, NamedTuple, Union from slither.analyses.data_dependency.data_dependency import is_dependent from slither.core.cfg.node import Node -from slither.core.declarations import Enum, Function +from slither.core.declarations import Enum, Function, Contract from slither.core.declarations.solidity_variables import ( SolidityVariableComposed, SolidityFunction, From 7f5535fc2411aae9db8b28a9855255745f64c028 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 11:41:06 +0200 Subject: [PATCH 279/338] Run black on the test file --- .../slithir/test_yul_parser_assembly_slot.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/unit/slithir/test_yul_parser_assembly_slot.py b/tests/unit/slithir/test_yul_parser_assembly_slot.py index d1bb5bb40..da800b55e 100644 --- a/tests/unit/slithir/test_yul_parser_assembly_slot.py +++ b/tests/unit/slithir/test_yul_parser_assembly_slot.py @@ -14,17 +14,18 @@ TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" def test_yul_parser_assembly_slot(solc_binary_path) -> None: # mstore(0x0, bucketId) # mstore(0x20, _counters.slot) - data = { - '0x0': 'bucketId', - '0x20': '_counters' - } + data = {"0x0": "bucketId", "0x20": "_counters"} solc_path = solc_binary_path("0.8.18") slither = Slither(Path(TEST_DATA_DIR, "assembly_storage_slot.sol").as_posix(), solc=solc_path) - contract = slither.get_contract_from_name('XXX')[0] - func = contract.get_function_from_full_name('getPackedBucketGlobalState(uint256)') - calls = [node.expression for node in func.all_nodes() if node.expression and 'mstore' in str(node.expression)] + contract = slither.get_contract_from_name("XXX")[0] + func = contract.get_function_from_full_name("getPackedBucketGlobalState(uint256)") + calls = [ + node.expression + for node in func.all_nodes() + if node.expression and "mstore" in str(node.expression) + ] for call in calls: assert isinstance(call, CallExpression) @@ -33,7 +34,7 @@ def test_yul_parser_assembly_slot(solc_binary_path) -> None: assert isinstance(memory_location, Literal) assert isinstance(value, Identifier) assert value.value.name == data[memory_location.value] - if value.value.name == '_counters': + if value.value.name == "_counters": assert isinstance(value.value, StateVariable) - elif value.value.name == 'bucketId': + elif value.value.name == "bucketId": assert isinstance(value.value, LocalVariable) From 0362e0023e4278014cba0d3363596f34db11de46 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 12:01:20 +0200 Subject: [PATCH 280/338] Keep tests contract in the echidna printer Echidna might need constant from the tests themselves ;) --- slither/printers/guidance/echidna.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 1acd4051f..2d437dd39 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -404,7 +404,7 @@ class Echidna(AbstractPrinter): _filename(string) """ - contracts = [c for c in self.slither.contracts if not is_test_contract(c)] + contracts = self.slither.contracts payable = _extract_payable(contracts) timestamp = _extract_solidity_variable_usage( From d9805c0e63aec426535241fa33149723a9b7b179 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 12:07:32 +0200 Subject: [PATCH 281/338] Add more types, fix pylint --- slither/printers/guidance/echidna.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 2d437dd39..c729779ce 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -32,7 +32,6 @@ from slither.slithir.operations import ( from slither.slithir.operations.binary import Binary from slither.slithir.variables import Constant, ReferenceVariable from slither.utils.output import Output -from slither.utils.tests_pattern import is_test_contract from slither.visitors.expression.constants_folding import ConstantFolding, NotConstant @@ -44,7 +43,7 @@ def _get_name(f: Union[Function, Variable]) -> str: return f.solidity_signature -def _extract_payable(contracts) -> Dict[str, List[str]]: +def _extract_payable(contracts: List[Contract]) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} for contract in contracts: payable_functions = [_get_name(f) for f in contract.functions_entry_points if f.payable] @@ -53,7 +52,9 @@ def _extract_payable(contracts) -> Dict[str, List[str]]: return ret -def _extract_solidity_variable_usage(contracts, sol_var: SolidityVariable) -> Dict[str, List[str]]: +def _extract_solidity_variable_usage( + contracts: List[Contract], sol_var: SolidityVariable +) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} for contract in contracts: functions_using_sol_var = [] @@ -113,7 +114,7 @@ def _is_constant(f: Function) -> bool: # pylint: disable=too-many-branches return True -def _extract_constant_functions(contracts) -> Dict[str, List[str]]: +def _extract_constant_functions(contracts: List[Contract]) -> Dict[str, List[str]]: ret: Dict[str, List[str]] = {} for contract in contracts: cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)] @@ -237,7 +238,7 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n def _extract_constants( - contracts, + contracts: List[Contract], ) -> Tuple[Dict[str, Dict[str, List]], Dict[str, Dict[str, Dict]]]: # contract -> function -> [ {"value": value, "type": type} ] ret_cst_used: Dict[str, Dict[str, List[ConstantValue]]] = defaultdict(dict) @@ -269,7 +270,7 @@ def _extract_constants( def _extract_function_relations( - contracts, + contracts: List[Contract], ) -> Dict[str, Dict[str, Dict[str, List[str]]]]: # contract -> function -> [functions] ret: Dict[str, Dict[str, Dict[str, List[str]]]] = defaultdict(dict) @@ -297,7 +298,7 @@ def _extract_function_relations( return ret -def _have_external_calls(contracts) -> Dict[str, List[str]]: +def _have_external_calls(contracts: List[Contract]) -> Dict[str, List[str]]: """ Detect the functions with external calls :param slither: @@ -313,7 +314,7 @@ def _have_external_calls(contracts) -> Dict[str, List[str]]: return ret -def _use_balance(contracts) -> Dict[str, List[str]]: +def _use_balance(contracts: List[Contract]) -> Dict[str, List[str]]: """ Detect the functions with external calls :param slither: @@ -332,7 +333,7 @@ def _use_balance(contracts) -> Dict[str, List[str]]: return ret -def _with_fallback(contracts) -> Set[str]: +def _with_fallback(contracts: List[Contract]) -> Set[str]: ret: Set[str] = set() for contract in contracts: for function in contract.functions_entry_points: @@ -341,7 +342,7 @@ def _with_fallback(contracts) -> Set[str]: return ret -def _with_receive(contracts) -> Set[str]: +def _with_receive(contracts: List[Contract]) -> Set[str]: ret: Set[str] = set() for contract in contracts: for function in contract.functions_entry_points: @@ -350,7 +351,7 @@ def _with_receive(contracts) -> Set[str]: return ret -def _call_a_parameter(slither: SlitherCore, contracts) -> Dict[str, List[Dict]]: +def _call_a_parameter(slither: SlitherCore, contracts: List[Contract]) -> Dict[str, List[Dict]]: """ Detect the functions with external calls :param slither: From 2e8e646cda4e809a1a7aa9ce65c9e8cb61f22cb1 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 13:09:05 +0200 Subject: [PATCH 282/338] Update readme --- README.md | 142 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 1a0d203c7..b250d40fa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# [Slither, the Solidity source analyzer](https://crytic.github.io/slither/slither.html) +# [Slither, the smart contrat static analyzer](https://crytic.github.io/slither/slither.html) Slither Static Analysis Framework Logo @@ -12,7 +12,7 @@ > [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/) > > - Discussions and Support -**Slither** is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. +**Slither** is a Solidity & Vyper static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses. * [Features](#features) * [Usage](#usage) @@ -46,6 +46,7 @@ * Correctly parses 99.9% of all public Solidity code * Average execution time of less than 1 second per contract * Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) +* Support for Vyper ## Usage @@ -129,72 +130,77 @@ Num | Detector | What it Detects | Impact | Confidence 19 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium 20 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium 21 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium -22 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium -23 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium -24 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium -25 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium -26 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium -27 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High -28 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High -29 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High -30 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High -31 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High -32 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High -33 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High -34 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High -35 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High -36 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High -37 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium -38 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium -39 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium -40 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium -41 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium -42 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium -43 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium -44 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium -45 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium -46 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium -47 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium -48 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High -49 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High -50 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High -51 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High -52 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High -53 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High -54 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium -55 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium -56 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium -57 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium -58 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium -59 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium -60 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium -61 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium -62 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High -63 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High -64 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High -65 | `cyclomatic-complexity` | [Detects functions with high (> 11) cyclomatic complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) | Informational | High -66 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High -67 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High -68 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High -69 | `incorrect-using-for` | [Detects using-for statement usage when no function from a given library matches a given type](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-using-for-usage) | Informational | High -70 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High -71 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High -72 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High -73 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High -74 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High -75 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High -76 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High -77 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High -78 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium -79 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium -80 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium -81 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium -82 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium -83 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it.](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High -84 | `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 -85 | `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 -86 | `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 -87 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Detector-Documentation#public-variable-read-in-external-context) | Optimization | High +22 | `incorrect-exp` | [Incorrect exponentiation](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation) | High | Medium +23 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +24 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium +25 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium +26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +27 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium +28 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium +29 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium +30 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High +31 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High +32 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High +33 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High +34 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High +35 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High +36 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High +37 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High +38 | `tautological-compare` | [Comparing a variable to itself always returns true or false, depending on comparison](https://github.com/crytic/slither/wiki/Detector-Documentation#tautological-compare) | Medium | High +39 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High +40 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High +41 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium +42 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium +43 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium +44 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium +45 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium +46 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium +47 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium +48 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium +49 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium +50 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium +51 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium +52 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High +53 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High +54 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High +55 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High +56 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High +57 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High +58 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium +59 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium +60 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium +61 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium +62 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium +63 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium +64 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium +65 | `return-bomb` | [A low level callee may consume all callers gas unexpectedly.](https://github.com/crytic/slither/wiki/Detector-Documentation#return-bomb) | Low | Medium +66 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium +67 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High +68 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High +69 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High +70 | `cyclomatic-complexity` | [Detects functions with high (> 11) cyclomatic complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) | Informational | High +71 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High +72 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High +73 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High +74 | `incorrect-using-for` | [Detects using-for statement usage when no function from a given library matches a given type](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-using-for-usage) | Informational | High +75 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High +76 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High +77 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High +78 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High +79 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High +80 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High +81 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High +82 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High +83 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium +84 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium +85 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium +86 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium +87 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium +88 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it. ](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High +89 | `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 +90 | `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 +91 | `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 +92 | `var-read-using-this` | [Contract reads its own variable using `this`](https://github.com/crytic/slither/wiki/Detector-Documentation#public-variable-read-in-external-context) | Optimization | High For more information, see From 00f189f2c7830a022ab261c94dfefdb04e71ce7c Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Fri, 13 Oct 2023 13:23:16 +0200 Subject: [PATCH 283/338] improve markdown --- README.md | 4 +++- slither/detectors/operations/cache_array_length.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b250d40fa..41b6e3209 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ Num | Detector | What it Detects | Impact | Confidence 85 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium 86 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium 87 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium -88 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it. ](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High +88 | `cache-array-length` | [Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it.](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) | Optimization | High 89 | `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 90 | `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 91 | `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 @@ -211,12 +211,14 @@ For more information, see ## Printers ### Quick Review Printers + * `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary) * `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph) * `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary) * `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc) ### In-Depth Review Printers + * `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph) * `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg) * `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary) diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py index 59289ed0f..eb4f43fa5 100644 --- a/slither/detectors/operations/cache_array_length.py +++ b/slither/detectors/operations/cache_array_length.py @@ -17,7 +17,7 @@ class CacheArrayLength(AbstractDetector): ARGUMENT = "cache-array-length" HELP = ( "Detects `for` loops that use `length` member of some storage array in their loop condition and don't " - "modify it. " + "modify it." ) IMPACT = DetectorClassification.OPTIMIZATION CONFIDENCE = DetectorClassification.HIGH From e94c582542f6696fbcf19a48d3745573d187b144 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:23:56 +0000 Subject: [PATCH 284/338] Bump @openzeppelin/contracts Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 4.4.0 to 4.9.3. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.3/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.4.0...v4.9.3) --- updated-dependencies: - dependency-name: "@openzeppelin/contracts" dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .../test_data/test_node_modules/package-lock.json | 11 +++++++---- .../test_data/test_node_modules/package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/e2e/compilation/test_data/test_node_modules/package-lock.json b/tests/e2e/compilation/test_data/test_node_modules/package-lock.json index a336d8b3b..0de76f190 100644 --- a/tests/e2e/compilation/test_data/test_node_modules/package-lock.json +++ b/tests/e2e/compilation/test_data/test_node_modules/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "@openzeppelin/contracts": "^4.4.0", + "@openzeppelin/contracts": "^4.9.3", "hardhat": "^2.13.0" } }, @@ -961,8 +961,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "4.4.0", - "license": "MIT" + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.3.tgz", + "integrity": "sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==" }, "node_modules/@scure/base": { "version": "1.1.1", @@ -4266,7 +4267,9 @@ "optional": true }, "@openzeppelin/contracts": { - "version": "4.4.0" + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.3.tgz", + "integrity": "sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==" }, "@scure/base": { "version": "1.1.1", diff --git a/tests/e2e/compilation/test_data/test_node_modules/package.json b/tests/e2e/compilation/test_data/test_node_modules/package.json index 124f77665..755f71022 100644 --- a/tests/e2e/compilation/test_data/test_node_modules/package.json +++ b/tests/e2e/compilation/test_data/test_node_modules/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@openzeppelin/contracts": "^4.4.0", + "@openzeppelin/contracts": "^4.9.3", "hardhat": "^2.13.0" } } From a433e3ba6652e17732062bb94196d3167e4f6cbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 12:23:57 +0000 Subject: [PATCH 285/338] Bump semver in /tests/e2e/compilation/test_data/test_node_modules Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2) --- updated-dependencies: - dependency-name: semver dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../test_node_modules/package-lock.json | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/e2e/compilation/test_data/test_node_modules/package-lock.json b/tests/e2e/compilation/test_data/test_node_modules/package-lock.json index a336d8b3b..0bedd3d28 100644 --- a/tests/e2e/compilation/test_data/test_node_modules/package-lock.json +++ b/tests/e2e/compilation/test_data/test_node_modules/package-lock.json @@ -3154,9 +3154,9 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -3247,9 +3247,9 @@ } }, "node_modules/solc/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "bin": { "semver": "bin/semver" } @@ -5864,9 +5864,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" }, "serialize-javascript": { "version": "6.0.0", @@ -5942,9 +5942,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" } } }, From 46be017fe538c04dbc5928c1134d78e8c3e70e74 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 17 Oct 2023 09:17:36 -0500 Subject: [PATCH 286/338] update vyper cfg to include reachability (#2182) * update vyper cfg to include reachability * revert https://github.com/crytic/slither/pull/2170 --- slither/core/dominators/utils.py | 26 +++++++++---------- .../vyper_parsing/declarations/function.py | 7 +++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/slither/core/dominators/utils.py b/slither/core/dominators/utils.py index eb20ef00c..150c0c50e 100644 --- a/slither/core/dominators/utils.py +++ b/slither/core/dominators/utils.py @@ -10,20 +10,19 @@ def intersection_predecessor(node: "Node") -> Set["Node"]: if not node.fathers: return set() - # Revert PR1984 ret = node.fathers[0].dominators for pred in node.fathers[1:]: ret = ret.intersection(pred.dominators) - # if not any(father.is_reachable for father in node.fathers): - # return set() - # - # ret = set() - # for pred in node.fathers: - # ret = ret.union(pred.dominators) - # - # for pred in node.fathers: - # if pred.is_reachable: - # ret = ret.intersection(pred.dominators) + if not any(father.is_reachable for father in node.fathers): + return set() + + ret = set() + for pred in node.fathers: + ret = ret.union(pred.dominators) + + for pred in node.fathers: + if pred.is_reachable: + ret = ret.intersection(pred.dominators) return ret @@ -96,9 +95,8 @@ def compute_dominance_frontier(nodes: List["Node"]) -> None: for node in nodes: if len(node.fathers) >= 2: for father in node.fathers: - # Revert PR1984 - # if not father.is_reachable: - # continue + if not father.is_reachable: + continue runner = father # Corner case: if there is a if without else # we need to add update the conditional node diff --git a/slither/vyper_parsing/declarations/function.py b/slither/vyper_parsing/declarations/function.py index 70e04c8e5..f5acf1296 100644 --- a/slither/vyper_parsing/declarations/function.py +++ b/slither/vyper_parsing/declarations/function.py @@ -184,6 +184,7 @@ class FunctionVyper: # pylint: disable=too-many-instance-attributes self._function.is_implemented = True self._function.is_empty = False self._parse_cfg(body) + self._update_reachability(self._function.entry_point) else: self._function.is_implemented = False self._function.is_empty = True @@ -243,6 +244,12 @@ class FunctionVyper: # pylint: disable=too-many-instance-attributes # region Parsing function ################################################################################### ################################################################################### + def _update_reachability(self, node: Node) -> None: + if node.is_reachable: + return + node.set_is_reachable(True) + for son in node.sons: + self._update_reachability(son) # pylint: disable=too-many-branches,too-many-statements,protected-access,too-many-locals def _parse_cfg(self, cfg: List[ASTNode]) -> None: From c04e860db3b8794f82dda7c17424c821ce8db319 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Tue, 17 Oct 2023 16:17:59 +0200 Subject: [PATCH 287/338] Update README.md (#2177) typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41b6e3209..0f548d6b8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# [Slither, the smart contrat static analyzer](https://crytic.github.io/slither/slither.html) +# [Slither, the smart contract static analyzer](https://crytic.github.io/slither/slither.html) Slither Static Analysis Framework Logo From dded959beb7d3e1ed3ebd54d78252f139a0173f6 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 09:18:57 -0500 Subject: [PATCH 288/338] revert https://github.com/crytic/slither/pull/2105 (#2185) --- slither/printers/guidance/echidna.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index c729779ce..0c47fa0f9 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -138,12 +138,17 @@ def _extract_assert(contracts: List[Contract]) -> Dict[str, Dict[str, List[Dict] """ ret: Dict[str, Dict[str, List[Dict]]] = {} for contract in contracts: - functions_using_assert: Dict[str, List[Dict]] = defaultdict(list) + functions_using_assert = [] # Dict[str, List[Dict]] = defaultdict(list) for f in contract.functions_entry_points: - for node in f.all_nodes(): - if SolidityFunction("assert(bool)") in node.solidity_calls and node.source_mapping: - func_name = _get_name(f) - functions_using_assert[func_name].append(node.source_mapping.to_json()) + for v in f.all_solidity_calls(): + if v == SolidityFunction("assert(bool)"): + functions_using_assert.append(_get_name(f)) + break + # Revert https://github.com/crytic/slither/pull/2105 until format is supported by echidna. + # for node in f.all_nodes(): + # if SolidityFunction("assert(bool)") in node.solidity_calls and node.source_mapping: + # func_name = _get_name(f) + # functions_using_assert[func_name].append(node.source_mapping.to_json()) if functions_using_assert: ret[contract.name] = functions_using_assert return ret From c422c0d1f6bd725e5475b1ea404814c1201e3209 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 09:41:47 -0500 Subject: [PATCH 289/338] Update setup.py --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 16aa80568..332f8fc18 100644 --- a/setup.py +++ b/setup.py @@ -5,18 +5,18 @@ with open("README.md", "r", encoding="utf-8") as f: setup( name="slither-analyzer", - description="Slither is a Solidity static analysis framework written in Python 3.", + description="Slither is a Solidity and Vyper static analysis framework written in Python 3.", url="https://github.com/crytic/slither", author="Trail of Bits", - version="0.9.6", + version="0.10.0", packages=find_packages(), python_requires=">=3.8", install_requires=[ "packaging", "prettytable>=3.3.0", "pycryptodome>=3.4.6", - # "crytic-compile>=0.3.1,<0.4.0", - "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", + "crytic-compile>=0.3.5,<0.4.0", + # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", "web3>=6.0.0", "eth-abi>=4.0.0", "eth-typing>=3.0.0", From cd3f2d41850c5744335e9592bd491a65d1bea5de Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 14:07:10 -0500 Subject: [PATCH 290/338] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d0a7d67be..6de5ec2c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,6 +47,6 @@ ENV PATH="/home/slither/.local/bin:${PATH}" RUN --mount=type=bind,target=/mnt,source=/wheels,from=python-wheels \ pip3 install --user --no-cache-dir --upgrade --no-index --find-links /mnt --no-deps /mnt/*.whl -RUN solc-select install 0.4.25 && solc-select use 0.4.25 +RUN solc-select use latest --always-install CMD /bin/bash From ea708cda4f950434804ae05d3cee02146de1f65f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 20 Oct 2023 08:52:39 -0500 Subject: [PATCH 291/338] remove unused files --- slither/core/children/__init__.py | 0 slither/core/children/child_event.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 slither/core/children/__init__.py delete mode 100644 slither/core/children/child_event.py diff --git a/slither/core/children/__init__.py b/slither/core/children/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/slither/core/children/child_event.py b/slither/core/children/child_event.py deleted file mode 100644 index e69de29bb..000000000 From 8d9199ed6cd6498b6c0fe9229c02a78ccd9e64fc Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 18 Oct 2023 14:14:05 -0500 Subject: [PATCH 292/338] Update installation instrucitons --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0f548d6b8..6ab019b77 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,14 @@ If you're **not** going to use one of the [supported compilation frameworks](htt ### Using Pip ```console -pip3 install slither-analyzer +python3 -m pip install slither-analyzer ``` ### Using Git ```bash git clone https://github.com/crytic/slither.git && cd slither -python3 setup.py install +python3 -m pip install . ``` We recommend using a Python virtual environment, as detailed in the [Developer Installation Instructions](https://github.com/trailofbits/slither/wiki/Developer-installation), if you prefer to install Slither via git. From 112786f890123497b6968480246575c8f41043ad Mon Sep 17 00:00:00 2001 From: Amos Dominion <121090896+VIELITE@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:54:10 -0400 Subject: [PATCH 293/338] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f548d6b8..c4b445783 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ * Correctly parses 99.9% of all public Solidity code * Average execution time of less than 1 second per contract * Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action) -* Support for Vyper +* Support for Vyper smart contracts ## Usage From 0cd9efec6fdf65e1867805f8ae7d8df26a03496b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:03:33 +0000 Subject: [PATCH 294/338] Bump actions/setup-node from 3 to 4 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb8f0ea6e..1660a25e9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: pip install ".[test]" - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '16' cache: 'npm' From b7ba2c48da01eded38b20702756d50d2a13e18c7 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 1 Nov 2023 12:12:24 -0500 Subject: [PATCH 295/338] fix is_reentrant for internal vyper functions --- slither/core/declarations/function.py | 13 +++++++++---- tests/unit/core/test_function_declaration.py | 9 ++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index e803154d0..d2baaf7e7 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -1500,10 +1500,13 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu """ Determine if the function can be re-entered """ + reentrancy_modifier = "nonReentrant" + + if self.function_language == FunctionLanguage.Vyper: + reentrancy_modifier = "nonreentrant(lock)" + # TODO: compare with hash of known nonReentrant modifier instead of the name - if "nonReentrant" in [m.name for m in self.modifiers] or "nonreentrant(lock)" in [ - m.name for m in self.modifiers - ]: + if reentrancy_modifier in [m.name for m in self.modifiers]: return False if self.visibility in ["public", "external"]: @@ -1515,7 +1518,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu ] if not all_entry_points: return True - return not all(("nonReentrant" in [m.name for m in f.modifiers] for f in all_entry_points)) + return not all( + (reentrancy_modifier in [m.name for m in f.modifiers] for f in all_entry_points) + ) # endregion ################################################################################### diff --git a/tests/unit/core/test_function_declaration.py b/tests/unit/core/test_function_declaration.py index cea207613..f75198d24 100644 --- a/tests/unit/core/test_function_declaration.py +++ b/tests/unit/core/test_function_declaration.py @@ -324,6 +324,9 @@ def withdraw(): @external @nonreentrant("lock") def withdraw_locked(): + self.withdraw_locked_internal() +@internal +def withdraw_locked_internal(): raw_call(msg.sender, b"", value= self.balances[msg.sender]) @payable @external @@ -376,10 +379,14 @@ def __default__(): assert not f.is_empty f = functions["withdraw_locked()"] - assert not f.is_reentrant + assert f.is_reentrant is False assert f.is_implemented assert not f.is_empty + f = functions["withdraw_locked_internal()"] + assert f.is_reentrant is False + assert f.visibility == "internal" + var = contract.get_state_variable_from_name("balances") assert var assert var.solidity_signature == "balances(address)" From 4a3354173818fb4cdf52f6b0aa62df60535fb903 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 6 Nov 2023 19:07:01 +0100 Subject: [PATCH 296/338] Add support top level events --- slither/core/compilation_unit.py | 6 +++++ slither/core/declarations/__init__.py | 2 ++ slither/core/declarations/contract.py | 12 ++++----- slither/core/declarations/event.py | 24 ++--------------- slither/core/declarations/event_contract.py | 25 ++++++++++++++++++ slither/core/declarations/event_top_level.py | 13 +++++++++ slither/core/scope/scope.py | 7 ++++- slither/core/slither_core.py | 2 ++ slither/solc_parsing/declarations/contract.py | 8 +++--- slither/solc_parsing/declarations/event.py | 19 +++++++------ .../solc_parsing/expressions/find_variable.py | 3 +++ .../slither_compilation_unit_solc.py | 11 ++++++++ slither/tools/flattening/flattening.py | 1 + .../vyper_parsing/declarations/contract.py | 4 +-- tests/e2e/solc_parsing/test_ast_parsing.py | 1 + .../event-top-level.sol-0.8.22-compact.zip | Bin 0 -> 2022 bytes .../test_data/event-top-level.sol | 7 +++++ .../event-top-level.sol-0.8.22-compact.json | 5 ++++ 18 files changed, 105 insertions(+), 45 deletions(-) create mode 100644 slither/core/declarations/event_contract.py create mode 100644 slither/core/declarations/event_top_level.py create mode 100644 tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/event-top-level.sol create mode 100644 tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py index 87853aa34..6221fd8bd 100644 --- a/slither/core/compilation_unit.py +++ b/slither/core/compilation_unit.py @@ -16,6 +16,7 @@ from slither.core.declarations import ( ) from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.structure_top_level import StructureTopLevel from slither.core.declarations.using_for_top_level import UsingForTopLevel @@ -57,6 +58,7 @@ class SlitherCompilationUnit(Context): self.contracts: List[Contract] = [] self._structures_top_level: List[StructureTopLevel] = [] self._enums_top_level: List[EnumTopLevel] = [] + self._events_top_level: List[EventTopLevel] = [] self._variables_top_level: List[TopLevelVariable] = [] self._functions_top_level: List[FunctionTopLevel] = [] self._using_for_top_level: List[UsingForTopLevel] = [] @@ -234,6 +236,10 @@ class SlitherCompilationUnit(Context): def enums_top_level(self) -> List[EnumTopLevel]: return self._enums_top_level + @property + def events_top_level(self) -> List[EventTopLevel]: + return self._events_top_level + @property def variables_top_level(self) -> List[TopLevelVariable]: return self._variables_top_level diff --git a/slither/core/declarations/__init__.py b/slither/core/declarations/__init__.py index f6e902e06..9d727da8e 100644 --- a/slither/core/declarations/__init__.py +++ b/slither/core/declarations/__init__.py @@ -1,6 +1,8 @@ from .contract import Contract from .enum import Enum from .event import Event +from .event_contract import EventContract +from .event_top_level import EventTopLevel from .function import Function from .import_directive import Import from .modifier import Modifier diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 458f951f5..5403d227a 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -33,7 +33,7 @@ if TYPE_CHECKING: from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType from slither.core.declarations import ( Enum, - Event, + EventContract, Modifier, EnumContract, StructureContract, @@ -73,7 +73,7 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods self._enums: Dict[str, "EnumContract"] = {} self._structures: Dict[str, "StructureContract"] = {} - self._events: Dict[str, "Event"] = {} + self._events: Dict[str, "EventContract"] = {} # map accessible variable from name -> variable # do not contain private variables inherited from contract self._variables: Dict[str, "StateVariable"] = {} @@ -278,28 +278,28 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods ################################################################################### @property - def events(self) -> List["Event"]: + def events(self) -> List["EventContract"]: """ list(Event): List of the events """ return list(self._events.values()) @property - def events_inherited(self) -> List["Event"]: + def events_inherited(self) -> List["EventContract"]: """ list(Event): List of the inherited events """ return [e for e in self.events if e.contract != self] @property - def events_declared(self) -> List["Event"]: + def events_declared(self) -> List["EventContract"]: """ list(Event): List of the events declared within the contract (not inherited) """ return [e for e in self.events if e.contract == self] @property - def events_as_dict(self) -> Dict[str, "Event"]: + def events_as_dict(self) -> Dict[str, "EventContract"]: return self._events # endregion diff --git a/slither/core/declarations/event.py b/slither/core/declarations/event.py index 1b58ff63b..7149e20c0 100644 --- a/slither/core/declarations/event.py +++ b/slither/core/declarations/event.py @@ -1,14 +1,10 @@ -from typing import List, Tuple, TYPE_CHECKING +from typing import List, Tuple -from slither.core.declarations.contract_level import ContractLevel from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables.event_variable import EventVariable -if TYPE_CHECKING: - from slither.core.declarations import Contract - -class Event(ContractLevel, SourceMapping): +class Event(SourceMapping): def __init__(self) -> None: super().__init__() self._name = None @@ -39,25 +35,9 @@ class Event(ContractLevel, SourceMapping): name, parameters = self.signature return name + "(" + ",".join(parameters) + ")" - @property - def canonical_name(self) -> str: - """Return the function signature as a str - Returns: - str: contract.func_name(type1,type2) - """ - return self.contract.name + "." + self.full_name - @property def elems(self) -> List["EventVariable"]: return self._elems - def is_declared_by(self, contract: "Contract") -> bool: - """ - Check if the element is declared by the contract - :param contract: - :return: - """ - return self.contract == contract - def __str__(self) -> str: return self.name diff --git a/slither/core/declarations/event_contract.py b/slither/core/declarations/event_contract.py new file mode 100644 index 000000000..652f8ca20 --- /dev/null +++ b/slither/core/declarations/event_contract.py @@ -0,0 +1,25 @@ +from typing import TYPE_CHECKING + +from slither.core.declarations.contract_level import ContractLevel +from slither.core.declarations import Event + +if TYPE_CHECKING: + from slither.core.declarations import Contract + + +class EventContract(Event, ContractLevel): + def is_declared_by(self, contract: "Contract") -> bool: + """ + Check if the element is declared by the contract + :param contract: + :return: + """ + return self.contract == contract + + @property + def canonical_name(self) -> str: + """Return the function signature as a str + Returns: + str: contract.func_name(type1,type2) + """ + return self.contract.name + "." + self.full_name diff --git a/slither/core/declarations/event_top_level.py b/slither/core/declarations/event_top_level.py new file mode 100644 index 000000000..5f9f1774d --- /dev/null +++ b/slither/core/declarations/event_top_level.py @@ -0,0 +1,13 @@ +from typing import TYPE_CHECKING + +from slither.core.declarations import Event +from slither.core.declarations.top_level import TopLevel + +if TYPE_CHECKING: + from slither.core.scope.scope import FileScope + + +class EventTopLevel(Event, TopLevel): + def __init__(self, scope: "FileScope") -> None: + super().__init__() + self.file_scope: "FileScope" = scope diff --git a/slither/core/scope/scope.py b/slither/core/scope/scope.py index 937a05136..784b17cb2 100644 --- a/slither/core/scope/scope.py +++ b/slither/core/scope/scope.py @@ -7,6 +7,7 @@ from crytic_compile.utils.naming import Filename from slither.core.declarations import Contract, Import, Pragma from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.using_for_top_level import UsingForTopLevel from slither.core.declarations.structure_top_level import StructureTopLevel @@ -35,6 +36,7 @@ class FileScope: # So we simplify the logic and have the scope fields all populated self.custom_errors: Set[CustomErrorTopLevel] = set() self.enums: Dict[str, EnumTopLevel] = {} + self.events: Dict[str, EventTopLevel] = {} # Functions is a list instead of a dict # Because we parse the function signature later on # So we simplify the logic and have the scope fields all populated @@ -54,7 +56,7 @@ class FileScope: # Name -> type alias self.type_aliases: Dict[str, TypeAlias] = {} - def add_accesible_scopes(self) -> bool: + def add_accesible_scopes(self) -> bool: # pylint: disable=too-many-branches """ Add information from accessible scopes. Return true if new information was obtained @@ -74,6 +76,9 @@ class FileScope: if not _dict_contain(new_scope.enums, self.enums): self.enums.update(new_scope.enums) learn_something = True + if not _dict_contain(new_scope.events, self.events): + self.events.update(new_scope.events) + learn_something = True if not new_scope.functions.issubset(self.functions): self.functions |= new_scope.functions learn_something = True diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 3535f2604..b1bb7c66b 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -269,6 +269,8 @@ class SlitherCore(Context): self._compute_offsets_from_thing(event) for enum in compilation_unit.enums_top_level: self._compute_offsets_from_thing(enum) + for event in compilation_unit.events_top_level: + self._compute_offsets_from_thing(event) for function in compilation_unit.functions_top_level: self._compute_offsets_from_thing(function) for st in compilation_unit.structures_top_level: diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index 3dd6e2fd5..34e2f2430 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -4,7 +4,7 @@ from typing import Any, List, Dict, Callable, TYPE_CHECKING, Union, Set, Sequenc from slither.core.declarations import ( Modifier, - Event, + EventContract, EnumContract, StructureContract, Function, @@ -747,12 +747,12 @@ class ContractSolc(CallerContextExpression): self._contract.events_as_dict.update(father.events_as_dict) for event_to_parse in self._eventsNotParsed: - event = Event() + event = EventContract() event.set_contract(self._contract) event.set_offset(event_to_parse["src"], self._contract.compilation_unit) - event_parser = EventSolc(event, event_to_parse, self) # type: ignore - event_parser.analyze(self) # type: ignore + event_parser = EventSolc(event, event_to_parse, self._slither_parser) # type: ignore + event_parser.analyze() # type: ignore self._contract.events_as_dict[event.full_name] = event except (VariableNotFound, KeyError) as e: self.log_incorrect_parsing(f"Missing event {e}") diff --git a/slither/solc_parsing/declarations/event.py b/slither/solc_parsing/declarations/event.py index 6531e6536..4a7d62389 100644 --- a/slither/solc_parsing/declarations/event.py +++ b/slither/solc_parsing/declarations/event.py @@ -8,7 +8,7 @@ from slither.solc_parsing.variables.event_variable import EventVariableSolc from slither.core.declarations.event import Event if TYPE_CHECKING: - from slither.solc_parsing.declarations.contract import ContractSolc + from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc class EventSolc: @@ -16,11 +16,12 @@ class EventSolc: Event class """ - def __init__(self, event: Event, event_data: Dict, contract_parser: "ContractSolc") -> None: + def __init__( + self, event: Event, event_data: Dict, slither_parser: "SlitherCompilationUnitSolc" + ) -> None: self._event = event - event.set_contract(contract_parser.underlying_contract) - self._parser_contract = contract_parser + self._slither_parser = slither_parser if self.is_compact_ast: self._event.name = event_data["name"] @@ -41,18 +42,16 @@ class EventSolc: @property def is_compact_ast(self) -> bool: - return self._parser_contract.is_compact_ast + return self._slither_parser.is_compact_ast - def analyze(self, contract: "ContractSolc") -> None: + def analyze(self) -> None: for elem_to_parse in self._elemsNotParsed: elem = EventVariable() # Todo: check if the source offset is always here if "src" in elem_to_parse: - elem.set_offset( - elem_to_parse["src"], self._parser_contract.underlying_contract.compilation_unit - ) + elem.set_offset(elem_to_parse["src"], self._slither_parser.compilation_unit) elem_parser = EventVariableSolc(elem, elem_to_parse) - elem_parser.analyze(contract) + elem_parser.analyze(self._slither_parser) self._event.elems.append(elem) diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 2261350b4..e7fa99521 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -134,6 +134,9 @@ def find_top_level( if var_name in scope.enums: return scope.enums[var_name], False + if var_name in scope.events: + return scope.events[var_name], False + for import_directive in scope.imports: if import_directive.alias == var_name: new_val = SolidityImportPlaceHolder(import_directive) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 85921ce74..08ee62d80 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -10,6 +10,7 @@ from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.declarations import Contract from slither.core.declarations.custom_error_top_level import CustomErrorTopLevel from slither.core.declarations.enum_top_level import EnumTopLevel +from slither.core.declarations.event_top_level import EventTopLevel from slither.core.declarations.function_top_level import FunctionTopLevel from slither.core.declarations.import_directive import Import from slither.core.declarations.pragma_directive import Pragma @@ -23,6 +24,7 @@ from slither.solc_parsing.declarations.caller_context import CallerContextExpres from slither.solc_parsing.declarations.contract import ContractSolc from slither.solc_parsing.declarations.custom_error import CustomErrorSolc from slither.solc_parsing.declarations.function import FunctionSolc +from slither.solc_parsing.declarations.event import EventSolc from slither.solc_parsing.declarations.structure_top_level import StructureTopLevelSolc from slither.solc_parsing.declarations.using_for_top_level import UsingForTopLevelSolc from slither.solc_parsing.exceptions import VariableNotFound @@ -347,6 +349,15 @@ class SlitherCompilationUnitSolc(CallerContextExpression): self._compilation_unit.type_aliases[alias] = type_alias scope.type_aliases[alias] = type_alias + elif top_level_data[self.get_key()] == "EventDefinition": + event = EventTopLevel(scope) + event.set_offset(top_level_data["src"], self._compilation_unit) + + event_parser = EventSolc(event, top_level_data, self) # type: ignore + event_parser.analyze() # type: ignore + scope.events[event.full_name] = event + self._compilation_unit.events_top_level.append(event) + else: raise SlitherException(f"Top level {top_level_data[self.get_key()]} not supported") diff --git a/slither/tools/flattening/flattening.py b/slither/tools/flattening/flattening.py index 55e1af21d..9cb2abc3f 100644 --- a/slither/tools/flattening/flattening.py +++ b/slither/tools/flattening/flattening.py @@ -77,6 +77,7 @@ class Flattening: self._get_source_code_top_level(compilation_unit.structures_top_level) self._get_source_code_top_level(compilation_unit.enums_top_level) + self._get_source_code_top_level(compilation_unit.events_top_level) self._get_source_code_top_level(compilation_unit.custom_errors) self._get_source_code_top_level(compilation_unit.variables_top_level) self._get_source_code_top_level(compilation_unit.functions_top_level) diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 6ca9c6557..2acd43e0f 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -24,7 +24,7 @@ from slither.vyper_parsing.declarations.struct import StructVyper from slither.vyper_parsing.variables.state_variable import StateVariableVyper from slither.vyper_parsing.declarations.function import FunctionVyper from slither.core.declarations.function_contract import FunctionContract -from slither.core.declarations import Contract, StructureContract, EnumContract, Event +from slither.core.declarations import Contract, StructureContract, EnumContract, EventContract from slither.core.variables.state_variable import StateVariable @@ -478,7 +478,7 @@ class ContractVyper: # pylint: disable=too-many-instance-attributes def parse_events(self) -> None: for event_to_parse in self._eventsNotParsed: - event = Event() + event = EventContract() event.set_contract(self._contract) event.set_offset(event_to_parse.src, self._contract.compilation_unit) diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index bc57dc51b..61250c5af 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -462,6 +462,7 @@ ALL_TESTS = [ Test("aliasing/main.sol", ["0.8.19"]), Test("type-aliases.sol", ["0.8.19"]), Test("enum-max-min.sol", ["0.8.19"]), + Test("event-top-level.sol", ["0.8.22"]), ] # create the output folder if needed try: diff --git a/tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip b/tests/e2e/solc_parsing/test_data/compile/event-top-level.sol-0.8.22-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..ed82f32b17350e7c70788a8d84e0d02dcbdd0bba GIT binary patch literal 2022 zcma)-c{~#g1IIUHBvRzQkBl7kxX+C!SMey@=wMb@=4#_*Dw2uHk;r1sZ02mt$K)J^ zJaXo~>SbcC=2}zX>3RQuKcDCK`{Vojfd zXaN9#+mW|JaC*4VFg?ugiP6V~Vtj5#g@xY5`5^D20@0DT_3vOqLxcs60B!&PaR7jI zQc{57FT?Pn;r@C{QBr3JTC+`wkm4a{qdbmnkvg|~-X?Wg9(iJ6v0+ODmY=rkD7Q^B z@Yo<`JC=%1j^M)cLWElT-iH$~#WgRhfD>{y@wY5PR!$A6W#mR@5x?!{3n$Pf(q(ae zFZxWjJ0JXY?vd!jL!t`1j6Q;6GHAVqfy@SWXC{%qVRL7K^&AmqPH%+aRUZ6$HhQ-! z0#!ZnV@g86a;9kisRHacvMt$8YPz;?{yk@?hW)NV1X@V$ZU!d4i}dLidRv2t8xF%m z&~W{*KfzG;#CLnr73^S76S*1~Up7H`;XP$TZh|9(lhGq=kMO%%RsIZNy$Ck=VUkQ0 z@n$UiG=_O}j8U_?n2Z0;+EuD~w{5hrrzB+Dg8Evo&QM>y=AA?##NzJASxl2m``V$g z)Q5}Rm0jj<-FInXD=tj68+{eM$_}}@?i0Q{f{)&x)za?DoE3_@NPrfaUCNS-%wvjd z>Udv2@99SwJCY+rcaPna9I)oea`AjIYnqX-tHUc8!u?I4*RDT-*03VMijMhG9XWyF zjP6+Hn{6|9zB#3*n9VIsqsPK87WO zN|*I?x145$+l`7Ye^Ge4Y)6S3H)rT_6?t(g^s2xaz8xJH(rtmI2-z=cR3@5D;Jdsb@dk+>2veK1M68klnfl-FkQ&Oc9La`GDCS4>n2@ z*pMJ-R9~U)kp?K4Lzc@KpHGJVT+9#_bzz^17MM4L`fY{9Hg`(XqM||fwy-|U5$tH| zf)OwHF;X&T&$ae1h@-<0`b5%aP<$Dii}{*SnWo5DA@;j~NM_`0Y) z%4h9qHtT?{8Wt?aCbxF-*NfmrJ%Zo#?}{eIwxoRVag8hg zqm|Jtx35W?|B$NaS}h6=KaqEQ)M3B(eErpeH``zht4U}($)L~d^Tk^4m(EYCmrdt) z((S0|I;e5BqTyKwN{Q(e1xI%oLSX~s`0`}L!i3nmvgL(N3w(rp>ENVAm=eFUmK{6@ z?KR}DEpy$8^GI5|72J5#3zof`)}h`bIjZVdSn#C^%XBv_Ji4?Iz36yr(KarNx8)Tv ztRfSC8n)eFUdJ1{29dfN)68dCkV;;=XRj%Fp6eVB)kF_zy!{!$5OeP-OelCY{ z%>j<`y)XozR&dekLNE#4nIY3qcj#0L%h8E4f)rQ=!}cisL@-lbL@S_M*`sb z>3)VO{p%b=m)c7|2jhkbG7P>EC;kjq9R3V2>e!RBQvS7^!nbtMPU+px)GRJ{|1!Z0 z4UN0bD+L9uzl|58#(_JzOPC~7HjW@3QB1sIf=Xj|2ymu;J}F)_y}_o7^!MPaWsSe96{95a5R z`5pFM$H-Rp1$~_ciG77b{e< z-6*P8?qynzlHZhePUxkpDpLsqxl!mAkjXQT5_dc~c>M{!^HgeQ#RZL+w4&13ry9C9&cY$YpFh@5{i+eq(;T1~N-!^45| zi>&pP3h%|~0l$vG|B{3UoKh=TO#Sxm{srI(wm7BppwbJ0v0|HD9wVD8aofC2N#oH> zpoZG6h?wfx^IGq`aw5{fb_io!27jt$RY;Ehj`yTvY00EydFu!8Uch^MxUq4KEiVnr zAP3Q%x@W6AZv^59_8JKu+-?S0GsV7({UG6t>QJRDhd0=i9RAkd`8Coj!Fr$QORa?@ zYm4cx$8uh#3R0`orJ@FjFP^{d)+^FbK+zY(50ZT_yUaT|!!+WwsG#Ah*0^e>sXigGw(QRz4Q?Dr+TD6*Z8DpEH~` p-Cclu5dQx!-{1cIU*drO;9siP-Q|ejKX>5odj4k2Z<_-Ee*>9z)$#xU literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/event-top-level.sol b/tests/e2e/solc_parsing/test_data/event-top-level.sol new file mode 100644 index 000000000..fa64e1bf7 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/event-top-level.sol @@ -0,0 +1,7 @@ +event MyEvent(uint256 a); + +contract T { + function a() public { + emit MyEvent(2); + } +} diff --git a/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json b/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json new file mode 100644 index 000000000..58c6a3ab6 --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/event-top-level.sol-0.8.22-compact.json @@ -0,0 +1,5 @@ +{ + "T": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file From 912d6b2e4e21a770437abbb5ac9e260f50ffa873 Mon Sep 17 00:00:00 2001 From: Usmann Khan Date: Thu, 16 Nov 2023 14:16:26 -0800 Subject: [PATCH 297/338] Error when a missing contract is specified to read-storage. Previously this just silently exited --- slither/tools/read_storage/__main__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index 8415ae185..3baa5d351 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -7,6 +7,7 @@ import argparse from crytic_compile import cryticparser from slither import Slither +from slither.exceptions import SlitherError from slither.tools.read_storage.read_storage import SlitherReadStorage, RpcInfo @@ -129,6 +130,8 @@ def main() -> None: if args.contract_name: contracts = slither.get_contract_from_name(args.contract_name) + if len(contracts) == 0: + raise SlitherError(f"Contract {args.contract_name} not found.") else: contracts = slither.contracts From 80b624ccf65c683d593c750cef9ab3825a27b09a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:16 +0000 Subject: [PATCH 298/338] Bump cachix/install-nix-action from 23 to 24 Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 23 to 24. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v23...v24) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f04436bd3..4a646bb42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v23 + uses: cachix/install-nix-action@v24 - name: Set up cachix if: matrix.type == 'dapp' From 4673fdae7f74a384d4f95a84ea67380bf69396b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:18 +0000 Subject: [PATCH 299/338] Bump actions/configure-pages from 3 to 4 Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 3 to 4. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 29356c0c6..d92e5b091 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - uses: actions/setup-python@v4 with: python-version: '3.8' From 11def5d607b2a5aee7f7b15484079c1d7f9a39e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:22 +0000 Subject: [PATCH 300/338] Bump actions/deploy-pages from 2 to 3 Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 3. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 29356c0c6..eca7ef0b2 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,4 +43,4 @@ jobs: path: './html/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v3 From 9b74e214eb6e8cdca21bb45f009c0fe47e912178 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:43:26 +0000 Subject: [PATCH 301/338] Bump pypa/gh-action-pypi-publish from 1.8.10 to 1.8.11 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.10 to 1.8.11. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.10...v1.8.11) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7b4d61e89..e0ab4b543 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: path: dist/ - name: publish - uses: pypa/gh-action-pypi-publish@v1.8.10 + uses: pypa/gh-action-pypi-publish@v1.8.11 - name: sign uses: sigstore/gh-action-sigstore-python@v2.1.0 From ff0e85d2c11203985924557ba848c861fc30cc3d Mon Sep 17 00:00:00 2001 From: Atreay Kukanur <66585295+ATREAY@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:12:48 +0000 Subject: [PATCH 302/338] Substituted the letter 'z' with 'x' in pre-declaration --- slither/detectors/variables/predeclaration_usage_local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/variables/predeclaration_usage_local.py b/slither/detectors/variables/predeclaration_usage_local.py index b4d75e51a..9816dd6e2 100644 --- a/slither/detectors/variables/predeclaration_usage_local.py +++ b/slither/detectors/variables/predeclaration_usage_local.py @@ -36,7 +36,7 @@ class PredeclarationUsageLocal(AbstractDetector): ```solidity contract C { function f(uint z) public returns (uint) { - uint y = x + 9 + z; // 'z' is used pre-declaration + uint y = x + 9 + z; // 'x' is used pre-declaration uint x = 7; if (z % 2 == 0) { From a0365982add762e2bb4abb80cdea9b272bcddd61 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 2 Jan 2024 09:20:59 -0500 Subject: [PATCH 303/338] updated mutator --- slither/tools/mutator/__main__.py | 81 +++++++++++++++---- slither/tools/mutator/mutators/MIA.py | 73 +++++++++++------ slither/tools/mutator/mutators/MVIE.py | 45 ++++++----- slither/tools/mutator/mutators/MVIV.py | 45 ++++++----- .../mutator/mutators/abstract_mutator.py | 19 +++-- slither/tools/mutator/utils/command_line.py | 2 - slither/tools/mutator/utils/file_handling.py | 77 ++++++++++++++++++ .../tools/mutator/utils/generic_patching.py | 30 ++++--- .../tools/mutator/utils/replace_conditions.py | 43 ++++++++++ .../mutator/utils/testing_generated_mutant.py | 31 +++++++ 10 files changed, 349 insertions(+), 97 deletions(-) create mode 100644 slither/tools/mutator/utils/file_handling.py create mode 100644 slither/tools/mutator/utils/replace_conditions.py create mode 100644 slither/tools/mutator/utils/testing_generated_mutant.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 84286ce66..fde87e5e2 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,7 +2,8 @@ import argparse import inspect import logging import sys -from typing import Type, List, Any +from typing import Type, List, Any, Dict, Tuple +import os from crytic_compile import cryticparser @@ -10,9 +11,10 @@ from slither import Slither from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators +from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list logging.basicConfig() -logger = logging.getLogger("Slither") +logger = logging.getLogger("Slither-Mutate") logger.setLevel(logging.INFO) @@ -22,7 +24,6 @@ logger.setLevel(logging.INFO) ################################################################################### ################################################################################### - def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", @@ -39,6 +40,22 @@ def parse_args() -> argparse.Namespace: default=False, ) + parser.add_argument( + "--test-cmd", + help="Command line needed to run the tests for your project" + ) + + parser.add_argument( + "--test-dir", + help="Directory of tests" + ) + + # parameter to ignore the interfaces, libraries + parser.add_argument( + "--ignore-dirs", + help="Directories to ignore" + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -73,16 +90,52 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: - args = parse_args() - - print(args.codebase) - sl = Slither(args.codebase, **vars(args)) - - for compilation_unit in sl.compilation_units: - for M in _get_mutators(): - m = M(compilation_unit) - m.mutate() - - + # print(os.path.isdir(args.codebase)) # provided file/folder + + # arguments + test_command: str = args.test_cmd + test_directory: str = args.test_dir + paths_to_ignore: List[str] = args.ignore_dirs + + # get all the contracts as a list from given codebase + sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) + + print("Starting Mutation Campaign in", args.codebase, "\n") + for filename in sol_file_list: + # slither object + sl = Slither(filename, **vars(args)) + + # folder where backup files and valid mutants created + output_folder = os.getcwd() + "/mutation_campaign" + + # create a backup files + files_dict = backup_source_file(sl.source_code, output_folder) + + # total count of valid mutants + total_count = 0 + + # mutation + try: + for compilation_unit_of_main_file in sl.compilation_units: + # compilation_unit_of_main_file = sl.compilation_units[-1] + # for i in compilation_unit_of_main_file.contracts: + # print(i.name) + for M in _get_mutators(): + m = M(compilation_unit_of_main_file) + count = m.mutate(test_command, test_directory) + if count != None: + total_count = total_count + count + except Exception as e: + logger.error(e) + + # transfer and delete the backup files + transfer_and_delete(files_dict) + + # output + print(f"Done mutating, '{filename}'") + print(f"Valid mutant count: '{total_count}'\n") + + print("Finished Mutation Campaign in", args.codebase, "\n") # endregion + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 405888f8b..370f419c1 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,39 +1,60 @@ -from typing import Dict - +from typing import Dict, Tuple from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass - +from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite +from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file_specific_line +from slither.tools.mutator.utils.file_handling import create_mutant_file class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} - + for contract in self.slither.contracts: - - for function in contract.functions_declared + list(contract.modifiers_declared): - - for node in function.nodes: - if node.type == NodeType.IF: - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] - - # Replace the expression with true - new_str = "true" - - create_patch(result, in_file, start, stop, old_str, new_str) - - return result + if not contract.is_library: + if not contract.is_interface: + for function in contract.functions_declared + list(contract.modifiers_declared): + for node in function.nodes: + if node.contains_if(): + # print(node.expression) + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + # old_str = in_file_str[start:stop] + old_str = str(node.expression) + line_no = node.source_mapping.lines + print(line_no) + # Replace the expression with true + new_str = "true" + + replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) + + # compile and run tests + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # print(True) + # generate the mutant and patch + create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) + create_patch(result, in_file, start, stop, old_str, new_str) + + + + return (result, self.VALID_MUTANTS_COUNT) + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index a16a8252e..9dccc9f13 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,36 +1,41 @@ -from typing import Dict +from typing import Dict, Tuple from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement - +from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - return result + if not contract.is_library: + if not contract.is_interface: + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + + return (result, self.VALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index d4a7c5486..9e7b143ae 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,37 +1,42 @@ -from typing import Dict +from typing import Dict, Tuple from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement - +from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing + VALID_MUTANTS_COUNT = 1 - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - return result + if not contract.is_library: + if not contract.is_interface: + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + return (result, self.VALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 169d8725e..ab295e295 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -4,9 +4,10 @@ from enum import Enum from typing import Optional, Dict from slither.core.compilation_unit import SlitherCompilationUnit +from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff -logger = logging.getLogger("Slither") +logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): @@ -68,13 +69,14 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- ) @abc.abstractmethod - def _mutate(self) -> Dict: + def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" return {} - def mutate(self) -> None: - all_patches = self._mutate() - + def mutate(self, testing_command: str, testing_directory: str) -> int: + # call _mutate function from different mutators + (all_patches, valid_mutant_count) = self._mutate(testing_command, testing_directory) + if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") return @@ -93,4 +95,11 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") + # print the differences print(diff) + + return valid_mutant_count + + + + \ No newline at end of file diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index feb479c5c..80d610a69 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -1,9 +1,7 @@ from typing import List, Type - from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.utils.myprettytable import MyPrettyTable - def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: mutators_list = [] for detector in mutators_classes: diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py new file mode 100644 index 000000000..800232a5a --- /dev/null +++ b/slither/tools/mutator/utils/file_handling.py @@ -0,0 +1,77 @@ +import os +from typing import Dict, Tuple, List +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to backup the source file +def backup_source_file(source_code: Dict, output_folder: str) -> Dict: + duplicated_files = {} + os.makedirs(output_folder, exist_ok=True) + + for file_path, content in source_code.items(): + directory, filename = os.path.split(file_path) + new_filename = f"{output_folder}/backup_{filename}" + new_file_path = os.path.join(directory, new_filename) + + with open(new_file_path, 'w') as new_file: + new_file.write(content) + duplicated_files[file_path] = new_file_path + + return duplicated_files + +# function to transfer the original content to the sol file after campaign +def transfer_and_delete(files_dict: Dict) -> None: + try: + for item, value in files_dict.items(): + with open(value, 'r') as duplicated_file: + content = duplicated_file.read() + + with open(item, 'w') as original_file: + original_file.write(content) + + os.remove(value) + except Exception as e: + logger.error(f"Error transferring content: {e}") + +#function to create new mutant file +def create_mutant_file(file: str, count: int, rule: str) -> None: + try: + directory, filename = os.path.split(file) + # Read content from the duplicated file + with open(file, 'r') as source_file: + content = source_file.read() + + # Write content to the original file + mutant_name = filename.split('.')[0] + with open("mutation_campaign/" + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + mutant_file.write(content) + + except Exception as e: + logger.error(f"Error creating mutant: {e}") + +# function to get the contracts list +def get_sol_file_list(codebase: str, ignore_paths: List[str]) -> List[str]: + sol_file_list = [] + + # if input is contract file + if os.path.isfile(codebase): + return [codebase] + + # if input is folder + elif os.path.isdir(codebase): + directory = os.path.abspath(codebase) + for file in os.listdir(directory): + filename = os.path.join(directory, file) + if os.path.isfile(filename): + sol_file_list.append(filename) + elif os.path.isdir(filename): + directory_name, dirname = os.path.split(filename) + if dirname in ignore_paths: + continue + for i in get_sol_file_list(filename, ignore_paths): + sol_file_list.append(i) + + return sol_file_list +# to_do: create a function to delete the commands from the sol file +# def remove_comments(self) -> None: \ No newline at end of file diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py index d773ea784..03ccadec7 100644 --- a/slither/tools/mutator/utils/generic_patching.py +++ b/slither/tools/mutator/utils/generic_patching.py @@ -1,11 +1,14 @@ from typing import Dict +import os from slither.core.declarations import Contract from slither.core.variables.variable import Variable from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite +from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file +from slither.tools.mutator.utils.file_handling import create_mutant_file - -def remove_assignement(variable: Variable, contract: Contract, result: Dict): +def remove_assignement(variable: Variable, contract: Contract, result: Dict, test_cmd: str, test_dir: str) -> bool: """ Remove the variable's initial assignement @@ -25,12 +28,19 @@ def remove_assignement(variable: Variable, contract: Contract, result: Dict): old_str = in_file_str[start:stop] new_str = old_str[: old_str.find("=")] + + replace_string_in_source_file(in_file, in_file_str[variable.source_mapping.start + old_str.find("="):variable.source_mapping.end], '') - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - ) + # compile and run tests before the mutant generated before patching + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # create_mutant_file(in_file, ) + create_patch( + result, + in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + ) + return True \ No newline at end of file diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py new file mode 100644 index 000000000..82d6c11c9 --- /dev/null +++ b/slither/tools/mutator/utils/replace_conditions.py @@ -0,0 +1,43 @@ +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to replace the string +def replace_string_in_source_file(file_path: str, old_string: str, new_string: str) -> None: + try: + # Read the content of the Solidity file + with open(file_path, 'r') as file: + content = file.read() + + # Perform the string replacement + modified_content = content.replace(old_string, new_string) + + # Write the modified content back to the file + with open(file_path, 'w') as file: + file.write(modified_content) + + logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.") + except Exception as e: + logger.error(f"Error replacing string: {e}") + +# function to replace the string in a specific line +def replace_string_in_source_file_specific_line(file_path: str, old_string: str, new_string: str, line_number : int) -> None: + try: + # Read the content of the Solidity file + with open(file_path, 'r') as file: + lines = file.readlines() + + if 1 <= line_number <= len(lines): + # Replace the old string with the new string on the specified line + lines[line_number - 1] = lines[line_number - 1].replace(old_string, new_string) + + # Write the modified content back to the file + with open(file_path, 'w') as file: + file.writelines(lines) + + logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.' at '{line_number}") + else: + logger.error(f'Error: Line number {line_number} is out of range') + + except Exception as e: + logger.erro(f'Error: {e}') \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py new file mode 100644 index 000000000..1c7de9acf --- /dev/null +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -0,0 +1,31 @@ +import crytic_compile +import subprocess +import os +import logging + +logger = logging.getLogger("Slither-Mutate") + +# function to compile the generated mutant +def compile_generated_mutant(file_path: str) -> bool: + try: + crytic_compile.CryticCompile(file_path) + return True + except Exception as e: # pylint: disable=broad-except + logger.error("Error Crytic Compile", e) + +# function to run the tests +def run_test_suite(cmd: str, dir: str) -> bool: + try: + # Change to the foundry folder + # os.chdir(dir) + + result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if not result.stderr: + return True + except subprocess.CalledProcessError as e: + logger.error(f"Error executing 'forge test': {e}") + return False + except Exception as e: + logger.error(f"An unexpected error occurred: {e}") + return False \ No newline at end of file From 37c23e11ce63f229593a500e7a1d8512d00cce43 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 3 Jan 2024 11:35:08 -0500 Subject: [PATCH 304/338] Updated replace string logic --- slither/tools/mutator/__main__.py | 31 +++++--- slither/tools/mutator/mutators/MIA.py | 72 ++++++++++--------- slither/tools/mutator/mutators/MVIE.py | 44 ++++++------ slither/tools/mutator/mutators/MVIV.py | 44 ++++++------ .../mutator/mutators/abstract_mutator.py | 8 +-- .../tools/mutator/mutators/all_mutators.py | 4 +- slither/tools/mutator/utils/file_handling.py | 10 ++- .../tools/mutator/utils/replace_conditions.py | 9 ++- .../mutator/utils/testing_generated_mutant.py | 7 +- 9 files changed, 131 insertions(+), 98 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index fde87e5e2..9cb1a9f8d 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -40,11 +40,13 @@ def parse_args() -> argparse.Namespace: default=False, ) + # argument to add the test command parser.add_argument( "--test-cmd", help="Command line needed to run the tests for your project" ) + # argument to add the test directory - containing all the tests parser.add_argument( "--test-dir", help="Directory of tests" @@ -96,13 +98,14 @@ def main() -> None: # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir - paths_to_ignore: List[str] = args.ignore_dirs + paths_to_ignore: List[str] | None = args.ignore_dirs # get all the contracts as a list from given codebase sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) print("Starting Mutation Campaign in", args.codebase, "\n") for filename in sol_file_list: + contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) @@ -112,9 +115,12 @@ def main() -> None: # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) - # total count of valid mutants + # total count of mutants total_count = 0 - + + # count of valid mutants + v_count = 0 + # mutation try: for compilation_unit_of_main_file in sl.compilation_units: @@ -123,19 +129,24 @@ def main() -> None: # print(i.name) for M in _get_mutators(): m = M(compilation_unit_of_main_file) - count = m.mutate(test_command, test_directory) - if count != None: - total_count = total_count + count + v_count, i_count = m.mutate(test_command, test_directory, contract_name) + if v_count != None and i_count != None: + total_count = total_count + v_count + i_count except Exception as e: logger.error(e) + except KeyboardInterrupt: + # transfer and delete the backup files if interrupted + logger.error("\nExecution interrupted by user (Ctrl + C). Cleaning up...") + transfer_and_delete(files_dict) + # transfer and delete the backup files transfer_and_delete(files_dict) - - # output - print(f"Done mutating, '{filename}'") - print(f"Valid mutant count: '{total_count}'\n") + + # output + print(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n") + print("Finished Mutation Campaign in", args.codebase, "\n") # endregion \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 370f419c1..b1c55d184 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -11,47 +11,53 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - for function in contract.functions_declared + list(contract.modifiers_declared): - for node in function.nodes: - if node.contains_if(): - # print(node.expression) - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + for function in contract.functions_declared + list(contract.modifiers_declared): + for node in function.nodes: + if node.contains_if(): + # print(node.expression) + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - # old_str = in_file_str[start:stop] - old_str = str(node.expression) - line_no = node.source_mapping.lines - print(line_no) - # Replace the expression with true - new_str = "true" - - replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) - - # compile and run tests - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # print(True) - # generate the mutant and patch - create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) - create_patch(result, in_file, start, stop, old_str, new_str) - + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + # old_str = in_file_str[start:stop] + old_str = str(node.expression) + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = "true" + print(line_no[0]) + replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) + + # compile and run tests + if compile_generated_mutant(in_file): + if run_test_suite(test_cmd, test_dir): + # generate the mutant and patch + create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) + create_patch(result, in_file, start, stop, old_str, new_str) + self.VALID_MUTANTS_COUNT = self.VALID_MUTANTS_COUNT + 1 + else: + self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 + else: + self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 + print(self.INVALID_MUTANTS_COUNT) + - return (result, self.VALID_MUTANTS_COUNT) + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 9dccc9f13..1c99b24ee 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -11,31 +11,33 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - if not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + if not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + - return (result, self.VALID_MUTANTS_COUNT) + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 9e7b143ae..bb1c4cabe 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -11,32 +11,34 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 1 + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str) -> Tuple[(Dict, int)]: + def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: result: Dict = {} variable: Variable for contract in self.slither.contracts: - if not contract.is_library: - if not contract.is_interface: - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + # if not contract.is_library: + # if not contract.is_interface: + if contract_name == str(contract.name): + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - if isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + if isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - return (result, self.VALID_MUTANTS_COUNT) + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if(remove_assignement(variable, contract, result, test_cmd, test_dir)): + create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) + + return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ab295e295..a79f45906 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,7 +1,7 @@ import abc import logging from enum import Enum -from typing import Optional, Dict +from typing import Optional, Dict, Tuple from slither.core.compilation_unit import SlitherCompilationUnit from slither.tools.doctor.utils import snip_section @@ -73,9 +73,9 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str) -> int: + def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[(int, int)]: # call _mutate function from different mutators - (all_patches, valid_mutant_count) = self._mutate(testing_command, testing_directory) + (all_patches, valid_mutant_count, invalid_mutant_count) = self._mutate(testing_command, testing_directory, contract_name) if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") @@ -98,7 +98,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # print the differences print(diff) - return valid_mutant_count + return (valid_mutant_count, invalid_mutant_count) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 5508fb68e..5a9465c86 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,4 +1,4 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV -from slither.tools.mutator.mutators.MVIE import MVIE +# from slither.tools.mutator.mutators.MVIV import MVIV +# from slither.tools.mutator.mutators.MVIE import MVIE from slither.tools.mutator.mutators.MIA import MIA diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 800232a5a..c041f76d6 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -36,6 +36,7 @@ def transfer_and_delete(files_dict: Dict) -> None: #function to create new mutant file def create_mutant_file(file: str, count: int, rule: str) -> None: + try: directory, filename = os.path.split(file) # Read content from the duplicated file @@ -44,16 +45,19 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # Write content to the original file mutant_name = filename.split('.')[0] - with open("mutation_campaign/" + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + # create folder for each contract + os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) + with open("mutation_campaign/" + mutant_name + '/' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: mutant_file.write(content) except Exception as e: logger.error(f"Error creating mutant: {e}") # function to get the contracts list -def get_sol_file_list(codebase: str, ignore_paths: List[str]) -> List[str]: +def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: sol_file_list = [] - + if ignore_paths == None: + ignore_paths = [] # if input is contract file if os.path.isfile(codebase): return [codebase] diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py index 82d6c11c9..4e3f91454 100644 --- a/slither/tools/mutator/utils/replace_conditions.py +++ b/slither/tools/mutator/utils/replace_conditions.py @@ -1,4 +1,5 @@ import logging +import re logger = logging.getLogger("Slither-Mutate") @@ -8,7 +9,7 @@ def replace_string_in_source_file(file_path: str, old_string: str, new_string: s # Read the content of the Solidity file with open(file_path, 'r') as file: content = file.read() - + # Perform the string replacement modified_content = content.replace(old_string, new_string) @@ -28,8 +29,12 @@ def replace_string_in_source_file_specific_line(file_path: str, old_string: str, lines = file.readlines() if 1 <= line_number <= len(lines): + # remove the spaces in the string + line = lines[line_number - 1].replace(" ", "") + old_string = old_string.replace(" ", "") + # Replace the old string with the new string on the specified line - lines[line_number - 1] = lines[line_number - 1].replace(old_string, new_string) + lines[line_number - 1] = line.replace(old_string.strip(), new_string) # Write the modified content back to the file with open(file_path, 'w') as file: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 1c7de9acf..61b9db214 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -20,11 +20,14 @@ def run_test_suite(cmd: str, dir: str) -> bool: # os.chdir(dir) result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - + # result = subprocess.run(cmd.split(' '), check=True) + print(result.stdout) if not result.stderr: return True except subprocess.CalledProcessError as e: - logger.error(f"Error executing 'forge test': {e}") + print(e.output) + logger.error(f"Error executing '{cmd}': {e}") + return False except Exception as e: logger.error(f"An unexpected error occurred: {e}") From 36eda1b3cb8599033097e613750eb7db154c5b55 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 5 Jan 2024 19:31:25 -0500 Subject: [PATCH 305/338] Added new mutant generators --- slither/tools/mutator/__main__.py | 44 ++++++--- slither/tools/mutator/mutators/LOR.py | 47 ++++++++++ slither/tools/mutator/mutators/MIA.py | 65 ++++--------- slither/tools/mutator/mutators/MVIE.py | 48 ++++------ slither/tools/mutator/mutators/MVIV.py | 41 ++++---- slither/tools/mutator/mutators/ROR.py | 53 +++++++++++ slither/tools/mutator/mutators/SBR.py | 94 +++++++++++++++++++ slither/tools/mutator/mutators/UOI.py | 56 +++++++++++ .../mutator/mutators/abstract_mutator.py | 46 ++++++--- .../tools/mutator/mutators/all_mutators.py | 7 +- slither/tools/mutator/utils/file_handling.py | 34 ++++++- .../tools/mutator/utils/generic_patching.py | 28 +++--- .../mutator/utils/testing_generated_mutant.py | 58 +++++++++++- 13 files changed, 467 insertions(+), 154 deletions(-) create mode 100644 slither/tools/mutator/mutators/LOR.py create mode 100644 slither/tools/mutator/mutators/ROR.py create mode 100644 slither/tools/mutator/mutators/SBR.py create mode 100644 slither/tools/mutator/mutators/UOI.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 9cb1a9f8d..201b39acd 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,6 +4,7 @@ import logging import sys from typing import Type, List, Any, Dict, Tuple import os +import shutil from crytic_compile import cryticparser @@ -12,12 +13,12 @@ from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list +from slither.utils.colors import yellow, magenta logging.basicConfig() logger = logging.getLogger("Slither-Mutate") logger.setLevel(logging.INFO) - ################################################################################### ################################################################################### # region Cli Arguments @@ -52,12 +53,17 @@ def parse_args() -> argparse.Namespace: help="Directory of tests" ) - # parameter to ignore the interfaces, libraries + # argument to ignore the interfaces, libraries parser.add_argument( "--ignore-dirs", help="Directories to ignore" ) + # to_do: add time out argument + parser.add_argument( + "--timeout", + help="Set timeout for test command" + ) # Initiate all the crytic config cli options cryticparser.init(parser) @@ -90,7 +96,6 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### - def main() -> None: args = parse_args() # print(os.path.isdir(args.codebase)) # provided file/folder @@ -98,19 +103,29 @@ def main() -> None: # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir - paths_to_ignore: List[str] | None = args.ignore_dirs + paths_to_ignore: str | None = args.ignore_dirs + timeout: int = args.timeout + + print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) + + if paths_to_ignore: + paths_to_ignore_list = paths_to_ignore.strip('][').split(',') + print(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) + else: + paths_to_ignore_list = [] # get all the contracts as a list from given codebase - sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore) + sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) + + # folder where backup files and valid mutants created + output_folder = os.getcwd() + "/mutation_campaign" + if os.path.exists(output_folder): + shutil.rmtree(output_folder) - print("Starting Mutation Campaign in", args.codebase, "\n") for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - - # folder where backup files and valid mutants created - output_folder = os.getcwd() + "/mutation_campaign" # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) @@ -129,9 +144,9 @@ def main() -> None: # print(i.name) for M in _get_mutators(): m = M(compilation_unit_of_main_file) - v_count, i_count = m.mutate(test_command, test_directory, contract_name) - if v_count != None and i_count != None: - total_count = total_count + v_count + i_count + count_valid, count_invalid = m.mutate(test_command, test_directory, contract_name) + v_count += count_valid + total_count += count_valid + count_invalid except Exception as e: logger.error(e) @@ -143,10 +158,9 @@ def main() -> None: # transfer and delete the backup files transfer_and_delete(files_dict) - # output - print(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n") + print(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) - print("Finished Mutation Campaign in", args.codebase, "\n") + print(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) # endregion \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py new file mode 100644 index 000000000..382a08aee --- /dev/null +++ b/slither/tools/mutator/mutators/LOR.py @@ -0,0 +1,47 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +logical_operators = [ + BinaryType.OROR, + BinaryType.ANDAND, +] + +class LOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "LOR" + HELP = "Logical operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + + contract = self.contract + + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + for function in contract.functions_and_modifiers_declared: + + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in logical_operators: + alternative_ops = logical_operators[:] + alternative_ops.remove(ir.type) + + for op in alternative_ops: + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index b1c55d184..d76369d4d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,63 +1,38 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite -from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file_specific_line -from slither.tools.mutator.utils.file_handling import create_mutant_file class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} + # Retrieve the file + in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = self.contract.compilation_unit.core.source_code[in_file] - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - for function in contract.functions_declared + list(contract.modifiers_declared): - for node in function.nodes: - if node.contains_if(): - # print(node.expression) - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + for function in self.contract.functions_declared + list(self.contract.modifiers_declared): + for node in function.nodes: + if node.type == NodeType.IF: + + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - # old_str = in_file_str[start:stop] - old_str = str(node.expression) - line_no = node.source_mapping.lines - # Replace the expression with true - new_str = "true" - print(line_no[0]) - replace_string_in_source_file_specific_line(in_file, old_str, new_str, line_no[0]) - - # compile and run tests - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # generate the mutant and patch - create_mutant_file(in_file, self.VALID_MUTANTS_COUNT, self.NAME) - create_patch(result, in_file, start, stop, old_str, new_str) - self.VALID_MUTANTS_COUNT = self.VALID_MUTANTS_COUNT + 1 - else: - self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 - else: - self.INVALID_MUTANTS_COUNT = self.INVALID_MUTANTS_COUNT + 1 - print(self.INVALID_MUTANTS_COUNT) + # Replace the expression with true and false + for value in ["true", "false"]: + new_str = value + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) - - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return result diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 1c99b24ee..15b2a20c3 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,43 +1,35 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement -from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} variable: Variable - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue - - if not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + contract = self.contract + + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if not isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) + + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and not isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) + + return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index bb1c4cabe..5e7c0a6e1 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,41 +4,32 @@ from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass from slither.tools.mutator.utils.generic_patching import remove_assignement -from slither.tools.mutator.utils.file_handling import create_mutant_file class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing - VALID_MUTANTS_COUNT = 0 - INVALID_MUTANTS_COUNT = 0 - def _mutate(self, test_cmd: str, test_dir: str, contract_name: str) -> Tuple[(Dict, int, int)]: + def _mutate(self) -> Dict: result: Dict = {} variable: Variable + contract = self.contract + + # Create fault for state variables declaration + for variable in contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue - for contract in self.slither.contracts: - # if not contract.is_library: - # if not contract.is_interface: - if contract_name == str(contract.name): - # Create fault for state variables declaration - for variable in contract.state_variables_declared: - if variable.initialized: - # Cannot remove the initialization of constant variables - if variable.is_constant: - continue + if isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) - if isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - + for function in contract.functions_declared + list(contract.modifiers_declared): + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + remove_assignement(variable, contract, result) - for function in contract.functions_declared + list(contract.modifiers_declared): - for variable in function.local_variables: - if variable.initialized and isinstance(variable.expression, Literal): - if(remove_assignement(variable, contract, result, test_cmd, test_dir)): - create_mutant_file(contract.source_mapping.filename.absolute, self.VALID_MUTANTS_COUNT, self.NAME) - - return (result, self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return result diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py new file mode 100644 index 000000000..9a8942e19 --- /dev/null +++ b/slither/tools/mutator/mutators/ROR.py @@ -0,0 +1,53 @@ +from typing import Dict +from collections import defaultdict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + + +relational_operators = [ + BinaryType.LESS, + BinaryType.GREATER, + BinaryType.LESS_EQUAL, + BinaryType.GREATER_EQUAL, + BinaryType.EQUAL, + BinaryType.NOT_EQUAL, +] + + +class ROR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "ROR" + HELP = "Relational operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + # result["patches"] = defaultdict(list) + contract = self.contract + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + # Retrieve the file + in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = self.contract.compilation_unit.core.source_code[in_file] + + if isinstance(ir, Binary) and ir.type in relational_operators: + alternative_ops = relational_operators[:] + alternative_ops.remove(ir.type) + + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py new file mode 100644 index 000000000..ac35d9540 --- /dev/null +++ b/slither/tools/mutator/mutators/SBR.py @@ -0,0 +1,94 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +import re + +solidity_rules = [ + "abi\.encode\( ==> abi.encodePacked(", + "abi\.encodePacked\( ==> abi.encode(", + "\.call([({]) ==> .delegatecall\\1", + "\.call([({]) ==> .staticcall\\1", + "\.delegatecall([({]) ==> .call\\1", + "\.delegatecall([({]) ==> .staticcall\\1", + "\.staticcall([({]) ==> .delegatecall\\1", + "\.staticcall([({]) ==> .call\\1", + "^now$ ==> 0", + "block.timestamp ==> 0", + "msg.value ==> 0", + "msg.value ==> 1", + "(\s)(wei|gwei) ==> \\1ether", + "(\s)(ether|gwei) ==> \\1wei", + "(\s)(wei|ether) ==> \\1gwei", + "(\s)(minutes|days|hours|weeks) ==> \\1seconds", + "(\s)(seconds|days|hours|weeks) ==> \\1minutes", + "(\s)(seconds|minutes|hours|weeks) ==> \\1days", + "(\s)(seconds|minutes|days|weeks) ==> \\1hours", + "(\s)(seconds|minutes|days|hours) ==> \\1weeks", + "(\s)(memory) ==> \\1storage", + "(\s)(storage) ==> \\1memory", + "(\s)(constant) ==> \\1immutable", + "addmod ==> mulmod", + "mulmod ==> addmod", + "msg.sender ==> tx.origin", + "tx.origin ==> msg.sender", + "([^u])fixed ==> \\1ufixed", + "ufixed ==> fixed", + "(u?)int16 ==> \\1int8", + "(u?)int32 ==> \\1int16", + "(u?)int64 ==> \\1int32", + "(u?)int128 ==> \\1int64", + "(u?)int256 ==> \\1int128" +] + + +class SBR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "SBR" + HELP = 'Solidity Based Replacements' + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + contract = self.contract + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + + for variable in contract.state_variables_declared: + node = variable.node_initialization + if node: + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + line_no = node.source_mapping.lines + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOI.py new file mode 100644 index 000000000..6d5862e76 --- /dev/null +++ b/slither/tools/mutator/mutators/UOI.py @@ -0,0 +1,56 @@ +from typing import Dict +import re +from slither.core.expressions.unary_operation import UnaryOperationType +from slither.slithir.variables import Constant +from slither.core.variables.local_variable import LocalVariable +from slither.core.expressions.expression import Expression +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.cfg.node import NodeType + + +unary_operators = [ + UnaryOperationType.PLUSPLUS_PRE, + UnaryOperationType.MINUSMINUS_PRE, + UnaryOperationType.PLUSPLUS_POST, + UnaryOperationType.MINUSMINUS_POST, + UnaryOperationType.MINUS_PRE, +] + + +class UOI(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "UOI" + HELP = "Unary operator insertion" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + + result: Dict = {} + + contract = self.contract + + # Retrieve the file + in_file = contract.source_mapping.filename.absolute + # Retrieve the source code + in_file_str = contract.compilation_unit.core.source_code[in_file] + + for function in contract.functions_and_modifiers_declared: + for node in function.nodes: + if (node.type == NodeType.EXPRESSION): + for op in unary_operators: + if str(op) in str(node.expression): + for i in node.variables_written: + print(i) + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = in_file_str[start:stop] + # print(old_str) + # Replace the expression with true + # new_str = old_str.replace(str(operand), f"{str(op)}{operand}") + # new_str = re.sub(r'(\w+)\+\+', r'++\1', text) + # print(new_str) + # create_patch(result, in_file, start, stop, old_str, new_str) + print(result) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index a79f45906..e58b705a1 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,12 +1,12 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple +from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff - +from slither.tools.mutator.utils.testing_generated_mutant import test_patch logger = logging.getLogger("Slither-Mutate") @@ -34,6 +34,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- HELP = "" FAULTCLASS = FaultClass.Undefined FAULTNATURE = FaultNature.Undefined + VALID_MUTANTS_COUNT = 0 + INVALID_MUTANTS_COUNT = 0 def __init__( self, compilation_unit: SlitherCompilationUnit, rate: int = 10, seed: Optional[int] = None @@ -73,13 +75,18 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[(int, int)]: + def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[int, int]: + # identify the main contract, ignore the imports + for contract in self.slither.contracts: + if contract_name == str(contract.name): + self.contract = contract + # call _mutate function from different mutators - (all_patches, valid_mutant_count, invalid_mutant_count) = self._mutate(testing_command, testing_directory, contract_name) - + (all_patches) = self._mutate() + if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") - return + return (0,0) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -87,18 +94,27 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- offset = 0 patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): - logger.info(f"Impossible to generate patch; patches collisions: {patches}") - continue + # if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): + # logger.error(f"Impossible to generate patch; patches collisions: {patches}") + # continue for patch in patches: - patched_txt, offset = apply_patch(patched_txt, patch, offset) - diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) - if not diff: - logger.info(f"Impossible to generate patch; empty {patches}") + # print(patch) + # test the patch + flag = test_patch(file, patch, testing_command, self.VALID_MUTANTS_COUNT, self.NAME) + # count the valid and invalid mutants + if not flag: + self.INVALID_MUTANTS_COUNT += 1 + continue + self.VALID_MUTANTS_COUNT += 1 + # patched_txt, offset = apply_patch(patched_txt, patch, offset) + # diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + # if not diff: + # logger.info(f"Impossible to generate patch; empty {patches}") + # print the differences - print(diff) + # print(diff) - return (valid_mutant_count, invalid_mutant_count) + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 5a9465c86..4b0c3b1ad 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,4 +1,9 @@ # pylint: disable=unused-import # from slither.tools.mutator.mutators.MVIV import MVIV # from slither.tools.mutator.mutators.MVIE import MVIE -from slither.tools.mutator.mutators.MIA import MIA +# from slither.tools.mutator.mutators.MIA import MIA +from slither.tools.mutator.mutators.ROR import ROR +# from slither.tools.mutator.mutators.LOR import LOR +# from slither.tools.mutator.mutators.UOI import UOI +# from slither.tools.mutator.mutators.SBR import SBR + diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index c041f76d6..70f7deb11 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -4,9 +4,10 @@ import logging logger = logging.getLogger("Slither-Mutate") +duplicated_files = {} + # function to backup the source file def backup_source_file(source_code: Dict, output_folder: str) -> Dict: - duplicated_files = {} os.makedirs(output_folder, exist_ok=True) for file_path, content in source_code.items(): @@ -23,7 +24,8 @@ def backup_source_file(source_code: Dict, output_folder: str) -> Dict: # function to transfer the original content to the sol file after campaign def transfer_and_delete(files_dict: Dict) -> None: try: - for item, value in files_dict.items(): + files_dict_copy = files_dict.copy() + for item, value in files_dict_copy.items(): with open(value, 'r') as duplicated_file: content = duplicated_file.read() @@ -31,6 +33,10 @@ def transfer_and_delete(files_dict: Dict) -> None: original_file.write(content) os.remove(value) + + # delete elements from the global dict + del duplicated_files[item] + except Exception as e: logger.error(f"Error transferring content: {e}") @@ -45,14 +51,36 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # Write content to the original file mutant_name = filename.split('.')[0] + # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: mutant_file.write(content) + # reset the file + with open(duplicated_files[file], 'r') as duplicated_file: + duplicate_content = duplicated_file.read() + + with open(file, 'w') as source_file: + source_file.write(duplicate_content) + except Exception as e: logger.error(f"Error creating mutant: {e}") +# function to reset the file +def reset_file(file: str) -> None: + try: + # directory, filename = os.path.split(file) + # reset the file + with open(duplicated_files[file], 'r') as duplicated_file: + duplicate_content = duplicated_file.read() + + with open(file, 'w') as source_file: + source_file.write(duplicate_content) + + except Exception as e: + logger.error(f"Error resetting file: {e}") + # function to get the contracts list def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: sol_file_list = [] diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py index 03ccadec7..6c0ba6511 100644 --- a/slither/tools/mutator/utils/generic_patching.py +++ b/slither/tools/mutator/utils/generic_patching.py @@ -8,7 +8,7 @@ from slither.tools.mutator.utils.testing_generated_mutant import compile_generat from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file from slither.tools.mutator.utils.file_handling import create_mutant_file -def remove_assignement(variable: Variable, contract: Contract, result: Dict, test_cmd: str, test_dir: str) -> bool: +def remove_assignement(variable: Variable, contract: Contract, result: Dict) -> bool: """ Remove the variable's initial assignement @@ -28,19 +28,13 @@ def remove_assignement(variable: Variable, contract: Contract, result: Dict, tes old_str = in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - - replace_string_in_source_file(in_file, in_file_str[variable.source_mapping.start + old_str.find("="):variable.source_mapping.end], '') - - # compile and run tests before the mutant generated before patching - if compile_generated_mutant(in_file): - if run_test_suite(test_cmd, test_dir): - # create_mutant_file(in_file, ) - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - ) - return True \ No newline at end of file + line_no = [0] + create_patch( + result, + in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 61b9db214..7ab406519 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -2,8 +2,13 @@ import crytic_compile import subprocess import os import logging - +import time +import signal +from typing import List, Dict +from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file +from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") +timeout = 30 # we can get it as parameter # function to compile the generated mutant def compile_generated_mutant(file_path: str) -> bool: @@ -11,7 +16,9 @@ def compile_generated_mutant(file_path: str) -> bool: crytic_compile.CryticCompile(file_path) return True except Exception as e: # pylint: disable=broad-except - logger.error("Error Crytic Compile", e) + print(True) + # logger.error("Error Crytic Compile") + return False # function to run the tests def run_test_suite(cmd: str, dir: str) -> bool: @@ -21,14 +28,55 @@ def run_test_suite(cmd: str, dir: str) -> bool: result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # result = subprocess.run(cmd.split(' '), check=True) - print(result.stdout) if not result.stderr: return True except subprocess.CalledProcessError as e: - print(e.output) logger.error(f"Error executing '{cmd}': {e}") return False except Exception as e: logger.error(f"An unexpected error occurred: {e}") - return False \ No newline at end of file + return False + +def run_test_cmd(cmd: str, dir: str) -> bool: + start = time.time() + + # starting new process + P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) + + try: + # checking whether the process is completed or not for 30 seconds + while P.poll() is None and (time.time() - start) < timeout: + time.sleep(0.05) + finally: + if P.poll() is None: + print() + print("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + # sends a SIGTERM signal to process group - bascially killing the process + os.killpg(os.getpgid(P.pid), signal.SIGTERM) + # Avoid any weird race conditions from grabbing the return code + time.sleep(0.05) + # indicates whether the command executed sucessfully or not + r = P.returncode + + # if r is 0 then it is valid mutant because tests didn't fail + return True if r == 0 else False + +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str) -> bool: + with open(file, 'r') as filepath: + content = filepath.read() + # Perform the replacement based on the index values + replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] + + # Write the modified content back to the file + with open(file, 'w') as filepath: + filepath.write(replaced_content) + if(compile_generated_mutant(file)): + if(run_test_cmd(command, file)): + create_mutant_file(file, index, generator_name) + logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) + return True + + reset_file(file) + logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> INVALID\n")) + return False \ No newline at end of file From 67b95dff7440c807e168c4796c37948810d0d77a Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 9 Jan 2024 12:03:22 -0500 Subject: [PATCH 306/338] Added new mutators --- slither/tools/mutator/__main__.py | 33 ++++++---- slither/tools/mutator/mutators/AOR.py | 38 ++++++++++++ slither/tools/mutator/mutators/ASOR.py | 50 +++++++++++++++ slither/tools/mutator/mutators/BOR.py | 35 +++++++++++ slither/tools/mutator/mutators/LOR.py | 14 +---- slither/tools/mutator/mutators/MIA.py | 20 +++--- slither/tools/mutator/mutators/MVIE.py | 45 +++++++++++--- slither/tools/mutator/mutators/MVIV.py | 45 +++++++++++--- slither/tools/mutator/mutators/MWA.py | 34 +++++++++++ slither/tools/mutator/mutators/ROR.py | 20 ++---- slither/tools/mutator/mutators/SBR.py | 22 +++---- slither/tools/mutator/mutators/UOI.py | 61 +++++++++---------- .../mutator/mutators/abstract_mutator.py | 25 +++++--- .../tools/mutator/mutators/all_mutators.py | 16 +++-- .../tools/mutator/utils/generic_patching.py | 40 ------------ .../tools/mutator/utils/replace_conditions.py | 48 --------------- .../mutator/utils/testing_generated_mutant.py | 13 ++-- 17 files changed, 339 insertions(+), 220 deletions(-) create mode 100644 slither/tools/mutator/mutators/AOR.py create mode 100644 slither/tools/mutator/mutators/ASOR.py create mode 100644 slither/tools/mutator/mutators/BOR.py create mode 100644 slither/tools/mutator/mutators/MWA.py delete mode 100644 slither/tools/mutator/utils/generic_patching.py delete mode 100644 slither/tools/mutator/utils/replace_conditions.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 201b39acd..aba427355 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -59,11 +59,18 @@ def parse_args() -> argparse.Namespace: help="Directories to ignore" ) - # to_do: add time out argument + # time out argument parser.add_argument( "--timeout", - help="Set timeout for test command" + help="Set timeout for test command (by deafult 30 seconds)" ) + + # output directory argument + parser.add_argument( + "--output-dir", + help="Output Directory (by default it is 'mutation_campaign')" + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -98,13 +105,13 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() - # print(os.path.isdir(args.codebase)) # provided file/folder # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir paths_to_ignore: str | None = args.ignore_dirs - timeout: int = args.timeout + output_dir: str | None = args.output_dir + timeout: int | None = args.timeout print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -118,33 +125,33 @@ def main() -> None: sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) # folder where backup files and valid mutants created - output_folder = os.getcwd() + "/mutation_campaign" + if output_dir == None: + output_dir = "/mutation_campaign" + output_folder = os.getcwd() + output_dir if os.path.exists(output_folder): shutil.rmtree(output_folder) + # set default timeout + if timeout == None: + timeout = 30 + for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) - # total count of mutants total_count = 0 - # count of valid mutants v_count = 0 # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - # compilation_unit_of_main_file = sl.compilation_units[-1] - # for i in compilation_unit_of_main_file.contracts: - # print(i.name) for M in _get_mutators(): - m = M(compilation_unit_of_main_file) - count_valid, count_invalid = m.mutate(test_command, test_directory, contract_name) + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name) + count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid except Exception as e: diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py new file mode 100644 index 000000000..f248d3c77 --- /dev/null +++ b/slither/tools/mutator/mutators/AOR.py @@ -0,0 +1,38 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +arithmetic_operators = [ + BinaryType.ADDITION, + BinaryType.DIVISION, + BinaryType.MULTIPLICATION, + BinaryType.SUBTRACTION, + BinaryType.MODULO +] + +class AOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "AOR" + HELP = "Arithmetic operator replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in arithmetic_operators: + alternative_ops = arithmetic_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py new file mode 100644 index 000000000..8c70756a2 --- /dev/null +++ b/slither/tools/mutator/mutators/ASOR.py @@ -0,0 +1,50 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation + +assignment_operators = [ + AssignmentOperationType.ASSIGN_ADDITION, + AssignmentOperationType.ASSIGN_SUBTRACTION, + AssignmentOperationType.ASSIGN, + AssignmentOperationType.ASSIGN_OR, + AssignmentOperationType.ASSIGN_CARET, + AssignmentOperationType.ASSIGN_AND, + AssignmentOperationType.ASSIGN_LEFT_SHIFT, + AssignmentOperationType.ASSIGN_RIGHT_SHIFT, + AssignmentOperationType.ASSIGN_MULTIPLICATION, + AssignmentOperationType.ASSIGN_DIVISION, + AssignmentOperationType.ASSIGN_MODULO +] + +class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "ASOR" + HELP = "Assignment Operator Replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: + if ir.expression.type == AssignmentOperationType.ASSIGN: + continue + alternative_ops = assignment_operators[:] + try: + alternative_ops.remove(ir.expression.type) + except: + continue + for op in assignment_operators: + if op != ir.expression: + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py new file mode 100644 index 000000000..7878a20ea --- /dev/null +++ b/slither/tools/mutator/mutators/BOR.py @@ -0,0 +1,35 @@ +from typing import Dict +from slither.slithir.operations import Binary, BinaryType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass + +bitwise_operators = [ + BinaryType.AND, + BinaryType.OR +] + +class BOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "BOR" + HELP = "Bitwise Operator Replacement" + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + for ir in node.irs: + if isinstance(ir, Binary) and ir.type in bitwise_operators: + alternative_ops = bitwise_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index 382a08aee..b00b13000 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -15,17 +15,9 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - contract = self.contract - - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - for function in contract.functions_and_modifiers_declared: - + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -37,11 +29,11 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index d76369d4d..1cc0fdb6d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -2,6 +2,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" @@ -10,32 +11,31 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - # Retrieve the file - in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = self.contract.compilation_unit.core.source_code[in_file] - for function in self.contract.functions_declared + list(self.contract.modifiers_declared): + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IF: - # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + # print(node.expression) + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - +# limitations - won't work if it is tenary operation \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 15b2a20c3..13a4e6d1a 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,9 +1,8 @@ from typing import Dict - from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.generic_patching import remove_assignement +from slither.formatters.utils.patches import create_patch class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" @@ -12,24 +11,52 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - contract = self.contract # Create fault for state variables declaration - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: continue if not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) - - for function in contract.functions_declared + list(contract.modifiers_declared): + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) + + for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and not isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 5e7c0a6e1..e705ff94a 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,9 +1,9 @@ -from typing import Dict, Tuple +from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.tools.mutator.utils.generic_patching import remove_assignement +from slither.formatters.utils.patches import create_patch class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" @@ -12,24 +12,51 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - contract = self.contract - + # Create fault for state variables declaration - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: continue if isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + # Get the string + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] - for function in contract.functions_declared + list(contract.modifiers_declared): + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) + + for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): - remove_assignement(variable, contract, result) + start = variable.source_mapping.start + stop = variable.expression.source_mapping.start + old_str = self.in_file_str[start:stop] + + new_str = old_str[: old_str.find("=")] + line_no = [0] + create_patch( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no + ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py new file mode 100644 index 000000000..1e2067425 --- /dev/null +++ b/slither/tools/mutator/mutators/MWA.py @@ -0,0 +1,34 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + +class MWA(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "MIA" + HELP = '"while" construct around statement' + FAULTCLASS = FaultClass.Checking + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type == NodeType.IFLOOP: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + + + +# limitations - won't work if it is tenary operation + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 9a8942e19..6a2ef6426 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,5 +1,4 @@ from typing import Dict -from collections import defaultdict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass @@ -22,19 +21,11 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - # result["patches"] = defaultdict(list) - contract = self.contract - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: - # Retrieve the file - in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = self.contract.compilation_unit.core.source_code[in_file] - if isinstance(ir, Binary) and ir.type in relational_operators: alternative_ops = relational_operators[:] alternative_ops.remove(ir.type) @@ -43,11 +34,12 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + +# failing in case of condition1 || condition2 \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index ac35d9540..6797c0c35 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -3,6 +3,7 @@ from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass import re +from slither.core.variables.variable import Variable solidity_rules = [ "abi\.encode\( ==> abi.encodePacked(", @@ -38,7 +39,8 @@ solidity_rules = [ "(u?)int32 ==> \\1int16", "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", - "(u?)int256 ==> \\1int128" + "(u?)int256 ==> \\1int128" + "while ==> if", ] @@ -51,40 +53,36 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - contract = self.contract - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] + variable: Variable - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type != NodeType.ENTRYPOINT: # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - for variable in contract.state_variables_declared: + for variable in self.contract.state_variables_declared: node = variable.node_initialization if node: start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, in_file, start, stop, old_str, new_str, line_no[0]) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOI.py index 6d5862e76..60e8c22c3 100644 --- a/slither/tools/mutator/mutators/UOI.py +++ b/slither/tools/mutator/mutators/UOI.py @@ -1,23 +1,19 @@ from typing import Dict -import re -from slither.core.expressions.unary_operation import UnaryOperationType +from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation +from slither.core.expressions.expression import Expression from slither.slithir.variables import Constant from slither.core.variables.local_variable import LocalVariable -from slither.core.expressions.expression import Expression from slither.formatters.utils.patches import create_patch from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass -from slither.core.cfg.node import NodeType - unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST, - UnaryOperationType.MINUS_PRE, + UnaryOperationType.MINUS_PRE ] - class UOI(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOI" HELP = "Unary operator insertion" @@ -25,32 +21,35 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: - result: Dict = {} - contract = self.contract - - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - for function in contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if (node.type == NodeType.EXPRESSION): + try: + ir_expression = node.expression + except Exception as e: + continue + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: for op in unary_operators: - if str(op) in str(node.expression): - for i in node.variables_written: - print(i) - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = in_file_str[start:stop] - # print(old_str) - # Replace the expression with true - # new_str = old_str.replace(str(operand), f"{str(op)}{operand}") - # new_str = re.sub(r'(\w+)\+\+', r'++\1', text) - # print(new_str) - # create_patch(result, in_file, start, stop, old_str, new_str) - print(result) + if not node.expression.is_prefix: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(variable_read) + str(op) + if new_str != old_str: + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(op) + str(variable_read) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + else: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(op) + str(variable_read) + if new_str != old_str: + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(variable_read) + str(op) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index e58b705a1..ead78ac97 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -38,12 +38,15 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- INVALID_MUTANTS_COUNT = 0 def __init__( - self, compilation_unit: SlitherCompilationUnit, rate: int = 10, seed: Optional[int] = None + self, compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, contract_name: str, rate: int = 10, seed: Optional[int] = None ): self.compilation_unit = compilation_unit self.slither = compilation_unit.core self.seed = seed self.rate = rate + self.test_command = testing_command + self.test_directory = testing_directory + self.timeout = timeout if not self.NAME: raise IncorrectMutatorInitialization( @@ -69,18 +72,23 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) + + # identify the main contract, ignore the imports + for contract in self.slither.contracts: + if contract_name == str(contract.name): # limitation: what if the contract name is not same as file name + # contract + self.contract = contract + # Retrieve the file + self.in_file = self.contract.source_mapping.filename.absolute + # Retrieve the source code + self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] @abc.abstractmethod def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" return {} - def mutate(self, testing_command: str, testing_directory: str, contract_name: str) -> Tuple[int, int]: - # identify the main contract, ignore the imports - for contract in self.slither.contracts: - if contract_name == str(contract.name): - self.contract = contract - + def mutate(self) -> Tuple[int, int]: # call _mutate function from different mutators (all_patches) = self._mutate() @@ -98,9 +106,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # logger.error(f"Impossible to generate patch; patches collisions: {patches}") # continue for patch in patches: - # print(patch) # test the patch - flag = test_patch(file, patch, testing_command, self.VALID_MUTANTS_COUNT, self.NAME) + flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 4b0c3b1ad..3f4e59043 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,9 +1,13 @@ # pylint: disable=unused-import -# from slither.tools.mutator.mutators.MVIV import MVIV -# from slither.tools.mutator.mutators.MVIE import MVIE -# from slither.tools.mutator.mutators.MIA import MIA +from slither.tools.mutator.mutators.MVIV import MVIV +from slither.tools.mutator.mutators.MVIE import MVIE +from slither.tools.mutator.mutators.MIA import MIA from slither.tools.mutator.mutators.ROR import ROR -# from slither.tools.mutator.mutators.LOR import LOR -# from slither.tools.mutator.mutators.UOI import UOI -# from slither.tools.mutator.mutators.SBR import SBR +from slither.tools.mutator.mutators.LOR import LOR +from slither.tools.mutator.mutators.UOI import UOI +from slither.tools.mutator.mutators.SBR import SBR +from slither.tools.mutator.mutators.AOR import AOR +from slither.tools.mutator.mutators.BOR import BOR +from slither.tools.mutator.mutators.ASOR import ASOR +from slither.tools.mutator.mutators.MWA import MWA diff --git a/slither/tools/mutator/utils/generic_patching.py b/slither/tools/mutator/utils/generic_patching.py deleted file mode 100644 index 6c0ba6511..000000000 --- a/slither/tools/mutator/utils/generic_patching.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Dict -import os - -from slither.core.declarations import Contract -from slither.core.variables.variable import Variable -from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.utils.testing_generated_mutant import compile_generated_mutant, run_test_suite -from slither.tools.mutator.utils.replace_conditions import replace_string_in_source_file -from slither.tools.mutator.utils.file_handling import create_mutant_file - -def remove_assignement(variable: Variable, contract: Contract, result: Dict) -> bool: - """ - Remove the variable's initial assignement - - :param variable: - :param contract: - :param result: - :return: - """ - # Retrieve the file - in_file = contract.source_mapping.filename.absolute - # Retrieve the source code - in_file_str = contract.compilation_unit.core.source_code[in_file] - - # Get the string - start = variable.source_mapping.start - stop = variable.expression.source_mapping.start - old_str = in_file_str[start:stop] - - new_str = old_str[: old_str.find("=")] - line_no = [0] - create_patch( - result, - in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no - ) \ No newline at end of file diff --git a/slither/tools/mutator/utils/replace_conditions.py b/slither/tools/mutator/utils/replace_conditions.py deleted file mode 100644 index 4e3f91454..000000000 --- a/slither/tools/mutator/utils/replace_conditions.py +++ /dev/null @@ -1,48 +0,0 @@ -import logging -import re - -logger = logging.getLogger("Slither-Mutate") - -# function to replace the string -def replace_string_in_source_file(file_path: str, old_string: str, new_string: str) -> None: - try: - # Read the content of the Solidity file - with open(file_path, 'r') as file: - content = file.read() - - # Perform the string replacement - modified_content = content.replace(old_string, new_string) - - # Write the modified content back to the file - with open(file_path, 'w') as file: - file.write(modified_content) - - logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.") - except Exception as e: - logger.error(f"Error replacing string: {e}") - -# function to replace the string in a specific line -def replace_string_in_source_file_specific_line(file_path: str, old_string: str, new_string: str, line_number : int) -> None: - try: - # Read the content of the Solidity file - with open(file_path, 'r') as file: - lines = file.readlines() - - if 1 <= line_number <= len(lines): - # remove the spaces in the string - line = lines[line_number - 1].replace(" ", "") - old_string = old_string.replace(" ", "") - - # Replace the old string with the new string on the specified line - lines[line_number - 1] = line.replace(old_string.strip(), new_string) - - # Write the modified content back to the file - with open(file_path, 'w') as file: - file.writelines(lines) - - logger.info(f"String '{old_string}' replaced with '{new_string}' in '{file_path}'.' at '{line_number}") - else: - logger.error(f'Error: Line number {line_number} is out of range') - - except Exception as e: - logger.erro(f'Error: {e}') \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 7ab406519..61a688f7c 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -38,14 +38,12 @@ def run_test_suite(cmd: str, dir: str) -> bool: logger.error(f"An unexpected error occurred: {e}") return False -def run_test_cmd(cmd: str, dir: str) -> bool: +def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: start = time.time() - # starting new process P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) - try: - # checking whether the process is completed or not for 30 seconds + # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: time.sleep(0.05) finally: @@ -58,21 +56,20 @@ def run_test_cmd(cmd: str, dir: str) -> bool: time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode - + # if r is 0 then it is valid mutant because tests didn't fail return True if r == 0 else False -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str) -> bool: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int) -> bool: with open(file, 'r') as filepath: content = filepath.read() # Perform the replacement based on the index values replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] - # Write the modified content back to the file with open(file, 'w') as filepath: filepath.write(replaced_content) if(compile_generated_mutant(file)): - if(run_test_cmd(command, file)): + if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) return True From df42cb66d18af3132c326b26759ce670144ad7e2 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sun, 14 Jan 2024 19:19:58 -0500 Subject: [PATCH 307/338] Updated mutators --- slither/tools/mutator/__main__.py | 48 +++++++---- slither/tools/mutator/mutators/AOR.py | 10 ++- slither/tools/mutator/mutators/ASOR.py | 6 +- slither/tools/mutator/mutators/BOR.py | 8 +- slither/tools/mutator/mutators/FHR.py | 36 ++++++++ slither/tools/mutator/mutators/LIR.py | 82 ++++++++++++++++++ slither/tools/mutator/mutators/LOR.py | 7 +- slither/tools/mutator/mutators/MIA.py | 18 ++-- slither/tools/mutator/mutators/MVIE.py | 11 ++- slither/tools/mutator/mutators/MVIV.py | 13 ++- slither/tools/mutator/mutators/MWA.py | 13 +-- slither/tools/mutator/mutators/RCR.py | 36 ++++++++ slither/tools/mutator/mutators/ROR.py | 34 ++++---- slither/tools/mutator/mutators/SBR.py | 9 +- .../tools/mutator/mutators/{UOI.py => UOR.py} | 18 ++-- .../mutator/mutators/abstract_mutator.py | 86 +++++++++++-------- .../tools/mutator/mutators/all_mutators.py | 26 +++--- slither/tools/mutator/utils/command_line.py | 11 ++- slither/tools/mutator/utils/file_handling.py | 4 +- .../mutator/utils/testing_generated_mutant.py | 58 +++++++------ 20 files changed, 351 insertions(+), 183 deletions(-) create mode 100644 slither/tools/mutator/mutators/FHR.py create mode 100644 slither/tools/mutator/mutators/LIR.py create mode 100644 slither/tools/mutator/mutators/RCR.py rename slither/tools/mutator/mutators/{UOI.py => UOR.py} (80%) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index aba427355..c41a82e35 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,12 +2,10 @@ import argparse import inspect import logging import sys -from typing import Type, List, Any, Dict, Tuple import os import shutil - +from typing import Type, List, Any from crytic_compile import cryticparser - from slither import Slither from slither.tools.mutator.mutators import all_mutators from .mutators.abstract_mutator import AbstractMutator @@ -62,13 +60,27 @@ def parse_args() -> argparse.Namespace: # time out argument parser.add_argument( "--timeout", - help="Set timeout for test command (by deafult 30 seconds)" + help="Set timeout for test command (by default 30 seconds)" ) # output directory argument parser.add_argument( "--output-dir", - help="Output Directory (by default it is 'mutation_campaign')" + help="Output Directory (by default 'mutation_campaign')" + ) + + # to print just all the mutants + parser.add_argument( + "--verbose", + help="output all mutants generated", + action="store_true", + default=False, + ) + + # select list of mutators to run + parser.add_argument( + "--mutators-to-run", + help="mutant generators to run", ) # Initiate all the crytic config cli options @@ -80,13 +92,14 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() - -def _get_mutators() -> List[Type[AbstractMutator]]: +def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator)] + if not mutators_list is None: + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] + else: + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] return detectors - class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any @@ -105,13 +118,15 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() - # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir paths_to_ignore: str | None = args.ignore_dirs output_dir: str | None = args.output_dir timeout: int | None = args.timeout + solc_remappings: str | None = args.solc_remaps + verbose: bool = args.verbose + mutators_to_run: List[str] | None = args.mutators_to_run print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -137,6 +152,7 @@ def main() -> None: for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] + # TODO: user provides contract name # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -149,11 +165,13 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - for M in _get_mutators(): - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name) - count_valid, count_invalid = m.mutate() - v_count += count_valid - total_count += count_valid + count_invalid + for M in _get_mutators(mutators_to_run): + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) + # check whether the contract instance exists or not + if m.get_exist_flag(): + count_valid, count_invalid = m.mutate() + v_count += count_valid + total_count += count_valid + count_invalid except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index f248d3c77..39e3a6a20 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,7 +1,8 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.core.expressions.unary_operation import UnaryOperation arithmetic_operators = [ BinaryType.ADDITION, @@ -14,7 +15,6 @@ arithmetic_operators = [ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -22,8 +22,14 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: + try: + ir_expression = node.expression + except: + continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: + if isinstance(ir_expression, UnaryOperation): + continue alternative_ops = arithmetic_operators[:] alternative_ops.remove(ir.type) for op in alternative_ops: diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 8c70756a2..04ad8f8b0 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,7 +1,6 @@ from typing import Dict -from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation assignment_operators = [ @@ -21,7 +20,6 @@ assignment_operators = [ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -38,7 +36,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops.remove(ir.expression.type) except: continue - for op in assignment_operators: + for op in alternative_ops: if op != ir.expression: start = node.source_mapping.start stop = start + node.source_mapping.length diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 7878a20ea..de9ad287e 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,17 +1,19 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature bitwise_operators = [ BinaryType.AND, - BinaryType.OR + BinaryType.OR, + BinaryType.LEFT_SHIFT, + BinaryType.RIGHT_SHIFT, + BinaryType.CARET ] class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py new file mode 100644 index 000000000..5709346b1 --- /dev/null +++ b/slither/tools/mutator/mutators/FHR.py @@ -0,0 +1,36 @@ +from typing import Dict +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +import re + +# INFO: low severity + +function_header_replacements = [ + "pure ==> view", + "view ==> pure", + "(\s)(external|public|internal) ==> \\1private", + "(\s)(external|public) ==> \\1internal" +] + +class FHR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "FHR" + HELP = 'Function Header Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + # function_header = function.source_mapping.content.split('{')[0] + start = function.source_mapping.start + stop = start + function.source_mapping.content.find('{') + old_str = self.in_file_str[start:stop] + line_no = function.source_mapping.lines + for value in function_header_replacements: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py new file mode 100644 index 000000000..99228913a --- /dev/null +++ b/slither/tools/mutator/mutators/LIR.py @@ -0,0 +1,82 @@ +from typing import Dict +from slither.core.expressions import Literal +from slither.core.variables.variable import Variable +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.formatters.utils.patches import create_patch +from slither.core.solidity_types import ElementaryType + +literal_replacements = [] + +class LIR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "LIR" + HELP = "Literal Interger Replacement" + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + variable: Variable + + # Create fault for state variables declaration + for variable in self.contract.state_variables_declared: + if variable.initialized: + # Cannot remove the initialization of constant variables + if variable.is_constant: + continue + + if isinstance(variable.expression, Literal): + if isinstance(variable.type, ElementaryType): + literal_replacements.append(variable.type.min) # append data type min value + literal_replacements.append(variable.type.max) # append data type max value + if str(variable.type).startswith("uint"): + literal_replacements.append('1') + elif str(variable.type).startswith("uint"): + literal_replacements.append('-1') + # Get the string + start = variable.source_mapping.start + stop = start + variable.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = variable.node_initialization.source_mapping.lines + # line_no = [0] + for value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != value: + new_str = f"{old_str.split('=')[0]}= {value}" + create_patch( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) + + for function in self.contract.functions_and_modifiers_declared: + for variable in function.local_variables: + if variable.initialized and isinstance(variable.expression, Literal): + if isinstance(variable.type, ElementaryType): + literal_replacements.append(variable.type.min) + literal_replacements.append(variable.type.max) + if str(variable.type).startswith("uint"): + literal_replacements.append('1') + elif str(variable.type).startswith("uint"): + literal_replacements.append('-1') + start = variable.source_mapping.start + stop = start + variable.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = variable.source_mapping.lines + for new_value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != new_value: + new_str = f"{old_str.split('=')[0]}= {new_value}" + create_patch( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) + + return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index b00b13000..fa66c7bca 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature logical_operators = [ BinaryType.OROR, @@ -10,8 +10,7 @@ logical_operators = [ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" - HELP = "Logical operator replacement" - FAULTCLASS = FaultClass.Checking + HELP = "Logical Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -25,14 +24,12 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops.remove(ir.type) for op in alternative_ops: - # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines # Replace the expression with true - # new_str = f"{ir.variable_left} {op.value} {ir.variable_right}" new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 1cc0fdb6d..f5bc52b16 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -17,8 +16,8 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: if node.type == NodeType.IF: # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length + start = node.expression.source_mapping.start + stop = start + node.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines @@ -27,15 +26,10 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods new_str = value create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - # print(node.expression) if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result - - -# limitations - won't work if it is tenary operation - - \ No newline at end of file + print(node.expression) + + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 13a4e6d1a..3c334e9e6 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.formatters.utils.patches import create_patch class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" - FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -28,7 +27,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.node_initialization.source_mapping.lines create_patch( result, self.in_file, @@ -36,7 +35,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) for function in self.contract.functions_and_modifiers_declared: @@ -48,7 +47,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.source_mapping.lines create_patch( result, self.in_file, @@ -56,7 +55,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index e705ff94a..7f75b1dcf 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -2,13 +2,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.formatters.utils.patches import create_patch class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" - FAULTCLASS = FaultClass.Assignement FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,9 +26,8 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.node_initialization.source_mapping.lines create_patch( result, self.in_file, @@ -37,7 +35,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) for function in self.contract.functions_and_modifiers_declared: @@ -46,9 +44,8 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] - line_no = [0] + line_no = variable.source_mapping.lines create_patch( result, self.in_file, @@ -56,7 +53,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no + line_no[0] ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 1e2067425..c6bacf485 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MWA(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "MIA" + NAME = "MWA" HELP = '"while" construct around statement' - FAULTCLASS = FaultClass.Checking FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -25,10 +24,4 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result - - - -# limitations - won't work if it is tenary operation - - \ No newline at end of file + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/RCR.py b/slither/tools/mutator/mutators/RCR.py new file mode 100644 index 000000000..96aebc68f --- /dev/null +++ b/slither/tools/mutator/mutators/RCR.py @@ -0,0 +1,36 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature + + +class RCR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "RCR" + HELP = 'Revert and Comment Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + if old_str != 'revert()': + new_str = 'revert()' + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + new_str = "//" + old_str + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 6a2ef6426..e1c78c1eb 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,8 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass - +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature relational_operators = [ BinaryType.LESS, @@ -13,11 +12,9 @@ relational_operators = [ BinaryType.NOT_EQUAL, ] - class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" - HELP = "Relational operator replacement" - FAULTCLASS = FaultClass.Checking + HELP = "Relational Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,19 +24,18 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: - alternative_ops = relational_operators[:] - alternative_ops.remove(ir.type) - - for op in alternative_ops: - # Get the string - start = node.source_mapping.start - stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] - line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if str(ir.variable_left.type) != 'address' and str(ir.variable_right) != 'address': + alternative_ops = relational_operators[:] + alternative_ops.remove(ir.type) + for op in alternative_ops: + # Get the string + start = ir.expression.source_mapping.start + stop = start + ir.expression.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + + create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result -# failing in case of condition1 || condition2 \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 6797c0c35..91c05b884 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re from slither.core.variables.variable import Variable @@ -39,15 +39,14 @@ solidity_rules = [ "(u?)int32 ==> \\1int16", "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", - "(u?)int256 ==> \\1int128" - "while ==> if", + "(u?)int256 ==> \\1int128", + "while ==> if", ] class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" - HELP = 'Solidity Based Replacements' - FAULTCLASS = FaultClass.Checking + HELP = 'Solidity Based Replacement' FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/UOI.py b/slither/tools/mutator/mutators/UOR.py similarity index 80% rename from slither/tools/mutator/mutators/UOI.py rename to slither/tools/mutator/mutators/UOR.py index 60e8c22c3..671ee676d 100644 --- a/slither/tools/mutator/mutators/UOI.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,10 +1,7 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation -from slither.core.expressions.expression import Expression -from slither.slithir.variables import Constant -from slither.core.variables.local_variable import LocalVariable from slither.formatters.utils.patches import create_patch -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature, FaultClass +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, @@ -14,10 +11,9 @@ unary_operators = [ UnaryOperationType.MINUS_PRE ] -class UOI(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "UOI" - HELP = "Unary operator insertion" - FAULTCLASS = FaultClass.Checking +class UOR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "UOR" + HELP = "Unary Operator Replacement" FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -27,7 +23,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods for node in function.nodes: try: ir_expression = node.expression - except Exception as e: + except: continue start = node.source_mapping.start stop = start + node.source_mapping.length @@ -39,7 +35,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) - if new_str != old_str: + if new_str != old_str and str(op) != '-': create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(op) + str(variable_read) create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) @@ -47,7 +43,7 @@ class UOI(AbstractMutator): # pylint: disable=too-few-public-methods if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) - if new_str != old_str: + if new_str != old_str and str(op) != '-': create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ead78ac97..5223e2d81 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,45 +1,48 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple, List - +from typing import Optional, Dict, Tuple from slither.core.compilation_unit import SlitherCompilationUnit -from slither.tools.doctor.utils import snip_section +# from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch -logger = logging.getLogger("Slither-Mutate") +from slither.utils.colors import yellow +logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - -class FaultClass(Enum): - Assignement = 0 - Checking = 1 - Interface = 2 - Algorithm = 3 - Undefined = 100 - - class FaultNature(Enum): Missing = 0 Wrong = 1 Extraneous = 2 Undefined = 100 - + # not executed - can be detected by replacing with revert + # has no effect - can be detected by removing a line / comment + # can have valid mutant + # can't have valid mutant + class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" - FAULTCLASS = FaultClass.Undefined FAULTNATURE = FaultNature.Undefined VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 def __init__( - self, compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, contract_name: str, rate: int = 10, seed: Optional[int] = None - ): + self, compilation_unit: SlitherCompilationUnit, + timeout: int, + testing_command: str, + testing_directory: str, + contract_name: str, + solc_remappings: str | None, + verbose: bool, + output_folder: str, + rate: int = 10, + seed: Optional[int] = None + ) -> None: self.compilation_unit = compilation_unit self.slither = compilation_unit.core self.seed = seed @@ -47,6 +50,10 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.test_command = testing_command self.test_directory = testing_directory self.timeout = timeout + self.contract_exist = False + self.solc_remappings = solc_remappings + self.verbose = verbose + self.output_folder = output_folder if not self.NAME: raise IncorrectMutatorInitialization( @@ -58,11 +65,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- f"HELP is not initialized {self.__class__.__name__}" ) - if self.FAULTCLASS == FaultClass.Undefined: - raise IncorrectMutatorInitialization( - f"FAULTCLASS is not initialized {self.__class__.__name__}" - ) - if self.FAULTNATURE == FaultNature.Undefined: raise IncorrectMutatorInitialization( f"FAULTNATURE is not initialized {self.__class__.__name__}" @@ -75,14 +77,25 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # identify the main contract, ignore the imports for contract in self.slither.contracts: - if contract_name == str(contract.name): # limitation: what if the contract name is not same as file name + # !limitation: what if the contract name is not same as file name + # !limitation: multi contract + if contract_name.lower() == str(contract.name).lower(): # contract self.contract = contract # Retrieve the file self.in_file = self.contract.source_mapping.filename.absolute # Retrieve the source code self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] - + # flag contract existence + self.contract_exist = True + + if not self.contract_exist: + self.contract_exist = False + logger.error(f"Contract name is not matching with the File name ({contract_name}). Please refer 'https://docs.soliditylang.org/en/latest/style-guide.html#contract-and-library-names')") + + def get_exist_flag(self) -> bool: + return self.contract_exist + @abc.abstractmethod def _mutate(self, test_cmd: str, test_dir: str) -> Dict: """TODO Documentation""" @@ -95,31 +108,28 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") return (0,0) - + for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") - patched_txt = original_txt - offset = 0 patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - # if not all(patches[i]["end"] <= patches[i + 1]["end"] for i in range(len(patches) - 1)): - # logger.error(f"Impossible to generate patch; patches collisions: {patches}") - # continue + print(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch - flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout) + flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 continue self.VALID_MUTANTS_COUNT += 1 - # patched_txt, offset = apply_patch(patched_txt, patch, offset) - # diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) - # if not diff: - # logger.info(f"Impossible to generate patch; empty {patches}") - - # print the differences - # print(diff) + patched_txt,_ = apply_patch(original_txt, patch, 0) + diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + if not diff: + logger.info(f"Impossible to generate patch; empty {patches}") + + # add valid mutant patches to a output file + with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: + patches_file.write(diff + '\n') return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 3f4e59043..9aa81a0fc 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,13 +1,17 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV -from slither.tools.mutator.mutators.MVIE import MVIE -from slither.tools.mutator.mutators.MIA import MIA -from slither.tools.mutator.mutators.ROR import ROR -from slither.tools.mutator.mutators.LOR import LOR -from slither.tools.mutator.mutators.UOI import UOI -from slither.tools.mutator.mutators.SBR import SBR -from slither.tools.mutator.mutators.AOR import AOR -from slither.tools.mutator.mutators.BOR import BOR -from slither.tools.mutator.mutators.ASOR import ASOR -from slither.tools.mutator.mutators.MWA import MWA +from slither.tools.mutator.mutators.MVIV import MVIV # severity low +from slither.tools.mutator.mutators.MVIE import MVIE # severity low +from slither.tools.mutator.mutators.LOR import LOR # severity medium +from slither.tools.mutator.mutators.UOR import UOR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.AOR import AOR # severity medium +from slither.tools.mutator.mutators.BOR import BOR # severity medium +from slither.tools.mutator.mutators.ASOR import ASOR # severity medium +from slither.tools.mutator.mutators.MWA import MWA # severity medium +from slither.tools.mutator.mutators.LIR import LIR # severity medium +from slither.tools.mutator.mutators.FHR import FHR # severity medium +from slither.tools.mutator.mutators.MIA import MIA # severity medium +from slither.tools.mutator.mutators.ROR import ROR # severity medium +from slither.tools.mutator.mutators.RCR import RCR # severity high + diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 80d610a69..042b4fff7 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -7,15 +7,14 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: for detector in mutators_classes: argument = detector.NAME help_info = detector.HELP - fault_class = detector.FAULTCLASS.name fault_nature = detector.FAULTNATURE.name - mutators_list.append((argument, help_info, fault_class, fault_nature)) - table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Class", "Fault Nature"]) + mutators_list.append((argument, help_info, fault_nature)) + table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Nature"]) # Sort by class, nature, name - mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[3], element[0])) + mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[0])) idx = 1 - for (argument, help_info, fault_class, fault_nature) in mutators_list: - table.add_row([str(idx), argument, help_info, fault_class, fault_nature]) + for (argument, help_info, fault_nature) in mutators_list: + table.add_row([str(idx), argument, help_info, fault_nature]) idx = idx + 1 print(table) diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 70f7deb11..d61bba58a 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -105,5 +105,5 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str sol_file_list.append(i) return sol_file_list -# to_do: create a function to delete the commands from the sol file -# def remove_comments(self) -> None: \ No newline at end of file + +# TODO: create a function to delete the commands from the sol file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 61a688f7c..6c6e80a55 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -7,38 +7,44 @@ import signal from typing import List, Dict from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red + logger = logging.getLogger("Slither-Mutate") -timeout = 30 # we can get it as parameter # function to compile the generated mutant -def compile_generated_mutant(file_path: str) -> bool: +def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: - crytic_compile.CryticCompile(file_path) + crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True - except Exception as e: # pylint: disable=broad-except - print(True) + except: # pylint: disable=broad-except # logger.error("Error Crytic Compile") return False # function to run the tests -def run_test_suite(cmd: str, dir: str) -> bool: - try: - # Change to the foundry folder - # os.chdir(dir) +# def run_test_suite(cmd: str, dir: str) -> bool: +# try: +# # Change to the foundry folder +# # os.chdir(dir) - result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # result = subprocess.run(cmd.split(' '), check=True) - if not result.stderr: - return True - except subprocess.CalledProcessError as e: - logger.error(f"Error executing '{cmd}': {e}") +# result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +# # result = subprocess.run(cmd.split(' '), check=True) +# if not result.stderr: +# return True +# except subprocess.CalledProcessError as e: +# logger.error(f"Error executing '{cmd}': {e}") - return False - except Exception as e: - logger.error(f"An unexpected error occurred: {e}") - return False +# return False +# except Exception as e: +# logger.error(f"An unexpected error occurred: {e}") +# return False def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + # add --fail-fast for foundry tests, to exit after first failure + if "forge test" in cmd and not "--fail-fast" in cmd : + cmd += " --fail-fast" + # add --bail for hardhat and truffle tests, to exit after first failure + elif not "--bail" in cmd: + cmd += " --bail" + start = time.time() # starting new process P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) @@ -48,19 +54,18 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: time.sleep(0.05) finally: if P.poll() is None: - print() - print("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") # sends a SIGTERM signal to process group - bascially killing the process os.killpg(os.getpgid(P.pid), signal.SIGTERM) # Avoid any weird race conditions from grabbing the return code time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode - + # if r is 0 then it is valid mutant because tests didn't fail return True if r == 0 else False -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int) -> bool: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: with open(file, 'r') as filepath: content = filepath.read() # Perform the replacement based on the index values @@ -68,12 +73,13 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: # Write the modified content back to the file with open(file, 'w') as filepath: filepath.write(replaced_content) - if(compile_generated_mutant(file)): + if(compile_generated_mutant(file, mappings)): if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) - logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> VALID\n")) + logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) return True reset_file(file) - logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' in '{file}' ---> INVALID\n")) + if verbose: + logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) return False \ No newline at end of file From 9db71678179c9b76546f91d0406cf52c40d970bc Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Tue, 16 Jan 2024 12:00:08 -0500 Subject: [PATCH 308/338] Updated run_test_cmd --- slither/tools/mutator/__main__.py | 1 + .../mutator/mutators/abstract_mutator.py | 2 +- .../mutator/utils/testing_generated_mutant.py | 23 ++----------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index c41a82e35..8cbb103ad 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -165,6 +165,7 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: + # TODO for M in _get_mutators(mutators_to_run): m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) # check whether the contract instance exists or not diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 5223e2d81..bd40ad6ac 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -97,7 +97,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- return self.contract_exist @abc.abstractmethod - def _mutate(self, test_cmd: str, test_dir: str) -> Dict: + def _mutate(self) -> Dict: """TODO Documentation""" return {} diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 6c6e80a55..65cf78c27 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -16,33 +16,14 @@ def compile_generated_mutant(file_path: str, mappings: str) -> bool: crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True except: # pylint: disable=broad-except - # logger.error("Error Crytic Compile") return False - -# function to run the tests -# def run_test_suite(cmd: str, dir: str) -> bool: -# try: -# # Change to the foundry folder -# # os.chdir(dir) - -# result = subprocess.run(cmd.split(' '), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -# # result = subprocess.run(cmd.split(' '), check=True) -# if not result.stderr: -# return True -# except subprocess.CalledProcessError as e: -# logger.error(f"Error executing '{cmd}': {e}") - -# return False -# except Exception as e: -# logger.error(f"An unexpected error occurred: {e}") -# return False def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: # add --fail-fast for foundry tests, to exit after first failure - if "forge test" in cmd and not "--fail-fast" in cmd : + if "forge test" in cmd and not "--fail-fast" in cmd: cmd += " --fail-fast" # add --bail for hardhat and truffle tests, to exit after first failure - elif not "--bail" in cmd: + elif "hardhat test" in cmd or "truffle test" and not "--bail" in cmd: cmd += " --bail" start = time.time() From 6ad193abd99198bde804144d21fc29fcc89feb86 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 17 Jan 2024 11:54:06 -0500 Subject: [PATCH 309/338] updated create patch --- slither/tools/mutator/__main__.py | 30 +++++++++++++++-- slither/tools/mutator/mutators/AOR.py | 4 +-- slither/tools/mutator/mutators/ASOR.py | 4 +-- slither/tools/mutator/mutators/BOR.py | 4 +-- slither/tools/mutator/mutators/CR.py | 32 +++++++++++++++++++ slither/tools/mutator/mutators/FHR.py | 4 +-- slither/tools/mutator/mutators/LIR.py | 6 ++-- slither/tools/mutator/mutators/LOR.py | 4 +-- slither/tools/mutator/mutators/MIA.py | 6 ++-- slither/tools/mutator/mutators/MVIE.py | 6 ++-- slither/tools/mutator/mutators/MVIV.py | 7 ++-- slither/tools/mutator/mutators/MWA.py | 4 +-- slither/tools/mutator/mutators/ROR.py | 4 +-- .../tools/mutator/mutators/{RCR.py => RR.py} | 14 +++----- slither/tools/mutator/mutators/SBR.py | 6 ++-- slither/tools/mutator/mutators/UOR.py | 10 +++--- .../tools/mutator/mutators/all_mutators.py | 5 ++- slither/tools/mutator/utils/file_handling.py | 2 +- slither/tools/mutator/utils/patch.py | 22 +++++++++++++ .../mutator/utils/testing_generated_mutant.py | 2 +- 20 files changed, 125 insertions(+), 51 deletions(-) create mode 100644 slither/tools/mutator/mutators/CR.py rename slither/tools/mutator/mutators/{RCR.py => RR.py} (66%) create mode 100644 slither/tools/mutator/utils/patch.py diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 8cbb103ad..66c0941a6 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -83,6 +83,20 @@ def parse_args() -> argparse.Namespace: help="mutant generators to run", ) + # list of contract names you want to mutate + parser.add_argument( + "--contract-names", + help="list of contract names you want to mutate", + ) + + # flag to run full mutation based revert mutator output + parser.add_argument( + "--quick", + help="to stop full mutation if revert mutator passes", + action="store_true", + default=False, + ) + # Initiate all the crytic config cli options cryticparser.init(parser) @@ -118,6 +132,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def main() -> None: args = parse_args() + # arguments test_command: str = args.test_cmd test_directory: str = args.test_dir @@ -127,6 +142,8 @@ def main() -> None: solc_remappings: str | None = args.solc_remaps verbose: bool = args.verbose mutators_to_run: List[str] | None = args.mutators_to_run + contract_names: List[str] | None = args.contract_names + quick_flag: bool = args.quick print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) @@ -150,6 +167,13 @@ def main() -> None: if timeout == None: timeout = 30 + # setting RR mutator as first mutator + mutators_list = _get_mutators(mutators_to_run) + for M in mutators_list: + if M.NAME == "RR": + mutators_list.remove(M) + mutators_list.insert(0, M) + for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] # TODO: user provides contract name @@ -165,14 +189,16 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - # TODO - for M in _get_mutators(mutators_to_run): + for M in mutators_list: m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) # check whether the contract instance exists or not if m.get_exist_flag(): count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid + if quick_flag: + if str(m.NAME) == 'RR' and v_count > 0: + break except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 39e3a6a20..61eed67b1 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperation @@ -40,5 +40,5 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 04ad8f8b0..e6fa41437 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,5 +1,5 @@ from typing import Dict -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation @@ -44,5 +44,5 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index de9ad287e..5ca46950f 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature bitwise_operators = [ @@ -33,5 +33,5 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py new file mode 100644 index 000000000..1935c43e6 --- /dev/null +++ b/slither/tools/mutator/mutators/CR.py @@ -0,0 +1,32 @@ +from typing import Dict +from slither.core.cfg.node import NodeType +from slither.tools.mutator.utils.patch import create_patch_with_line +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature + + +class CR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "CR" + HELP = 'Comment Replacement' + FAULTNATURE = FaultNature.Missing + + def _mutate(self) -> Dict: + result: Dict = {} + + for function in self.contract.functions_and_modifiers_declared: + for node in function.nodes: + if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + # Get the string + start = node.source_mapping.start + stop = start + node.source_mapping.length + old_str = self.in_file_str[start:stop] + line_no = node.source_mapping.lines + new_str = "//" + old_str + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + return result + + + + + + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 5709346b1..3758306f3 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,5 +1,5 @@ from typing import Dict -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re @@ -31,6 +31,6 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 99228913a..c9966f1be 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -2,7 +2,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.core.solidity_types import ElementaryType literal_replacements = [] @@ -41,7 +41,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods old_value = old_str[old_str.find("=")+1:].strip() if old_value != value: new_str = f"{old_str.split('=')[0]}= {value}" - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -69,7 +69,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods old_value = old_str[old_str.find("=")+1:].strip() if old_value != new_value: new_str = f"{old_str.split('=')[0]}= {new_value}" - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index fa66c7bca..e6903a01e 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature logical_operators = [ @@ -32,5 +32,5 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index f5bc52b16..0217324e0 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation @@ -24,11 +24,11 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) print(node.expression) diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 3c334e9e6..c81182c43 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -2,7 +2,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" @@ -28,7 +28,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -48,7 +48,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 7f75b1dcf..890c55b1c 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,9 +1,8 @@ from typing import Dict - from slither.core.expressions import Literal from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" @@ -28,7 +27,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, @@ -46,7 +45,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch( + create_patch_with_line( result, self.in_file, start, diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index c6bacf485..9bb6a1600 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation @@ -23,5 +23,5 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index e1c78c1eb..2a38ce323 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature relational_operators = [ @@ -36,6 +36,6 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/RCR.py b/slither/tools/mutator/mutators/RR.py similarity index 66% rename from slither/tools/mutator/mutators/RCR.py rename to slither/tools/mutator/mutators/RR.py index 96aebc68f..95cbf617a 100644 --- a/slither/tools/mutator/mutators/RCR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -1,12 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature -class RCR(AbstractMutator): # pylint: disable=too-few-public-methods - NAME = "RCR" - HELP = 'Revert and Comment Replacement' +class RR(AbstractMutator): # pylint: disable=too-few-public-methods + NAME = "RR" + HELP = 'Revert Replacement' FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: @@ -22,11 +22,7 @@ class RCR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if old_str != 'revert()': new_str = 'revert()' - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - new_str = "//" + old_str - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 91c05b884..9e9afc1e5 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.cfg.node import NodeType -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re from slither.core.variables.variable import Variable @@ -67,7 +67,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) for variable in self.contract.state_variables_declared: node = variable.node_initialization @@ -81,7 +81,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) != None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index 671ee676d..aac4b02a6 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation -from slither.formatters.utils.patches import create_patch +from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature unary_operators = [ @@ -36,16 +36,16 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) if new_str != old_str and str(op) != '-': - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(op) + str(variable_read) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) else: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) if new_str != old_str and str(op) != '-': - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) - create_patch(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 9aa81a0fc..21925317d 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -12,6 +12,5 @@ from slither.tools.mutator.mutators.LIR import LIR # severity medium from slither.tools.mutator.mutators.FHR import FHR # severity medium from slither.tools.mutator.mutators.MIA import MIA # severity medium from slither.tools.mutator.mutators.ROR import ROR # severity medium -from slither.tools.mutator.mutators.RCR import RCR # severity high - - +from slither.tools.mutator.mutators.RR import RR # severity high +from slither.tools.mutator.mutators.CR import CR # severity high \ No newline at end of file diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index d61bba58a..01a142c8d 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -1,5 +1,5 @@ import os -from typing import Dict, Tuple, List +from typing import Dict, List import logging logger = logging.getLogger("Slither-Mutate") diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py new file mode 100644 index 000000000..39c77f673 --- /dev/null +++ b/slither/tools/mutator/utils/patch.py @@ -0,0 +1,22 @@ +from typing import Dict, Union +from collections import defaultdict + +# pylint: disable=too-many-arguments +def create_patch_with_line( + result: Dict, + file: str, + start: int, + end: int, + old_str: Union[str, bytes], + new_str: Union[str, bytes], + line_no: int +) -> None: + if isinstance(old_str, bytes): + old_str = old_str.decode("utf8") + if isinstance(new_str, bytes): + new_str = new_str.decode("utf8") + p = {"start": start, "end": end, "old_string": old_str, "new_string": new_str, "line_number": line_no} + if "patches" not in result: + result["patches"] = defaultdict(list) + if p not in result["patches"][file]: + result["patches"][file].append(p) \ No newline at end of file diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 65cf78c27..8525e2808 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -4,7 +4,7 @@ import os import logging import time import signal -from typing import List, Dict +from typing import Dict from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red From 96e8adc39b9eb0cc12c13d51b0c32437444665dd Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 18 Jan 2024 10:49:42 -0500 Subject: [PATCH 310/338] Added contract_names arg --- slither/tools/mutator/__main__.py | 16 +++++++---- slither/tools/mutator/mutators/FHR.py | 2 -- .../mutator/mutators/abstract_mutator.py | 28 ++++--------------- .../mutator/utils/testing_generated_mutant.py | 4 ++- 4 files changed, 19 insertions(+), 31 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 66c0941a6..e576970f7 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -176,7 +176,6 @@ def main() -> None: for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] - # TODO: user provides contract name # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -189,10 +188,17 @@ def main() -> None: # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_name, solc_remappings, verbose, output_folder) - # check whether the contract instance exists or not - if m.get_exist_flag(): + contract_instance = '' + for contract in compilation_unit_of_main_file.contracts: + if contract_names != None and contract.name in contract_names: + contract_instance = contract + elif str(contract.name).lower() == contract_name.lower(): + contract_instance = contract + if contract_instance == '': + logger.error("Can't find the contract") + else: + for M in mutators_list: + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder) count_valid, count_invalid = m.mutate() v_count += count_valid total_count += count_valid + count_invalid diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 3758306f3..a5d7f5f7f 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -3,8 +3,6 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature import re -# INFO: low severity - function_header_replacements = [ "pure ==> view", "view ==> pure", diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index bd40ad6ac..edd584386 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -7,6 +7,7 @@ from slither.core.compilation_unit import SlitherCompilationUnit from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch from slither.utils.colors import yellow +from slither.core.declarations import Contract logger = logging.getLogger("Slither-Mutate") @@ -36,7 +37,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- timeout: int, testing_command: str, testing_directory: str, - contract_name: str, + contract_instance: Contract, solc_remappings: str | None, verbose: bool, output_folder: str, @@ -50,10 +51,12 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.test_command = testing_command self.test_directory = testing_directory self.timeout = timeout - self.contract_exist = False self.solc_remappings = solc_remappings self.verbose = verbose self.output_folder = output_folder + self.contract = contract_instance + self.in_file = self.contract.source_mapping.filename.absolute + self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] if not self.NAME: raise IncorrectMutatorInitialization( @@ -74,27 +77,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) - - # identify the main contract, ignore the imports - for contract in self.slither.contracts: - # !limitation: what if the contract name is not same as file name - # !limitation: multi contract - if contract_name.lower() == str(contract.name).lower(): - # contract - self.contract = contract - # Retrieve the file - self.in_file = self.contract.source_mapping.filename.absolute - # Retrieve the source code - self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] - # flag contract existence - self.contract_exist = True - - if not self.contract_exist: - self.contract_exist = False - logger.error(f"Contract name is not matching with the File name ({contract_name}). Please refer 'https://docs.soliditylang.org/en/latest/style-guide.html#contract-and-library-names')") - - def get_exist_flag(self) -> bool: - return self.contract_exist @abc.abstractmethod def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 8525e2808..2013858df 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -9,7 +9,7 @@ from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") - +# dont_mutate_line = {} # function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: @@ -58,6 +58,8 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + # if generator_name == 'RR': + # dont_mutate_line[patch['line_number']] = True return True reset_file(file) From 48b6f6fee2bd82ae968d48b00eac23f97f4d46f2 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sat, 20 Jan 2024 12:25:12 -0500 Subject: [PATCH 311/338] updated quick --- slither/tools/mutator/__main__.py | 22 +++++--- slither/tools/mutator/mutators/AOR.py | 8 +-- slither/tools/mutator/mutators/ASOR.py | 7 ++- slither/tools/mutator/mutators/BOR.py | 7 ++- slither/tools/mutator/mutators/CR.py | 5 +- slither/tools/mutator/mutators/FHR.py | 13 +++-- slither/tools/mutator/mutators/LIR.py | 55 ++++++++++--------- slither/tools/mutator/mutators/LOR.py | 8 +-- slither/tools/mutator/mutators/MIA.py | 20 +++---- slither/tools/mutator/mutators/MVIE.py | 40 +++++++------- slither/tools/mutator/mutators/MVIV.py | 38 +++++++------ slither/tools/mutator/mutators/MWA.py | 8 +-- slither/tools/mutator/mutators/ROR.py | 8 +-- slither/tools/mutator/mutators/RR.py | 7 ++- slither/tools/mutator/mutators/SBR.py | 28 +++++----- slither/tools/mutator/mutators/UOR.py | 35 ++++++------ .../mutator/mutators/abstract_mutator.py | 14 +++-- .../mutator/utils/testing_generated_mutant.py | 4 +- 18 files changed, 172 insertions(+), 155 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index e576970f7..80d025c97 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -169,10 +169,17 @@ def main() -> None: # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) - for M in mutators_list: + + CR_RR_list = [] + duplicate_list = mutators_list.copy() + for M in duplicate_list: if M.NAME == "RR": mutators_list.remove(M) - mutators_list.insert(0, M) + CR_RR_list.insert(0,M) + elif M.NAME == "CR": + mutators_list.remove(M) + CR_RR_list.insert(1,M) + mutators_list = CR_RR_list + mutators_list for filename in sol_file_list: contract_name = os.path.split(filename)[1].split('.sol')[0] @@ -185,6 +192,7 @@ def main() -> None: # count of valid mutants v_count = 0 + dont_mutate_lines = [] # mutation try: for compilation_unit_of_main_file in sl.compilation_units: @@ -198,13 +206,13 @@ def main() -> None: logger.error("Can't find the contract") else: for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder) - count_valid, count_invalid = m.mutate() + m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder, dont_mutate_lines) + (count_valid, count_invalid, lines_list) = m.mutate() v_count += count_valid total_count += count_valid + count_invalid - if quick_flag: - if str(m.NAME) == 'RR' and v_count > 0: - break + dont_mutate_lines = lines_list + if not quick_flag: + dont_mutate_lines = [] except Exception as e: logger.error(e) diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 61eed67b1..11593ee37 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -19,7 +19,6 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: @@ -38,7 +37,8 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index e6fa41437..29a6dc672 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -42,7 +42,8 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 5ca46950f..6a5552a5f 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -31,7 +31,8 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 1935c43e6..79a63a88f 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -20,8 +20,9 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - new_str = "//" + old_str - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + new_str = "//" + old_str + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index a5d7f5f7f..84bfebe22 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -24,11 +24,12 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + function.source_mapping.content.find('{') old_str = self.in_file_str[start:stop] line_no = function.source_mapping.lines - for value in function_header_replacements: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in function_header_replacements: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index c9966f1be..e8217e935 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -36,20 +36,20 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.node_initialization.source_mapping.lines - # line_no = [0] - for value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() - if old_value != value: - new_str = f"{old_str.split('=')[0]}= {value}" - create_patch_with_line( - result, - self.in_file, - start, - stop, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + for value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != value: + new_str = f"{old_str.split('=')[0]}= {value}" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -65,18 +65,19 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.source_mapping.lines - for new_value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() - if old_value != new_value: - new_str = f"{old_str.split('=')[0]}= {new_value}" - create_patch_with_line( - result, - self.in_file, - start, - stop, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + for new_value in literal_replacements: + old_value = old_str[old_str.find("=")+1:].strip() + if old_value != new_value: + new_str = f"{old_str.split('=')[0]}= {new_value}" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index e6903a01e..e14c85708 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -29,8 +29,8 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 0217324e0..421f94a5e 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -20,16 +20,14 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true and false + for value in ["true", "false"]: + new_str = value + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - # Replace the expression with true and false - for value in ["true", "false"]: - new_str = value - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - print(node.expression) - return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index c81182c43..4ae387d29 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -25,18 +25,18 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -45,17 +45,17 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods start = variable.source_mapping.start stop = variable.expression.source_mapping.start old_str = self.in_file_str[start:stop] - new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 890c55b1c..68bc2f2d8 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -27,15 +27,16 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.node_initialization.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: @@ -45,14 +46,15 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods old_str = self.in_file_str[start:stop] new_str = old_str[: old_str.find("=")] line_no = variable.source_mapping.lines - create_patch_with_line( - result, - self.in_file, - start, - stop + variable.expression.source_mapping.length, - old_str, - new_str, - line_no[0] - ) + if not line_no[0] in self.dont_mutate_line: + create_patch_with_line( + result, + self.in_file, + start, + stop + variable.expression.source_mapping.length, + old_str, + new_str, + line_no[0] + ) return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 9bb6a1600..4c1e91b32 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -20,8 +20,8 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - - if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + if not isinstance(node.expression, UnaryOperation): + new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 2a38ce323..da75a592a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -33,9 +33,9 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + ir.expression.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - # Replace the expression with true - new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + # Replace the expression with true + new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 95cbf617a..3aab255ec 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -20,9 +20,10 @@ class RR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - if old_str != 'revert()': - new_str = 'revert()' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + if old_str != 'revert()': + new_str = 'revert()' + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 9e9afc1e5..f6adfff84 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -56,18 +56,19 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type != NodeType.ENTRYPOINT: + if node.type != NodeType.ENTRYPOINT and node.type != NodeType.ENDIF and node.type != NodeType.ENDLOOP: # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - for value in solidity_rules: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) for variable in self.contract.state_variables_declared: node = variable.node_initialization @@ -76,12 +77,13 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - for value in solidity_rules: - left_value = value.split(" ==> ")[0] - right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if not line_no[0] in self.dont_mutate_line: + for value in solidity_rules: + left_value = value.split(" ==> ")[0] + right_value = value.split(" ==> ")[1] + if re.search(re.compile(left_value), old_str) != None: + new_str = re.sub(re.compile(left_value), right_value, old_str) + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index aac4b02a6..fa00b52ae 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -29,23 +29,24 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines - if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: - for op in unary_operators: - if not node.expression.is_prefix: - if node.expression.type != op: - variable_read = node.variables_read[0] - new_str = str(variable_read) + str(op) - if new_str != old_str and str(op) != '-': + if not line_no[0] in self.dont_mutate_line: + if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: + for op in unary_operators: + if not node.expression.is_prefix: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(variable_read) + str(op) + if new_str != old_str and str(op) != '-': + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(op) + str(variable_read) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - new_str = str(op) + str(variable_read) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - else: - if node.expression.type != op: - variable_read = node.variables_read[0] - new_str = str(op) + str(variable_read) - if new_str != old_str and str(op) != '-': + else: + if node.expression.type != op: + variable_read = node.variables_read[0] + new_str = str(op) + str(variable_read) + if new_str != old_str and str(op) != '-': + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(variable_read) + str(op) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - new_str = str(variable_read) + str(op) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index edd584386..f11d69db1 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,7 +1,7 @@ import abc import logging from enum import Enum -from typing import Optional, Dict, Tuple +from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit # from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff @@ -41,6 +41,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- solc_remappings: str | None, verbose: bool, output_folder: str, + dont_mutate_line: List[int], rate: int = 10, seed: Optional[int] = None ) -> None: @@ -57,6 +58,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- self.contract = contract_instance self.in_file = self.contract.source_mapping.filename.absolute self.in_file_str = self.contract.compilation_unit.core.source_code[self.in_file] + self.dont_mutate_line = dont_mutate_line if not self.NAME: raise IncorrectMutatorInitialization( @@ -83,13 +85,12 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- """TODO Documentation""" return {} - def mutate(self) -> Tuple[int, int]: + def mutate(self) -> Tuple[int, int, List[int]]: # call _mutate function from different mutators (all_patches) = self._mutate() - if "patches" not in all_patches: logger.debug(f"No patches found by {self.NAME}") - return (0,0) + return (0,0,self.dont_mutate_line) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -99,6 +100,8 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + if (self.NAME == 'RR' or self.NAME == 'CR') and flag: + self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 @@ -112,8 +115,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT) + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 2013858df..8525e2808 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -9,7 +9,7 @@ from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") -# dont_mutate_line = {} + # function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: try: @@ -58,8 +58,6 @@ def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: if(run_test_cmd(command, file, timeout)): create_mutant_file(file, index, generator_name) logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) - # if generator_name == 'RR': - # dont_mutate_line[patch['line_number']] = True return True reset_file(file) From 799117d0868a0e2eaab0085b42eb416822942328 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Sun, 21 Jan 2024 12:08:13 -0500 Subject: [PATCH 312/338] Added README --- slither/tools/mutator/README.md | 31 +++++++++++++++++++ slither/tools/mutator/__main__.py | 12 ++++--- .../mutator/mutators/abstract_mutator.py | 2 +- slither/tools/mutator/utils/file_handling.py | 4 +-- 4 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 slither/tools/mutator/README.md diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md new file mode 100644 index 000000000..11b0b7eb5 --- /dev/null +++ b/slither/tools/mutator/README.md @@ -0,0 +1,31 @@ +# Slither-mutate + +`slither-mutate` is a mutation testing tool for solidity based smart contracts. + +## Usage + +`slither-mutate ` + +### CLI Interface + +``` +positional arguments: + codebase Codebase to analyze (.sol file, truffle directory, ...) + test-cmd Command to run the tests for your project + +options: + -h, --help show this help message and exit + --list-mutators List available detectors + --test-dir TEST_DIR Tests directory + --ignore-dirs IGNORE_DIRS + Directories to ignore + --timeout TIMEOUT Set timeout for test command (by default 30 seconds) + --output-dir OUTPUT_DIR + Name of output Directory (by default 'mutation_campaign') + --verbose output all mutants generated + --mutators-to-run MUTATORS_TO_RUN + mutant generators to run + --contract-names CONTRACT_NAMES + list of contract names you want to mutate + --quick to stop full mutation if revert mutator passes +``` \ No newline at end of file diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 80d025c97..b375e9558 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -41,14 +41,14 @@ def parse_args() -> argparse.Namespace: # argument to add the test command parser.add_argument( - "--test-cmd", - help="Command line needed to run the tests for your project" + "test-cmd", + help="Command to run the tests for your project" ) # argument to add the test directory - containing all the tests parser.add_argument( "--test-dir", - help="Directory of tests" + help="Tests directory" ) # argument to ignore the interfaces, libraries @@ -66,7 +66,7 @@ def parse_args() -> argparse.Namespace: # output directory argument parser.add_argument( "--output-dir", - help="Output Directory (by default 'mutation_campaign')" + help="Name of output directory (by default 'mutation_campaign')" ) # to print just all the mutants @@ -170,6 +170,7 @@ def main() -> None: # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) + # insert RR and CR in front of the list CR_RR_list = [] duplicate_list = mutators_list.copy() for M in duplicate_list: @@ -191,8 +192,9 @@ def main() -> None: total_count = 0 # count of valid mutants v_count = 0 - + # lines those need not be mutated (taken from RR and CR) dont_mutate_lines = [] + # mutation try: for compilation_unit_of_main_file in sl.compilation_units: diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index f11d69db1..558a51451 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -3,7 +3,6 @@ import logging from enum import Enum from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit -# from slither.tools.doctor.utils import snip_section from slither.formatters.utils.patches import apply_patch, create_diff from slither.tools.mutator.utils.testing_generated_mutant import test_patch from slither.utils.colors import yellow @@ -100,6 +99,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + # if RR or CR and valid mutant, add line no. if (self.NAME == 'RR' or self.NAME == 'CR') and flag: self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index 01a142c8d..ffebee9fc 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -104,6 +104,4 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str for i in get_sol_file_list(filename, ignore_paths): sol_file_list.append(i) - return sol_file_list - -# TODO: create a function to delete the commands from the sol file + return sol_file_list \ No newline at end of file From 5fb5f69b8e15480eeb0cd37b22f8123719ebe7e3 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 24 Jan 2024 11:47:55 -0500 Subject: [PATCH 313/338] Updated arguments --- slither/tools/mutator/README.md | 6 +++--- slither/tools/mutator/__main__.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index 11b0b7eb5..c615b0b79 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -4,24 +4,24 @@ ## Usage -`slither-mutate ` +`slither-mutate --test-cmd ` ### CLI Interface ``` positional arguments: codebase Codebase to analyze (.sol file, truffle directory, ...) - test-cmd Command to run the tests for your project options: -h, --help show this help message and exit --list-mutators List available detectors + --test-cmd TEST_CMD Command to run the tests for your project --test-dir TEST_DIR Tests directory --ignore-dirs IGNORE_DIRS Directories to ignore --timeout TIMEOUT Set timeout for test command (by default 30 seconds) --output-dir OUTPUT_DIR - Name of output Directory (by default 'mutation_campaign') + Name of output directory (by default 'mutation_campaign') --verbose output all mutants generated --mutators-to-run MUTATORS_TO_RUN mutant generators to run diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index b375e9558..7bd4f8d79 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -26,7 +26,7 @@ logger.setLevel(logging.INFO) def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", - usage="slither-mutate target", + usage="slither-mutate --test-cmd ", ) parser.add_argument("codebase", help="Codebase to analyze (.sol file, truffle directory, ...)") @@ -41,7 +41,7 @@ def parse_args() -> argparse.Namespace: # argument to add the test command parser.add_argument( - "test-cmd", + "--test-cmd", help="Command to run the tests for your project" ) From 71f970f0517befa56ae6875f6c7d7711789024dd Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Wed, 24 Jan 2024 14:49:28 -0500 Subject: [PATCH 314/338] Updated mutators --- slither/tools/mutator/README.md | 2 ++ slither/tools/mutator/__main__.py | 2 +- slither/tools/mutator/mutators/AOR.py | 3 +-- slither/tools/mutator/mutators/ASOR.py | 3 +-- slither/tools/mutator/mutators/BOR.py | 3 +-- slither/tools/mutator/mutators/CR.py | 3 +-- slither/tools/mutator/mutators/FHR.py | 3 +-- slither/tools/mutator/mutators/LIR.py | 3 +-- slither/tools/mutator/mutators/LOR.py | 3 +-- slither/tools/mutator/mutators/MIA.py | 3 +-- slither/tools/mutator/mutators/MVIE.py | 3 +-- slither/tools/mutator/mutators/MVIV.py | 3 +-- slither/tools/mutator/mutators/MWA.py | 3 +-- slither/tools/mutator/mutators/ROR.py | 3 +-- slither/tools/mutator/mutators/RR.py | 4 +--- slither/tools/mutator/mutators/SBR.py | 3 +-- slither/tools/mutator/mutators/UOR.py | 3 +-- .../mutator/mutators/abstract_mutator.py | 24 +------------------ slither/tools/mutator/utils/command_line.py | 13 +++++----- 19 files changed, 25 insertions(+), 62 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index c615b0b79..30b83ac46 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -6,6 +6,8 @@ `slither-mutate --test-cmd ` +To view the list of mutators available `slither-mutate --list-mutators` + ### CLI Interface ``` diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 7bd4f8d79..13e78a30e 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -118,7 +118,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any ) -> None: # pylint: disable=signature-differs - checks = _get_mutators() + checks = _get_mutators(None) output_mutators(checks) parser.exit() diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 11593ee37..0c7f906b3 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperation arithmetic_operators = [ @@ -15,7 +15,6 @@ arithmetic_operators = [ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 29a6dc672..551cf8c64 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation assignment_operators = [ @@ -20,7 +20,6 @@ assignment_operators = [ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 6a5552a5f..b6a9ae749 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator bitwise_operators = [ BinaryType.AND, @@ -14,7 +14,6 @@ bitwise_operators = [ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 79a63a88f..5c34416e9 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class CR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "CR" HELP = 'Comment Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 84bfebe22..847466611 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,6 +1,6 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator import re function_header_replacements = [ @@ -13,7 +13,6 @@ function_header_replacements = [ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "FHR" HELP = 'Function Header Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index e8217e935..29efe6502 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line from slither.core.solidity_types import ElementaryType @@ -10,7 +10,6 @@ literal_replacements = [] class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index e14c85708..a8fff1c31 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator logical_operators = [ BinaryType.OROR, @@ -11,7 +11,6 @@ logical_operators = [ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" HELP = "Logical Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 421f94a5e..592014349 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 4ae387d29..b562ba9b0 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index 68bc2f2d8..dcb5be259 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.expressions import Literal from slither.core.variables.variable import Variable -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 4c1e91b32..b482ab566 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -1,13 +1,12 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation class MWA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MWA" HELP = '"while" construct around statement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index da75a592a..826b15a4a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.slithir.operations import Binary, BinaryType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator relational_operators = [ BinaryType.LESS, @@ -15,7 +15,6 @@ relational_operators = [ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" HELP = "Relational Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 3aab255ec..5afe18892 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -1,13 +1,11 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature - +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class RR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "RR" HELP = 'Revert Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index f6adfff84..0e9432908 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator import re from slither.core.variables.variable import Variable @@ -47,7 +47,6 @@ solidity_rules = [ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" HELP = 'Solidity Based Replacement' - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index fa00b52ae..cf62c21bd 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -1,7 +1,7 @@ from typing import Dict from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation from slither.tools.mutator.utils.patch import create_patch_with_line -from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator, FaultNature +from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator unary_operators = [ UnaryOperationType.PLUSPLUS_PRE, @@ -14,7 +14,6 @@ unary_operators = [ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOR" HELP = "Unary Operator Replacement" - FAULTNATURE = FaultNature.Missing def _mutate(self) -> Dict: result: Dict = {} diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 558a51451..ea331e7c5 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -1,6 +1,5 @@ import abc import logging -from enum import Enum from typing import Optional, Dict, Tuple, List from slither.core.compilation_unit import SlitherCompilationUnit from slither.formatters.utils.patches import apply_patch, create_diff @@ -12,22 +11,10 @@ logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - -class FaultNature(Enum): - Missing = 0 - Wrong = 1 - Extraneous = 2 - Undefined = 100 - - # not executed - can be detected by replacing with revert - # has no effect - can be detected by removing a line / comment - # can have valid mutant - # can't have valid mutant class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" - FAULTNATURE = FaultNature.Undefined VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 @@ -69,11 +56,6 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- f"HELP is not initialized {self.__class__.__name__}" ) - if self.FAULTNATURE == FaultNature.Undefined: - raise IncorrectMutatorInitialization( - f"FAULTNATURE is not initialized {self.__class__.__name__}" - ) - if rate < 0 or rate > 100: raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" @@ -115,8 +97,4 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) - - - - \ No newline at end of file + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) \ No newline at end of file diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 042b4fff7..358586688 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -7,14 +7,13 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: for detector in mutators_classes: argument = detector.NAME help_info = detector.HELP - fault_nature = detector.FAULTNATURE.name - mutators_list.append((argument, help_info, fault_nature)) - table = MyPrettyTable(["Num", "Name", "What it Does", "Fault Nature"]) + mutators_list.append((argument, help_info)) + table = MyPrettyTable(["Num", "Name", "What it Does"]) - # Sort by class, nature, name - mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[0])) + # Sort by class + mutators_list = sorted(mutators_list, key=lambda element: (element[0])) idx = 1 - for (argument, help_info, fault_nature) in mutators_list: - table.add_row([str(idx), argument, help_info, fault_nature]) + for (argument, help_info) in mutators_list: + table.add_row([str(idx), argument, help_info]) idx = idx + 1 print(table) From c8462b24339a36b3c9faa48524fe184d1ce844dc Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 25 Jan 2024 12:46:34 -0500 Subject: [PATCH 315/338] Updated files --- slither/tools/mutator/README.md | 8 +-- slither/tools/mutator/__main__.py | 66 ++++++++++--------- slither/tools/mutator/mutators/AOR.py | 6 +- slither/tools/mutator/mutators/ASOR.py | 6 +- slither/tools/mutator/mutators/BOR.py | 4 +- slither/tools/mutator/mutators/CR.py | 13 +--- slither/tools/mutator/mutators/FHR.py | 13 ++-- slither/tools/mutator/mutators/LIR.py | 7 +- slither/tools/mutator/mutators/LOR.py | 4 +- slither/tools/mutator/mutators/MIA.py | 7 +- slither/tools/mutator/mutators/MVIE.py | 3 +- slither/tools/mutator/mutators/MVIV.py | 3 +- slither/tools/mutator/mutators/MWA.py | 7 +- slither/tools/mutator/mutators/ROR.py | 3 +- slither/tools/mutator/mutators/RR.py | 10 +-- slither/tools/mutator/mutators/SBR.py | 20 ++---- slither/tools/mutator/mutators/UOR.py | 7 +- .../mutator/mutators/abstract_mutator.py | 30 ++++----- .../tools/mutator/mutators/all_mutators.py | 4 +- slither/tools/mutator/utils/file_handling.py | 60 +++++++++-------- slither/tools/mutator/utils/patch.py | 2 +- .../mutator/utils/testing_generated_mutant.py | 54 ++++++++++----- 22 files changed, 168 insertions(+), 169 deletions(-) diff --git a/slither/tools/mutator/README.md b/slither/tools/mutator/README.md index 30b83ac46..8af977b08 100644 --- a/slither/tools/mutator/README.md +++ b/slither/tools/mutator/README.md @@ -1,6 +1,6 @@ # Slither-mutate -`slither-mutate` is a mutation testing tool for solidity based smart contracts. +`slither-mutate` is a mutation testing tool for solidity based smart contracts. ## Usage @@ -10,9 +10,9 @@ To view the list of mutators available `slither-mutate --list-mutators` ### CLI Interface -``` +```shell positional arguments: - codebase Codebase to analyze (.sol file, truffle directory, ...) + codebase Codebase to analyze (.sol file, project directory, ...) options: -h, --help show this help message and exit @@ -30,4 +30,4 @@ options: --contract-names CONTRACT_NAMES list of contract names you want to mutate --quick to stop full mutation if revert mutator passes -``` \ No newline at end of file +``` diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 13e78a30e..56582d6f5 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -4,14 +4,14 @@ import logging import sys import os import shutil -from typing import Type, List, Any +from typing import Type, List, Any, Optional from crytic_compile import cryticparser from slither import Slither from slither.tools.mutator.mutators import all_mutators +from slither.utils.colors import yellow, magenta from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list -from slither.utils.colors import yellow, magenta logging.basicConfig() logger = logging.getLogger("Slither-Mutate") @@ -24,12 +24,16 @@ logger.setLevel(logging.INFO) ################################################################################### def parse_args() -> argparse.Namespace: + """ + Parse the underlying arguments for the program. + Returns: The arguments for the program. + """ parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", usage="slither-mutate --test-cmd ", ) - parser.add_argument("codebase", help="Codebase to analyze (.sol file, truffle directory, ...)") + parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") parser.add_argument( "--list-mutators", @@ -108,7 +112,7 @@ def parse_args() -> argparse.Namespace: def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] - if not mutators_list is None: + if mutators_list is not None: detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] else: detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] @@ -122,7 +126,6 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods output_mutators(checks) parser.exit() - # endregion ################################################################################### ################################################################################### @@ -130,46 +133,46 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### -def main() -> None: +def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments test_command: str = args.test_cmd - test_directory: str = args.test_dir - paths_to_ignore: str | None = args.ignore_dirs - output_dir: str | None = args.output_dir - timeout: int | None = args.timeout - solc_remappings: str | None = args.solc_remaps - verbose: bool = args.verbose - mutators_to_run: List[str] | None = args.mutators_to_run - contract_names: List[str] | None = args.contract_names - quick_flag: bool = args.quick - - print(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) + test_directory: Optional[str] = args.test_dir + paths_to_ignore: Optional[str] = args.ignore_dirs + output_dir: Optional[str] = args.output_dir + timeout: Optional[int] = args.timeout + solc_remappings: Optional[str] = args.solc_remaps + verbose: Optional[bool] = args.verbose + mutators_to_run: Optional[List[str]] = args.mutators_to_run + contract_names: Optional[List[str]] = args.contract_names + quick_flag: Optional[bool] = args.quick + + logger.info(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) if paths_to_ignore: paths_to_ignore_list = paths_to_ignore.strip('][').split(',') - print(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) + logger.info(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) else: paths_to_ignore_list = [] - # get all the contracts as a list from given codebase + # get all the contracts as a list from given codebase sol_file_list: List[str] = get_sol_file_list(args.codebase, paths_to_ignore_list) # folder where backup files and valid mutants created - if output_dir == None: + if output_dir is None: output_dir = "/mutation_campaign" output_folder = os.getcwd() + output_dir if os.path.exists(output_folder): shutil.rmtree(output_folder) # set default timeout - if timeout == None: + if timeout is None: timeout = 30 # setting RR mutator as first mutator mutators_list = _get_mutators(mutators_to_run) - + # insert RR and CR in front of the list CR_RR_list = [] duplicate_list = mutators_list.copy() @@ -178,15 +181,15 @@ def main() -> None: mutators_list.remove(M) CR_RR_list.insert(0,M) elif M.NAME == "CR": - mutators_list.remove(M) + mutators_list.remove(M) CR_RR_list.insert(1,M) mutators_list = CR_RR_list + mutators_list - for filename in sol_file_list: + for filename in sol_file_list: # pylint: disable=too-many-nested-blocks contract_name = os.path.split(filename)[1].split('.sol')[0] # slither object sl = Slither(filename, **vars(args)) - # create a backup files + # create a backup files files_dict = backup_source_file(sl.source_code, output_folder) # total count of mutants total_count = 0 @@ -200,7 +203,7 @@ def main() -> None: for compilation_unit_of_main_file in sl.compilation_units: contract_instance = '' for contract in compilation_unit_of_main_file.contracts: - if contract_names != None and contract.name in contract_names: + if contract_names is not None and contract.name in contract_names: contract_instance = contract elif str(contract.name).lower() == contract_name.lower(): contract_instance = contract @@ -215,20 +218,19 @@ def main() -> None: dont_mutate_lines = lines_list if not quick_flag: dont_mutate_lines = [] - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(e) except KeyboardInterrupt: # transfer and delete the backup files if interrupted logger.error("\nExecution interrupted by user (Ctrl + C). Cleaning up...") transfer_and_delete(files_dict) - + # transfer and delete the backup files transfer_and_delete(files_dict) - + # output - print(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) + logger.info(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) - print(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) + logger.info(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) # endregion - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 0c7f906b3..00506a1bb 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -18,11 +18,11 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: try: ir_expression = node.expression - except: + except: # pylint: disable=bare-except continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: @@ -40,4 +40,4 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 551cf8c64..0e7452594 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -24,7 +24,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: @@ -33,7 +33,7 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods alternative_ops = assignment_operators[:] try: alternative_ops.remove(ir.expression.type) - except: + except: # pylint: disable=bare-except continue for op in alternative_ops: if op != ir.expression: @@ -45,4 +45,4 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index b6a9ae749..9f8ca2a11 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -18,7 +18,7 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in bitwise_operators: @@ -34,4 +34,4 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 5c34416e9..296028236 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -11,22 +11,15 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: new_str = "//" + old_str create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 847466611..4560db4da 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -1,7 +1,8 @@ from typing import Dict +import re from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -import re + function_header_replacements = [ "pure ==> view", @@ -16,9 +17,8 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - - for function in self.contract.functions_and_modifiers_declared: - # function_header = function.source_mapping.content.split('{')[0] + + for function in self.contract.functions_and_modifiers_declared: start = function.source_mapping.start stop = start + function.source_mapping.content.find('{') old_str = self.in_file_str[start:stop] @@ -27,8 +27,7 @@ class FHR(AbstractMutator): # pylint: disable=too-few-public-methods for value in function_header_replacements: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 29efe6502..f9ef874cd 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -11,12 +11,12 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - def _mutate(self) -> Dict: + def _mutate(self) -> Dict: # pylint: disable=too-many-branches result: Dict = {} variable: Variable # Create fault for state variables declaration - for variable in self.contract.state_variables_declared: + for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: @@ -50,7 +50,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods line_no[0] ) - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): @@ -78,5 +78,4 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index a8fff1c31..21837d81e 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -15,7 +15,7 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -32,4 +32,4 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index 592014349..a10ce1f1d 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -10,7 +10,6 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IF: @@ -24,9 +23,9 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods for value in ["true", "false"]: new_str = value create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - + if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index b562ba9b0..678b3b747 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -56,5 +56,4 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - - return result + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index dcb5be259..c82f132d7 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -55,5 +55,4 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods new_str, line_no[0] ) - - return result + return result \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index b482ab566..20447290a 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -10,7 +10,7 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - + for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: if node.type == NodeType.IFLOOP: @@ -22,5 +22,6 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: if not isinstance(node.expression, UnaryOperation): new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - return result \ No newline at end of file + create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + return result + \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index 826b15a4a..d59e7575a 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -19,7 +19,7 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: @@ -37,4 +37,3 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 5afe18892..6bfd644e0 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -12,20 +12,14 @@ class RR(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and NodeType.ENDIF != node.type and NodeType.ENDLOOP != node.type: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: if old_str != 'revert()': new_str = 'revert()' create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 0e9432908..bbdc63194 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -1,8 +1,8 @@ from typing import Dict +import re from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -import re from slither.core.variables.variable import Variable solidity_rules = [ @@ -43,19 +43,17 @@ solidity_rules = [ "while ==> if", ] - class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" HELP = 'Solidity Based Replacement' def _mutate(self) -> Dict: - result: Dict = {} variable: Variable - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: - if node.type != NodeType.ENTRYPOINT and node.type != NodeType.ENDIF and node.type != NodeType.ENDLOOP: + if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length @@ -65,11 +63,11 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - for variable in self.contract.state_variables_declared: + for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks node = variable.node_initialization if node: start = node.source_mapping.start @@ -80,13 +78,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods for value in solidity_rules: left_value = value.split(" ==> ")[0] right_value = value.split(" ==> ")[1] - if re.search(re.compile(left_value), old_str) != None: + if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) return result - - - - - - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index cf62c21bd..b7e8c8156 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -18,11 +18,11 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: + for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks for node in function.nodes: try: ir_expression = node.expression - except: + except: # pylint: disable=bare-except continue start = node.source_mapping.start stop = start + node.source_mapping.length @@ -47,5 +47,4 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) new_str = str(variable_read) + str(op) create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) - - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index ea331e7c5..c2f15cd74 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -11,24 +11,24 @@ logger = logging.getLogger("Slither-Mutate") class IncorrectMutatorInitialization(Exception): pass - + class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods NAME = "" HELP = "" VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 - def __init__( - self, compilation_unit: SlitherCompilationUnit, - timeout: int, - testing_command: str, - testing_directory: str, - contract_instance: Contract, - solc_remappings: str | None, + def __init__( # pylint: disable=too-many-arguments + self, compilation_unit: SlitherCompilationUnit, + timeout: int, + testing_command: str, + testing_directory: str, + contract_instance: Contract, + solc_remappings: str | None, verbose: bool, output_folder: str, dont_mutate_line: List[int], - rate: int = 10, + rate: int = 10, seed: Optional[int] = None ) -> None: self.compilation_unit = compilation_unit @@ -60,7 +60,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- raise IncorrectMutatorInitialization( f"rate must be between 0 and 100 {self.__class__.__name__}" ) - + @abc.abstractmethod def _mutate(self) -> Dict: """TODO Documentation""" @@ -70,19 +70,19 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # call _mutate function from different mutators (all_patches) = self._mutate() if "patches" not in all_patches: - logger.debug(f"No patches found by {self.NAME}") + logger.debug("No patches found by %s", self.NAME) return (0,0,self.dont_mutate_line) - + for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") patches = all_patches["patches"][file] patches.sort(key=lambda x: x["start"]) - print(yellow(f"Mutating {file} with {self.NAME} \n")) + logger.info(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) # if RR or CR and valid mutant, add line no. - if (self.NAME == 'RR' or self.NAME == 'CR') and flag: + if self.NAME in ('RR', 'CR') and flag: self.dont_mutate_line.append(patch['line_number']) # count the valid and invalid mutants if not flag: @@ -97,4 +97,4 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- # add valid mutant patches to a output file with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) \ No newline at end of file + return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 21925317d..852a8efc3 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -3,7 +3,7 @@ from slither.tools.mutator.mutators.MVIV import MVIV # severity low from slither.tools.mutator.mutators.MVIE import MVIE # severity low from slither.tools.mutator.mutators.LOR import LOR # severity medium from slither.tools.mutator.mutators.UOR import UOR # severity medium -from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium from slither.tools.mutator.mutators.AOR import AOR # severity medium from slither.tools.mutator.mutators.BOR import BOR # severity medium from slither.tools.mutator.mutators.ASOR import ASOR # severity medium @@ -13,4 +13,4 @@ from slither.tools.mutator.mutators.FHR import FHR # severity medium from slither.tools.mutator.mutators.MIA import MIA # severity medium from slither.tools.mutator.mutators.ROR import ROR # severity medium from slither.tools.mutator.mutators.RR import RR # severity high -from slither.tools.mutator.mutators.CR import CR # severity high \ No newline at end of file +from slither.tools.mutator.mutators.CR import CR # severity high diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index ffebee9fc..d4474c310 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,47 +6,49 @@ logger = logging.getLogger("Slither-Mutate") duplicated_files = {} -# function to backup the source file def backup_source_file(source_code: Dict, output_folder: str) -> Dict: + """ + function to backup the source file + returns: dictionary of duplicated files + """ os.makedirs(output_folder, exist_ok=True) - + for file_path, content in source_code.items(): directory, filename = os.path.split(file_path) new_filename = f"{output_folder}/backup_{filename}" new_file_path = os.path.join(directory, new_filename) - with open(new_file_path, 'w') as new_file: + with open(new_file_path, 'w', encoding="utf8") as new_file: new_file.write(content) duplicated_files[file_path] = new_file_path return duplicated_files -# function to transfer the original content to the sol file after campaign def transfer_and_delete(files_dict: Dict) -> None: + """function to transfer the original content to the sol file after campaign""" try: files_dict_copy = files_dict.copy() - for item, value in files_dict_copy.items(): - with open(value, 'r') as duplicated_file: + for item, value in files_dict_copy.items(): + with open(value, 'r', encoding="utf8") as duplicated_file: content = duplicated_file.read() - with open(item, 'w') as original_file: + with open(item, 'w', encoding="utf8") as original_file: original_file.write(content) os.remove(value) # delete elements from the global dict del duplicated_files[item] - - except Exception as e: + + except Exception as e: # pylint: disable=broad-except logger.error(f"Error transferring content: {e}") -#function to create new mutant file def create_mutant_file(file: str, count: int, rule: str) -> None: - + """function to create new mutant file""" try: - directory, filename = os.path.split(file) + _, filename = os.path.split(file) # Read content from the duplicated file - with open(file, 'r') as source_file: + with open(file, 'r', encoding="utf8") as source_file: content = source_file.read() # Write content to the original file @@ -54,42 +56,46 @@ def create_mutant_file(file: str, count: int, rule: str) -> None: # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w') as mutant_file: + with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w', encoding="utf8") as mutant_file: mutant_file.write(content) # reset the file - with open(duplicated_files[file], 'r') as duplicated_file: + with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w') as source_file: + with open(file, 'w', encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(f"Error creating mutant: {e}") -# function to reset the file def reset_file(file: str) -> None: + """function to reset the file""" try: # directory, filename = os.path.split(file) # reset the file - with open(duplicated_files[file], 'r') as duplicated_file: + with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w') as source_file: + with open(file, 'w', encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: + except Exception as e: # pylint: disable=broad-except logger.error(f"Error resetting file: {e}") -# function to get the contracts list + def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str]: + """ + function to get the contracts list + returns: list of .sol files + """ sol_file_list = [] - if ignore_paths == None: + if ignore_paths is None: ignore_paths = [] # if input is contract file if os.path.isfile(codebase): return [codebase] - + # if input is folder elif os.path.isdir(codebase): directory = os.path.abspath(codebase) @@ -98,10 +104,10 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str if os.path.isfile(filename): sol_file_list.append(filename) elif os.path.isdir(filename): - directory_name, dirname = os.path.split(filename) + _, dirname = os.path.split(filename) if dirname in ignore_paths: - continue + continue for i in get_sol_file_list(filename, ignore_paths): sol_file_list.append(i) - return sol_file_list \ No newline at end of file + return sol_file_list diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py index 39c77f673..e50f44612 100644 --- a/slither/tools/mutator/utils/patch.py +++ b/slither/tools/mutator/utils/patch.py @@ -19,4 +19,4 @@ def create_patch_with_line( if "patches" not in result: result["patches"] = defaultdict(list) if p not in result["patches"][file]: - result["patches"][file].append(p) \ No newline at end of file + result["patches"][file].append(p) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 8525e2808..5c75f0eb3 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -1,34 +1,48 @@ -import crytic_compile import subprocess import os import logging import time import signal from typing import Dict +import crytic_compile from slither.tools.mutator.utils.file_handling import create_mutant_file, reset_file from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") -# function to compile the generated mutant def compile_generated_mutant(file_path: str, mappings: str) -> bool: + """ + function to compile the generated mutant + returns: status of compilation + """ try: crytic_compile.CryticCompile(file_path, solc_remaps=mappings) return True - except: # pylint: disable=broad-except + except: # pylint: disable=bare-except return False - + def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + """ + function to run codebase tests + returns: boolean whether the tests passed or not + """ # add --fail-fast for foundry tests, to exit after first failure - if "forge test" in cmd and not "--fail-fast" in cmd: + if "forge test" in cmd and "--fail-fast" not in cmd: cmd += " --fail-fast" # add --bail for hardhat and truffle tests, to exit after first failure - elif "hardhat test" in cmd or "truffle test" and not "--bail" in cmd: + elif "hardhat test" in cmd or "truffle test" in cmd and "--bail" not in cmd: cmd += " --bail" start = time.time() + # starting new process - P = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) + P = subprocess.Popen( + [cmd], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + preexec_fn=os.setsid + ) try: # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: @@ -37,30 +51,34 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: if P.poll() is None: logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") # sends a SIGTERM signal to process group - bascially killing the process - os.killpg(os.getpgid(P.pid), signal.SIGTERM) + os.killpg(os.getpgid(P.pid), signal.SIGTERM) # Avoid any weird race conditions from grabbing the return code time.sleep(0.05) # indicates whether the command executed sucessfully or not r = P.returncode # if r is 0 then it is valid mutant because tests didn't fail - return True if r == 0 else False + return r == 0 -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: - with open(file, 'r') as filepath: +def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: # pylint: disable=too-many-arguments + """ + function to verify the validity of each patch + returns: valid or invalid patch + """ + with open(file, 'r', encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] # Write the modified content back to the file - with open(file, 'w') as filepath: + with open(file, 'w', encoding="utf-8") as filepath: filepath.write(replaced_content) - if(compile_generated_mutant(file, mappings)): - if(run_test_cmd(command, file, timeout)): + if compile_generated_mutant(file, mappings): + if run_test_cmd(command, file, timeout): create_mutant_file(file, index, generator_name) - logger.info(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + print(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) return True - + reset_file(file) if verbose: - logger.info(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) - return False \ No newline at end of file + print(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) + return False From f0bb9d35674c822e3397392a912ecef4a7f40d12 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Thu, 25 Jan 2024 19:22:08 -0500 Subject: [PATCH 316/338] Updated with formatting --- slither/tools/mutator/__main__.py | 90 +++++++++++------- slither/tools/mutator/mutators/AOR.py | 19 +++- slither/tools/mutator/mutators/ASOR.py | 29 ++++-- slither/tools/mutator/mutators/BOR.py | 17 +++- slither/tools/mutator/mutators/CR.py | 22 ++++- slither/tools/mutator/mutators/FHR.py | 21 +++-- slither/tools/mutator/mutators/LIR.py | 35 ++++--- slither/tools/mutator/mutators/LOR.py | 15 ++- slither/tools/mutator/mutators/MIA.py | 24 ++++- slither/tools/mutator/mutators/MVIE.py | 11 ++- slither/tools/mutator/mutators/MVIV.py | 7 +- slither/tools/mutator/mutators/MWA.py | 14 ++- slither/tools/mutator/mutators/ROR.py | 20 +++- slither/tools/mutator/mutators/RR.py | 23 ++++- slither/tools/mutator/mutators/SBR.py | 93 ++++++++++++------- slither/tools/mutator/mutators/UOR.py | 58 ++++++++++-- .../mutator/mutators/abstract_mutator.py | 48 +++++++--- .../tools/mutator/mutators/all_mutators.py | 30 +++--- slither/tools/mutator/utils/command_line.py | 3 +- slither/tools/mutator/utils/file_handling.py | 45 ++++++--- slither/tools/mutator/utils/patch.py | 11 ++- .../mutator/utils/testing_generated_mutant.py | 74 +++++++++------ 22 files changed, 504 insertions(+), 205 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 56582d6f5..f0b5c88bc 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -11,7 +11,11 @@ from slither.tools.mutator.mutators import all_mutators from slither.utils.colors import yellow, magenta from .mutators.abstract_mutator import AbstractMutator from .utils.command_line import output_mutators -from .utils.file_handling import transfer_and_delete, backup_source_file, get_sol_file_list +from .utils.file_handling import ( + transfer_and_delete, + backup_source_file, + get_sol_file_list, +) logging.basicConfig() logger = logging.getLogger("Slither-Mutate") @@ -23,6 +27,7 @@ logger.setLevel(logging.INFO) ################################################################################### ################################################################################### + def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. @@ -33,7 +38,9 @@ def parse_args() -> argparse.Namespace: usage="slither-mutate --test-cmd ", ) - parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") + parser.add_argument( + "codebase", help="Codebase to analyze (.sol file, project directory, ...)" + ) parser.add_argument( "--list-mutators", @@ -44,33 +51,22 @@ def parse_args() -> argparse.Namespace: ) # argument to add the test command - parser.add_argument( - "--test-cmd", - help="Command to run the tests for your project" - ) + parser.add_argument("--test-cmd", help="Command to run the tests for your project") # argument to add the test directory - containing all the tests - parser.add_argument( - "--test-dir", - help="Tests directory" - ) + parser.add_argument("--test-dir", help="Tests directory") # argument to ignore the interfaces, libraries - parser.add_argument( - "--ignore-dirs", - help="Directories to ignore" - ) + parser.add_argument("--ignore-dirs", help="Directories to ignore") # time out argument parser.add_argument( - "--timeout", - help="Set timeout for test command (by default 30 seconds)" + "--timeout", help="Set timeout for test command (by default 30 seconds)" ) # output directory argument parser.add_argument( - "--output-dir", - help="Name of output directory (by default 'mutation_campaign')" + "--output-dir", help="Name of output directory (by default 'mutation_campaign')" ) # to print just all the mutants @@ -110,14 +106,26 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() + def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator]]: detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] if mutators_list is not None: - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) and str(c.NAME) in mutators_list ] + detectors = [ + c + for c in detectors_ + if inspect.isclass(c) + and issubclass(c, AbstractMutator) + and str(c.NAME) in mutators_list + ] else: - detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator) ] + detectors = [ + c + for c in detectors_ + if inspect.isclass(c) and issubclass(c, AbstractMutator) + ] return detectors + class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods def __call__( self, parser: Any, *args: Any, **kwargs: Any @@ -126,6 +134,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods output_mutators(checks) parser.exit() + # endregion ################################################################################### ################################################################################### @@ -133,7 +142,10 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### ################################################################################### -def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too-many-locals + +def main() -> ( + None +): # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments @@ -151,7 +163,7 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- logger.info(magenta(f"Starting Mutation Campaign in '{args.codebase} \n")) if paths_to_ignore: - paths_to_ignore_list = paths_to_ignore.strip('][').split(',') + paths_to_ignore_list = paths_to_ignore.strip("][").split(",") logger.info(magenta(f"Ignored paths - {', '.join(paths_to_ignore_list)} \n")) else: paths_to_ignore_list = [] @@ -179,14 +191,14 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- for M in duplicate_list: if M.NAME == "RR": mutators_list.remove(M) - CR_RR_list.insert(0,M) + CR_RR_list.insert(0, M) elif M.NAME == "CR": mutators_list.remove(M) - CR_RR_list.insert(1,M) + CR_RR_list.insert(1, M) mutators_list = CR_RR_list + mutators_list - for filename in sol_file_list: # pylint: disable=too-many-nested-blocks - contract_name = os.path.split(filename)[1].split('.sol')[0] + for filename in sol_file_list: # pylint: disable=too-many-nested-blocks + contract_name = os.path.split(filename)[1].split(".sol")[0] # slither object sl = Slither(filename, **vars(args)) # create a backup files @@ -201,24 +213,34 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- # mutation try: for compilation_unit_of_main_file in sl.compilation_units: - contract_instance = '' + contract_instance = "" for contract in compilation_unit_of_main_file.contracts: if contract_names is not None and contract.name in contract_names: contract_instance = contract elif str(contract.name).lower() == contract_name.lower(): contract_instance = contract - if contract_instance == '': + if contract_instance == "": logger.error("Can't find the contract") else: for M in mutators_list: - m = M(compilation_unit_of_main_file, int(timeout), test_command, test_directory, contract_instance, solc_remappings, verbose, output_folder, dont_mutate_lines) + m = M( + compilation_unit_of_main_file, + int(timeout), + test_command, + test_directory, + contract_instance, + solc_remappings, + verbose, + output_folder, + dont_mutate_lines, + ) (count_valid, count_invalid, lines_list) = m.mutate() v_count += count_valid total_count += count_valid + count_invalid dont_mutate_lines = lines_list if not quick_flag: dont_mutate_lines = [] - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(e) except KeyboardInterrupt: @@ -230,7 +252,13 @@ def main() -> None: # pylint: disable=too-many-statements,too-many-branches,too- transfer_and_delete(files_dict) # output - logger.info(yellow(f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n")) + logger.info( + yellow( + f"Done mutating, '{filename}'. Valid mutant count: '{v_count}' and Total mutant count '{total_count}'.\n" + ) + ) logger.info(magenta(f"Finished Mutation Campaign in '{args.codebase}' \n")) + + # endregion diff --git a/slither/tools/mutator/mutators/AOR.py b/slither/tools/mutator/mutators/AOR.py index 00506a1bb..0bf0fb2a2 100644 --- a/slither/tools/mutator/mutators/AOR.py +++ b/slither/tools/mutator/mutators/AOR.py @@ -9,20 +9,23 @@ arithmetic_operators = [ BinaryType.DIVISION, BinaryType.MULTIPLICATION, BinaryType.SUBTRACTION, - BinaryType.MODULO + BinaryType.MODULO, ] + class AOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "AOR" HELP = "Arithmetic operator replacement" def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: ir_expression = node.expression - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue for ir in node.irs: if isinstance(ir, Binary) and ir.type in arithmetic_operators: @@ -39,5 +42,13 @@ class AOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/ASOR.py b/slither/tools/mutator/mutators/ASOR.py index 0e7452594..2ff403b38 100644 --- a/slither/tools/mutator/mutators/ASOR.py +++ b/slither/tools/mutator/mutators/ASOR.py @@ -1,7 +1,10 @@ from typing import Dict from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator -from slither.core.expressions.assignment_operation import AssignmentOperationType, AssignmentOperation +from slither.core.expressions.assignment_operation import ( + AssignmentOperationType, + AssignmentOperation, +) assignment_operators = [ AssignmentOperationType.ASSIGN_ADDITION, @@ -14,9 +17,10 @@ assignment_operators = [ AssignmentOperationType.ASSIGN_RIGHT_SHIFT, AssignmentOperationType.ASSIGN_MULTIPLICATION, AssignmentOperationType.ASSIGN_DIVISION, - AssignmentOperationType.ASSIGN_MODULO + AssignmentOperationType.ASSIGN_MODULO, ] + class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ASOR" HELP = "Assignment Operator Replacement" @@ -24,16 +28,21 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: - if isinstance(ir.expression, AssignmentOperation) and ir.expression.type in assignment_operators: + if ( + isinstance(ir.expression, AssignmentOperation) + and ir.expression.type in assignment_operators + ): if ir.expression.type == AssignmentOperationType.ASSIGN: continue alternative_ops = assignment_operators[:] try: alternative_ops.remove(ir.expression.type) - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue for op in alternative_ops: if op != ir.expression: @@ -44,5 +53,13 @@ class ASOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(str(ir.expression.type))[0]}{op}{old_str.split(str(ir.expression.type))[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/BOR.py b/slither/tools/mutator/mutators/BOR.py index 9f8ca2a11..a8720a4b6 100644 --- a/slither/tools/mutator/mutators/BOR.py +++ b/slither/tools/mutator/mutators/BOR.py @@ -8,9 +8,10 @@ bitwise_operators = [ BinaryType.OR, BinaryType.LEFT_SHIFT, BinaryType.RIGHT_SHIFT, - BinaryType.CARET + BinaryType.CARET, ] + class BOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "BOR" HELP = "Bitwise Operator Replacement" @@ -18,7 +19,9 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in bitwise_operators: @@ -33,5 +36,13 @@ class BOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]}{op.value}{old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/CR.py b/slither/tools/mutator/mutators/CR.py index 296028236..ebf93bf18 100644 --- a/slither/tools/mutator/mutators/CR.py +++ b/slither/tools/mutator/mutators/CR.py @@ -6,14 +6,20 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator class CR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "CR" - HELP = 'Comment Replacement' + HELP = "Comment Replacement" def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length @@ -21,5 +27,13 @@ class CR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: new_str = "//" + old_str - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/FHR.py b/slither/tools/mutator/mutators/FHR.py index 4560db4da..028c1916c 100644 --- a/slither/tools/mutator/mutators/FHR.py +++ b/slither/tools/mutator/mutators/FHR.py @@ -7,27 +7,36 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator function_header_replacements = [ "pure ==> view", "view ==> pure", - "(\s)(external|public|internal) ==> \\1private", - "(\s)(external|public) ==> \\1internal" + "(\\s)(external|public|internal) ==> \\1private", + "(\\s)(external|public) ==> \\1internal", ] + class FHR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "FHR" - HELP = 'Function Header Replacement' + HELP = "Function Header Replacement" def _mutate(self) -> Dict: result: Dict = {} for function in self.contract.functions_and_modifiers_declared: start = function.source_mapping.start - stop = start + function.source_mapping.content.find('{') + stop = start + function.source_mapping.content.find("{") old_str = self.in_file_str[start:stop] line_no = function.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in function_header_replacements: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index f9ef874cd..066a1fbb0 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -7,16 +7,19 @@ from slither.core.solidity_types import ElementaryType literal_replacements = [] + class LIR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LIR" HELP = "Literal Interger Replacement" - def _mutate(self) -> Dict: # pylint: disable=too-many-branches + def _mutate(self) -> Dict: # pylint: disable=too-many-branches result: Dict = {} variable: Variable # Create fault for state variables declaration - for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + variable + ) in self.contract.state_variables_declared: if variable.initialized: # Cannot remove the initialization of constant variables if variable.is_constant: @@ -24,12 +27,16 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods if isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): - literal_replacements.append(variable.type.min) # append data type min value - literal_replacements.append(variable.type.max) # append data type max value + literal_replacements.append( + variable.type.min + ) # append data type min value + literal_replacements.append( + variable.type.max + ) # append data type max value if str(variable.type).startswith("uint"): - literal_replacements.append('1') + literal_replacements.append("1") elif str(variable.type).startswith("uint"): - literal_replacements.append('-1') + literal_replacements.append("-1") # Get the string start = variable.source_mapping.start stop = start + variable.source_mapping.length @@ -37,7 +44,7 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods line_no = variable.node_initialization.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() + old_value = old_str[old_str.find("=") + 1 :].strip() if old_value != value: new_str = f"{old_str.split('=')[0]}= {value}" create_patch_with_line( @@ -47,26 +54,28 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop, old_str, new_str, - line_no[0] + line_no[0], ) - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: if variable.initialized and isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): literal_replacements.append(variable.type.min) literal_replacements.append(variable.type.max) if str(variable.type).startswith("uint"): - literal_replacements.append('1') + literal_replacements.append("1") elif str(variable.type).startswith("uint"): - literal_replacements.append('-1') + literal_replacements.append("-1") start = variable.source_mapping.start stop = start + variable.source_mapping.length old_str = self.in_file_str[start:stop] line_no = variable.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for new_value in literal_replacements: - old_value = old_str[old_str.find("=")+1:].strip() + old_value = old_str[old_str.find("=") + 1 :].strip() if old_value != new_value: new_str = f"{old_str.split('=')[0]}= {new_value}" create_patch_with_line( @@ -76,6 +85,6 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods stop, old_str, new_str, - line_no[0] + line_no[0], ) return result diff --git a/slither/tools/mutator/mutators/LOR.py b/slither/tools/mutator/mutators/LOR.py index 21837d81e..2d1535b1a 100644 --- a/slither/tools/mutator/mutators/LOR.py +++ b/slither/tools/mutator/mutators/LOR.py @@ -8,6 +8,7 @@ logical_operators = [ BinaryType.ANDAND, ] + class LOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "LOR" HELP = "Logical Operator Replacement" @@ -15,7 +16,9 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in logical_operators: @@ -31,5 +34,13 @@ class LOR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/MIA.py b/slither/tools/mutator/mutators/MIA.py index a10ce1f1d..f29569f63 100644 --- a/slither/tools/mutator/mutators/MIA.py +++ b/slither/tools/mutator/mutators/MIA.py @@ -4,6 +4,7 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + class MIA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MIA" HELP = '"if" construct around statement' @@ -22,10 +23,25 @@ class MIA(AbstractMutator): # pylint: disable=too-few-public-methods # Replace the expression with true and false for value in ["true", "false"]: new_str = value - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(UnaryOperationType.BANG) + "(" + old_str + ")" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 678b3b747..4d5f6205d 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -4,6 +4,7 @@ from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line + class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIE" HELP = "variable initialization using an expression" @@ -34,12 +35,14 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: - if variable.initialized and not isinstance(variable.expression, Literal): + if variable.initialized and not isinstance( + variable.expression, Literal + ): # Get the string start = variable.source_mapping.start stop = variable.expression.source_mapping.start @@ -54,6 +57,6 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MVIV.py b/slither/tools/mutator/mutators/MVIV.py index c82f132d7..f9e51c553 100644 --- a/slither/tools/mutator/mutators/MVIV.py +++ b/slither/tools/mutator/mutators/MVIV.py @@ -4,6 +4,7 @@ from slither.core.variables.variable import Variable from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.tools.mutator.utils.patch import create_patch_with_line + class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MVIV" HELP = "variable initialization using a value" @@ -34,7 +35,7 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) for function in self.contract.functions_and_modifiers_declared: @@ -53,6 +54,6 @@ class MVIV(AbstractMutator): # pylint: disable=too-few-public-methods stop + variable.expression.source_mapping.length, old_str, new_str, - line_no[0] + line_no[0], ) - return result \ No newline at end of file + return result diff --git a/slither/tools/mutator/mutators/MWA.py b/slither/tools/mutator/mutators/MWA.py index 20447290a..9682f10ca 100644 --- a/slither/tools/mutator/mutators/MWA.py +++ b/slither/tools/mutator/mutators/MWA.py @@ -4,6 +4,7 @@ from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.expressions.unary_operation import UnaryOperationType, UnaryOperation + class MWA(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "MWA" HELP = '"while" construct around statement' @@ -21,7 +22,14 @@ class MWA(AbstractMutator): # pylint: disable=too-few-public-methods line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: if not isinstance(node.expression, UnaryOperation): - new_str = str(UnaryOperationType.BANG) + '(' + old_str + ')' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = str(UnaryOperationType.BANG) + "(" + old_str + ")" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result - \ No newline at end of file diff --git a/slither/tools/mutator/mutators/ROR.py b/slither/tools/mutator/mutators/ROR.py index d59e7575a..9daae0663 100644 --- a/slither/tools/mutator/mutators/ROR.py +++ b/slither/tools/mutator/mutators/ROR.py @@ -12,6 +12,7 @@ relational_operators = [ BinaryType.NOT_EQUAL, ] + class ROR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "ROR" HELP = "Relational Operator Replacement" @@ -19,11 +20,16 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: for ir in node.irs: if isinstance(ir, Binary) and ir.type in relational_operators: - if str(ir.variable_left.type) != 'address' and str(ir.variable_right) != 'address': + if ( + str(ir.variable_left.type) != "address" + and str(ir.variable_right) != "address" + ): alternative_ops = relational_operators[:] alternative_ops.remove(ir.type) for op in alternative_ops: @@ -35,5 +41,13 @@ class ROR(AbstractMutator): # pylint: disable=too-few-public-methods if not line_no[0] in self.dont_mutate_line: # Replace the expression with true new_str = f"{old_str.split(ir.type.value)[0]} {op.value} {old_str.split(ir.type.value)[1]}" - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/RR.py b/slither/tools/mutator/mutators/RR.py index 6bfd644e0..e285d7a3f 100644 --- a/slither/tools/mutator/mutators/RR.py +++ b/slither/tools/mutator/mutators/RR.py @@ -3,23 +3,36 @@ from slither.core.cfg.node import NodeType from slither.tools.mutator.utils.patch import create_patch_with_line from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator + class RR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "RR" - HELP = 'Revert Replacement' + HELP = "Revert Replacement" def _mutate(self) -> Dict: result: Dict = {} for function in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: - if old_str != 'revert()': - new_str = 'revert()' - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if old_str != "revert()": + new_str = "revert()" + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index bbdc63194..770b57180 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -6,29 +6,29 @@ from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.core.variables.variable import Variable solidity_rules = [ - "abi\.encode\( ==> abi.encodePacked(", - "abi\.encodePacked\( ==> abi.encode(", - "\.call([({]) ==> .delegatecall\\1", - "\.call([({]) ==> .staticcall\\1", - "\.delegatecall([({]) ==> .call\\1", - "\.delegatecall([({]) ==> .staticcall\\1", - "\.staticcall([({]) ==> .delegatecall\\1", - "\.staticcall([({]) ==> .call\\1", + "abi\\.encode\\( ==> abi.encodePacked(", + "abi\\.encodePacked\\( ==> abi.encode(", + "\\.call([({]) ==> .delegatecall\\1", + "\\.call([({]) ==> .staticcall\\1", + "\\.delegatecall([({]) ==> .call\\1", + "\\.delegatecall([({]) ==> .staticcall\\1", + "\\.staticcall([({]) ==> .delegatecall\\1", + "\\.staticcall([({]) ==> .call\\1", "^now$ ==> 0", "block.timestamp ==> 0", "msg.value ==> 0", "msg.value ==> 1", - "(\s)(wei|gwei) ==> \\1ether", - "(\s)(ether|gwei) ==> \\1wei", - "(\s)(wei|ether) ==> \\1gwei", - "(\s)(minutes|days|hours|weeks) ==> \\1seconds", - "(\s)(seconds|days|hours|weeks) ==> \\1minutes", - "(\s)(seconds|minutes|hours|weeks) ==> \\1days", - "(\s)(seconds|minutes|days|weeks) ==> \\1hours", - "(\s)(seconds|minutes|days|hours) ==> \\1weeks", - "(\s)(memory) ==> \\1storage", - "(\s)(storage) ==> \\1memory", - "(\s)(constant) ==> \\1immutable", + "(\\s)(wei|gwei) ==> \\1ether", + "(\\s)(ether|gwei) ==> \\1wei", + "(\\s)(wei|ether) ==> \\1gwei", + "(\\s)(minutes|days|hours|weeks) ==> \\1seconds", + "(\\s)(seconds|days|hours|weeks) ==> \\1minutes", + "(\\s)(seconds|minutes|hours|weeks) ==> \\1days", + "(\\s)(seconds|minutes|days|weeks) ==> \\1hours", + "(\\s)(seconds|minutes|days|hours) ==> \\1weeks", + "(\\s)(memory) ==> \\1storage", + "(\\s)(storage) ==> \\1memory", + "(\\s)(constant) ==> \\1immutable", "addmod ==> mulmod", "mulmod ==> addmod", "msg.sender ==> tx.origin", @@ -40,45 +40,74 @@ solidity_rules = [ "(u?)int64 ==> \\1int32", "(u?)int128 ==> \\1int64", "(u?)int256 ==> \\1int128", - "while ==> if", + "while ==> if", ] + class SBR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "SBR" - HELP = 'Solidity Based Replacement' + HELP = "Solidity Based Replacement" def _mutate(self) -> Dict: result: Dict = {} variable: Variable - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: - if node.type not in (NodeType.ENTRYPOINT, NodeType.ENDIF, NodeType.ENDLOOP): + if node.type not in ( + NodeType.ENTRYPOINT, + NodeType.ENDIF, + NodeType.ENDLOOP, + ): # Get the string start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in solidity_rules: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = re.sub( + re.compile(left_value), right_value, old_str + ) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) - for variable in self.contract.state_variables_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + variable + ) in self.contract.state_variables_declared: node = variable.node_initialization if node: start = node.source_mapping.start stop = start + node.source_mapping.length - old_str = self.in_file_str[start:stop] + old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: for value in solidity_rules: - left_value = value.split(" ==> ")[0] + left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub(re.compile(left_value), right_value, old_str) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + new_str = re.sub( + re.compile(left_value), right_value, old_str + ) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/UOR.py b/slither/tools/mutator/mutators/UOR.py index b7e8c8156..f427c2fbf 100644 --- a/slither/tools/mutator/mutators/UOR.py +++ b/slither/tools/mutator/mutators/UOR.py @@ -8,9 +8,10 @@ unary_operators = [ UnaryOperationType.MINUSMINUS_PRE, UnaryOperationType.PLUSPLUS_POST, UnaryOperationType.MINUSMINUS_POST, - UnaryOperationType.MINUS_PRE + UnaryOperationType.MINUS_PRE, ] + class UOR(AbstractMutator): # pylint: disable=too-few-public-methods NAME = "UOR" HELP = "Unary Operator Replacement" @@ -18,33 +19,70 @@ class UOR(AbstractMutator): # pylint: disable=too-few-public-methods def _mutate(self) -> Dict: result: Dict = {} - for function in self.contract.functions_and_modifiers_declared: # pylint: disable=too-many-nested-blocks + for ( # pylint: disable=too-many-nested-blocks + function + ) in self.contract.functions_and_modifiers_declared: for node in function.nodes: try: ir_expression = node.expression - except: # pylint: disable=bare-except + except: # pylint: disable=bare-except continue start = node.source_mapping.start stop = start + node.source_mapping.length old_str = self.in_file_str[start:stop] line_no = node.source_mapping.lines if not line_no[0] in self.dont_mutate_line: - if isinstance(ir_expression, UnaryOperation) and ir_expression.type in unary_operators: + if ( + isinstance(ir_expression, UnaryOperation) + and ir_expression.type in unary_operators + ): for op in unary_operators: if not node.expression.is_prefix: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(variable_read) + str(op) - if new_str != old_str and str(op) != '-': - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if new_str != old_str and str(op) != "-": + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) new_str = str(op) + str(variable_read) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) else: if node.expression.type != op: variable_read = node.variables_read[0] new_str = str(op) + str(variable_read) - if new_str != old_str and str(op) != '-': - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + if new_str != old_str and str(op) != "-": + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) new_str = str(variable_read) + str(op) - create_patch_with_line(result, self.in_file, start, stop, old_str, new_str, line_no[0]) + create_patch_with_line( + result, + self.in_file, + start, + stop, + old_str, + new_str, + line_no[0], + ) return result diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index c2f15cd74..12c6b2298 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -9,17 +9,22 @@ from slither.core.declarations import Contract logger = logging.getLogger("Slither-Mutate") + class IncorrectMutatorInitialization(Exception): pass -class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods + +class AbstractMutator( + metaclass=abc.ABCMeta +): # pylint: disable=too-few-public-methods,too-many-instance-attributes NAME = "" HELP = "" VALID_MUTANTS_COUNT = 0 INVALID_MUTANTS_COUNT = 0 - def __init__( # pylint: disable=too-many-arguments - self, compilation_unit: SlitherCompilationUnit, + def __init__( # pylint: disable=too-many-arguments + self, + compilation_unit: SlitherCompilationUnit, timeout: int, testing_command: str, testing_directory: str, @@ -29,7 +34,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- output_folder: str, dont_mutate_line: List[int], rate: int = 10, - seed: Optional[int] = None + seed: Optional[int] = None, ) -> None: self.compilation_unit = compilation_unit self.slither = compilation_unit.core @@ -71,7 +76,7 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- (all_patches) = self._mutate() if "patches" not in all_patches: logger.debug("No patches found by %s", self.NAME) - return (0,0,self.dont_mutate_line) + return (0, 0, self.dont_mutate_line) for file in all_patches["patches"]: original_txt = self.slither.source_code[file].encode("utf8") @@ -80,21 +85,38 @@ class AbstractMutator(metaclass=abc.ABCMeta): # pylint: disable=too-few-public- logger.info(yellow(f"Mutating {file} with {self.NAME} \n")) for patch in patches: # test the patch - flag = test_patch(file, patch, self.test_command, self.VALID_MUTANTS_COUNT, self.NAME, self.timeout, self.solc_remappings, self.verbose) + flag = test_patch( + file, + patch, + self.test_command, + self.VALID_MUTANTS_COUNT, + self.NAME, + self.timeout, + self.solc_remappings, + self.verbose, + ) # if RR or CR and valid mutant, add line no. - if self.NAME in ('RR', 'CR') and flag: - self.dont_mutate_line.append(patch['line_number']) + if self.NAME in ("RR", "CR") and flag: + self.dont_mutate_line.append(patch["line_number"]) # count the valid and invalid mutants if not flag: self.INVALID_MUTANTS_COUNT += 1 continue self.VALID_MUTANTS_COUNT += 1 - patched_txt,_ = apply_patch(original_txt, patch, 0) - diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) + patched_txt, _ = apply_patch(original_txt, patch, 0) + diff = create_diff( + self.compilation_unit, original_txt, patched_txt, file + ) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") # add valid mutant patches to a output file - with open(self.output_folder + "/patches_file.txt", 'a') as patches_file: - patches_file.write(diff + '\n') - return (self.VALID_MUTANTS_COUNT, self.INVALID_MUTANTS_COUNT, self.dont_mutate_line) + with open( + self.output_folder + "/patches_file.txt", "a", encoding="utf8" + ) as patches_file: + patches_file.write(diff + "\n") + return ( + self.VALID_MUTANTS_COUNT, + self.INVALID_MUTANTS_COUNT, + self.dont_mutate_line, + ) diff --git a/slither/tools/mutator/mutators/all_mutators.py b/slither/tools/mutator/mutators/all_mutators.py index 852a8efc3..b02a2cc9b 100644 --- a/slither/tools/mutator/mutators/all_mutators.py +++ b/slither/tools/mutator/mutators/all_mutators.py @@ -1,16 +1,16 @@ # pylint: disable=unused-import -from slither.tools.mutator.mutators.MVIV import MVIV # severity low -from slither.tools.mutator.mutators.MVIE import MVIE # severity low -from slither.tools.mutator.mutators.LOR import LOR # severity medium -from slither.tools.mutator.mutators.UOR import UOR # severity medium -from slither.tools.mutator.mutators.SBR import SBR # severity medium -from slither.tools.mutator.mutators.AOR import AOR # severity medium -from slither.tools.mutator.mutators.BOR import BOR # severity medium -from slither.tools.mutator.mutators.ASOR import ASOR # severity medium -from slither.tools.mutator.mutators.MWA import MWA # severity medium -from slither.tools.mutator.mutators.LIR import LIR # severity medium -from slither.tools.mutator.mutators.FHR import FHR # severity medium -from slither.tools.mutator.mutators.MIA import MIA # severity medium -from slither.tools.mutator.mutators.ROR import ROR # severity medium -from slither.tools.mutator.mutators.RR import RR # severity high -from slither.tools.mutator.mutators.CR import CR # severity high +from slither.tools.mutator.mutators.MVIV import MVIV # severity low +from slither.tools.mutator.mutators.MVIE import MVIE # severity low +from slither.tools.mutator.mutators.LOR import LOR # severity medium +from slither.tools.mutator.mutators.UOR import UOR # severity medium +from slither.tools.mutator.mutators.SBR import SBR # severity medium +from slither.tools.mutator.mutators.AOR import AOR # severity medium +from slither.tools.mutator.mutators.BOR import BOR # severity medium +from slither.tools.mutator.mutators.ASOR import ASOR # severity medium +from slither.tools.mutator.mutators.MWA import MWA # severity medium +from slither.tools.mutator.mutators.LIR import LIR # severity medium +from slither.tools.mutator.mutators.FHR import FHR # severity medium +from slither.tools.mutator.mutators.MIA import MIA # severity medium +from slither.tools.mutator.mutators.ROR import ROR # severity medium +from slither.tools.mutator.mutators.RR import RR # severity high +from slither.tools.mutator.mutators.CR import CR # severity high diff --git a/slither/tools/mutator/utils/command_line.py b/slither/tools/mutator/utils/command_line.py index 358586688..79d705097 100644 --- a/slither/tools/mutator/utils/command_line.py +++ b/slither/tools/mutator/utils/command_line.py @@ -2,6 +2,7 @@ from typing import List, Type from slither.tools.mutator.mutators.abstract_mutator import AbstractMutator from slither.utils.myprettytable import MyPrettyTable + def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: mutators_list = [] for detector in mutators_classes: @@ -13,7 +14,7 @@ def output_mutators(mutators_classes: List[Type[AbstractMutator]]) -> None: # Sort by class mutators_list = sorted(mutators_list, key=lambda element: (element[0])) idx = 1 - for (argument, help_info) in mutators_list: + for argument, help_info in mutators_list: table.add_row([str(idx), argument, help_info]) idx = idx + 1 print(table) diff --git a/slither/tools/mutator/utils/file_handling.py b/slither/tools/mutator/utils/file_handling.py index d4474c310..ddb3efb50 100644 --- a/slither/tools/mutator/utils/file_handling.py +++ b/slither/tools/mutator/utils/file_handling.py @@ -6,6 +6,7 @@ logger = logging.getLogger("Slither-Mutate") duplicated_files = {} + def backup_source_file(source_code: Dict, output_folder: str) -> Dict: """ function to backup the source file @@ -18,21 +19,22 @@ def backup_source_file(source_code: Dict, output_folder: str) -> Dict: new_filename = f"{output_folder}/backup_{filename}" new_file_path = os.path.join(directory, new_filename) - with open(new_file_path, 'w', encoding="utf8") as new_file: + with open(new_file_path, "w", encoding="utf8") as new_file: new_file.write(content) duplicated_files[file_path] = new_file_path return duplicated_files + def transfer_and_delete(files_dict: Dict) -> None: """function to transfer the original content to the sol file after campaign""" try: files_dict_copy = files_dict.copy() for item, value in files_dict_copy.items(): - with open(value, 'r', encoding="utf8") as duplicated_file: + with open(value, "r", encoding="utf8") as duplicated_file: content = duplicated_file.read() - with open(item, 'w', encoding="utf8") as original_file: + with open(item, "w", encoding="utf8") as original_file: original_file.write(content) os.remove(value) @@ -40,47 +42,61 @@ def transfer_and_delete(files_dict: Dict) -> None: # delete elements from the global dict del duplicated_files[item] - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error transferring content: {e}") + def create_mutant_file(file: str, count: int, rule: str) -> None: """function to create new mutant file""" try: _, filename = os.path.split(file) # Read content from the duplicated file - with open(file, 'r', encoding="utf8") as source_file: + with open(file, "r", encoding="utf8") as source_file: content = source_file.read() # Write content to the original file - mutant_name = filename.split('.')[0] + mutant_name = filename.split(".")[0] # create folder for each contract os.makedirs("mutation_campaign/" + mutant_name, exist_ok=True) - with open("mutation_campaign/" + mutant_name + '/' + mutant_name + '_' + rule + '_' + str(count) + '.sol', 'w', encoding="utf8") as mutant_file: + with open( + "mutation_campaign/" + + mutant_name + + "/" + + mutant_name + + "_" + + rule + + "_" + + str(count) + + ".sol", + "w", + encoding="utf8", + ) as mutant_file: mutant_file.write(content) # reset the file - with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: + with open(duplicated_files[file], "r", encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w', encoding="utf8") as source_file: + with open(file, "w", encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error creating mutant: {e}") + def reset_file(file: str) -> None: """function to reset the file""" try: # directory, filename = os.path.split(file) # reset the file - with open(duplicated_files[file], 'r', encoding="utf8") as duplicated_file: + with open(duplicated_files[file], "r", encoding="utf8") as duplicated_file: duplicate_content = duplicated_file.read() - with open(file, 'w', encoding="utf8") as source_file: + with open(file, "w", encoding="utf8") as source_file: source_file.write(duplicate_content) - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except logger.error(f"Error resetting file: {e}") @@ -92,12 +108,13 @@ def get_sol_file_list(codebase: str, ignore_paths: List[str] | None) -> List[str sol_file_list = [] if ignore_paths is None: ignore_paths = [] + # if input is contract file if os.path.isfile(codebase): return [codebase] # if input is folder - elif os.path.isdir(codebase): + if os.path.isdir(codebase): directory = os.path.abspath(codebase) for file in os.listdir(directory): filename = os.path.join(directory, file) diff --git a/slither/tools/mutator/utils/patch.py b/slither/tools/mutator/utils/patch.py index e50f44612..54ff81e60 100644 --- a/slither/tools/mutator/utils/patch.py +++ b/slither/tools/mutator/utils/patch.py @@ -1,6 +1,7 @@ from typing import Dict, Union from collections import defaultdict + # pylint: disable=too-many-arguments def create_patch_with_line( result: Dict, @@ -9,13 +10,19 @@ def create_patch_with_line( end: int, old_str: Union[str, bytes], new_str: Union[str, bytes], - line_no: int + line_no: int, ) -> None: if isinstance(old_str, bytes): old_str = old_str.decode("utf8") if isinstance(new_str, bytes): new_str = new_str.decode("utf8") - p = {"start": start, "end": end, "old_string": old_str, "new_string": new_str, "line_number": line_no} + p = { + "start": start, + "end": end, + "old_string": old_str, + "new_string": new_str, + "line_number": line_no, + } if "patches" not in result: result["patches"] = defaultdict(list) if p not in result["patches"][file]: diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 5c75f0eb3..0e495f8ae 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -10,6 +10,7 @@ from slither.utils.colors import green, red logger = logging.getLogger("Slither-Mutate") + def compile_generated_mutant(file_path: str, mappings: str) -> bool: """ function to compile the generated mutant @@ -21,11 +22,14 @@ def compile_generated_mutant(file_path: str, mappings: str) -> bool: except: # pylint: disable=bare-except return False -def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: + +def run_test_cmd(cmd: str, test_dir: str, timeout: int) -> bool: """ function to run codebase tests returns: boolean whether the tests passed or not """ + # future purpose + _ = test_dir # add --fail-fast for foundry tests, to exit after first failure if "forge test" in cmd and "--fail-fast" not in cmd: cmd += " --fail-fast" @@ -36,49 +40,65 @@ def run_test_cmd(cmd: str, dir: str, timeout: int) -> bool: start = time.time() # starting new process - P = subprocess.Popen( - [cmd], - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - preexec_fn=os.setsid - ) - try: - # checking whether the process is completed or not within 30 seconds(default) - while P.poll() is None and (time.time() - start) < timeout: - time.sleep(0.05) - finally: - if P.poll() is None: - logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") - # sends a SIGTERM signal to process group - bascially killing the process - os.killpg(os.getpgid(P.pid), signal.SIGTERM) - # Avoid any weird race conditions from grabbing the return code - time.sleep(0.05) - # indicates whether the command executed sucessfully or not - r = P.returncode + with subprocess.Popen( + [cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) as P: + try: + # checking whether the process is completed or not within 30 seconds(default) + while P.poll() is None and (time.time() - start) < timeout: + time.sleep(0.05) + finally: + if P.poll() is None: + logger.error("HAD TO TERMINATE ANALYSIS (TIMEOUT OR EXCEPTION)") + # sends a SIGTERM signal to process group - bascially killing the process + os.killpg(os.getpgid(P.pid), signal.SIGTERM) + # Avoid any weird race conditions from grabbing the return code + time.sleep(0.05) + # indicates whether the command executed sucessfully or not + r = P.returncode # if r is 0 then it is valid mutant because tests didn't fail return r == 0 -def test_patch(file: str, patch: Dict, command: str, index: int, generator_name: str, timeout: int, mappings: str | None, verbose: bool) -> bool: # pylint: disable=too-many-arguments + +def test_patch( # pylint: disable=too-many-arguments + file: str, + patch: Dict, + command: str, + index: int, + generator_name: str, + timeout: int, + mappings: str | None, + verbose: bool, +) -> bool: """ function to verify the validity of each patch returns: valid or invalid patch """ - with open(file, 'r', encoding="utf-8") as filepath: + with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = content[:patch['start']] + patch['new_string'] + content[patch['end']:] + replaced_content = ( + content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] + ) # Write the modified content back to the file - with open(file, 'w', encoding="utf-8") as filepath: + with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) if compile_generated_mutant(file, mappings): if run_test_cmd(command, file, timeout): create_mutant_file(file, index, generator_name) - print(green(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n")) + print( + green( + f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> VALID\n" + ) + ) return True reset_file(file) if verbose: - print(red(f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n")) + print( + red( + f"String '{patch['old_string']}' replaced with '{patch['new_string']}' at line no. '{patch['line_number']}' ---> INVALID\n" + ) + ) return False From c5f1537022be4f5301c3f986d6fa1a94681db1a1 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 26 Jan 2024 11:37:05 -0500 Subject: [PATCH 317/338] Formatted mutators --- slither/tools/mutator/__main__.py | 18 ++++-------------- slither/tools/mutator/mutators/LIR.py | 8 ++------ slither/tools/mutator/mutators/MVIE.py | 4 +--- slither/tools/mutator/mutators/SBR.py | 8 ++------ .../tools/mutator/mutators/abstract_mutator.py | 4 +--- .../mutator/utils/testing_generated_mutant.py | 8 ++------ 6 files changed, 12 insertions(+), 38 deletions(-) diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index f0b5c88bc..5c13d7aea 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -38,9 +38,7 @@ def parse_args() -> argparse.Namespace: usage="slither-mutate --test-cmd ", ) - parser.add_argument( - "codebase", help="Codebase to analyze (.sol file, project directory, ...)" - ) + parser.add_argument("codebase", help="Codebase to analyze (.sol file, project directory, ...)") parser.add_argument( "--list-mutators", @@ -60,9 +58,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--ignore-dirs", help="Directories to ignore") # time out argument - parser.add_argument( - "--timeout", help="Set timeout for test command (by default 30 seconds)" - ) + parser.add_argument("--timeout", help="Set timeout for test command (by default 30 seconds)") # output directory argument parser.add_argument( @@ -118,11 +114,7 @@ def _get_mutators(mutators_list: List[str] | None) -> List[Type[AbstractMutator] and str(c.NAME) in mutators_list ] else: - detectors = [ - c - for c in detectors_ - if inspect.isclass(c) and issubclass(c, AbstractMutator) - ] + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator)] return detectors @@ -143,9 +135,7 @@ class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods ################################################################################### -def main() -> ( - None -): # pylint: disable=too-many-statements,too-many-branches,too-many-locals +def main() -> (None): # pylint: disable=too-many-statements,too-many-branches,too-many-locals args = parse_args() # arguments diff --git a/slither/tools/mutator/mutators/LIR.py b/slither/tools/mutator/mutators/LIR.py index 066a1fbb0..cc58cbae1 100644 --- a/slither/tools/mutator/mutators/LIR.py +++ b/slither/tools/mutator/mutators/LIR.py @@ -27,12 +27,8 @@ class LIR(AbstractMutator): # pylint: disable=too-few-public-methods if isinstance(variable.expression, Literal): if isinstance(variable.type, ElementaryType): - literal_replacements.append( - variable.type.min - ) # append data type min value - literal_replacements.append( - variable.type.max - ) # append data type max value + literal_replacements.append(variable.type.min) # append data type min value + literal_replacements.append(variable.type.max) # append data type max value if str(variable.type).startswith("uint"): literal_replacements.append("1") elif str(variable.type).startswith("uint"): diff --git a/slither/tools/mutator/mutators/MVIE.py b/slither/tools/mutator/mutators/MVIE.py index 4d5f6205d..ce51792ff 100644 --- a/slither/tools/mutator/mutators/MVIE.py +++ b/slither/tools/mutator/mutators/MVIE.py @@ -40,9 +40,7 @@ class MVIE(AbstractMutator): # pylint: disable=too-few-public-methods for function in self.contract.functions_and_modifiers_declared: for variable in function.local_variables: - if variable.initialized and not isinstance( - variable.expression, Literal - ): + if variable.initialized and not isinstance(variable.expression, Literal): # Get the string start = variable.source_mapping.start stop = variable.expression.source_mapping.start diff --git a/slither/tools/mutator/mutators/SBR.py b/slither/tools/mutator/mutators/SBR.py index 770b57180..efbda4877 100644 --- a/slither/tools/mutator/mutators/SBR.py +++ b/slither/tools/mutator/mutators/SBR.py @@ -71,9 +71,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub( - re.compile(left_value), right_value, old_str - ) + new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line( result, self.in_file, @@ -98,9 +96,7 @@ class SBR(AbstractMutator): # pylint: disable=too-few-public-methods left_value = value.split(" ==> ", maxsplit=1)[0] right_value = value.split(" ==> ")[1] if re.search(re.compile(left_value), old_str) is not None: - new_str = re.sub( - re.compile(left_value), right_value, old_str - ) + new_str = re.sub(re.compile(left_value), right_value, old_str) create_patch_with_line( result, self.in_file, diff --git a/slither/tools/mutator/mutators/abstract_mutator.py b/slither/tools/mutator/mutators/abstract_mutator.py index 12c6b2298..375af1e6f 100644 --- a/slither/tools/mutator/mutators/abstract_mutator.py +++ b/slither/tools/mutator/mutators/abstract_mutator.py @@ -104,9 +104,7 @@ class AbstractMutator( continue self.VALID_MUTANTS_COUNT += 1 patched_txt, _ = apply_patch(original_txt, patch, 0) - diff = create_diff( - self.compilation_unit, original_txt, patched_txt, file - ) + diff = create_diff(self.compilation_unit, original_txt, patched_txt, file) if not diff: logger.info(f"Impossible to generate patch; empty {patches}") diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 0e495f8ae..6104cdd8a 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -40,9 +40,7 @@ def run_test_cmd(cmd: str, test_dir: str, timeout: int) -> bool: start = time.time() # starting new process - with subprocess.Popen( - [cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) as P: + with subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as P: try: # checking whether the process is completed or not within 30 seconds(default) while P.poll() is None and (time.time() - start) < timeout: @@ -78,9 +76,7 @@ def test_patch( # pylint: disable=too-many-arguments with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = ( - content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] - ) + replaced_content = (content[: patch["start"]] + patch["new_string"] + content[patch["end"] :]) # Write the modified content back to the file with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) From 360509f8185d9915c98a66fefc0a9c91b30d8f84 Mon Sep 17 00:00:00 2001 From: Vishnuram Rajkumar Date: Fri, 26 Jan 2024 12:25:32 -0500 Subject: [PATCH 318/338] Formatted test_patch --- slither/tools/mutator/utils/testing_generated_mutant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/tools/mutator/utils/testing_generated_mutant.py b/slither/tools/mutator/utils/testing_generated_mutant.py index 6104cdd8a..4c51b7e5a 100644 --- a/slither/tools/mutator/utils/testing_generated_mutant.py +++ b/slither/tools/mutator/utils/testing_generated_mutant.py @@ -76,7 +76,7 @@ def test_patch( # pylint: disable=too-many-arguments with open(file, "r", encoding="utf-8") as filepath: content = filepath.read() # Perform the replacement based on the index values - replaced_content = (content[: patch["start"]] + patch["new_string"] + content[patch["end"] :]) + replaced_content = content[: patch["start"]] + patch["new_string"] + content[patch["end"] :] # Write the modified content back to the file with open(file, "w", encoding="utf-8") as filepath: filepath.write(replaced_content) From d6e40afc5ede852624693490111adbc94d13c030 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:41:54 -0600 Subject: [PATCH 319/338] Bump cachix/cachix-action from 12 to 14 (#2275) Bumps [cachix/cachix-action](https://github.com/cachix/cachix-action) from 12 to 14. - [Release notes](https://github.com/cachix/cachix-action/releases) - [Commits](https://github.com/cachix/cachix-action/compare/v12...v14) --- updated-dependencies: - dependency-name: cachix/cachix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a646bb42..9675b0d35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Set up cachix if: matrix.type == 'dapp' - uses: cachix/cachix-action@v12 + uses: cachix/cachix-action@v14 with: name: dapp From 340cbe09a6f58a8bfe48b37d93653c6a8d3293cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:42:07 -0600 Subject: [PATCH 320/338] Bump actions/upload-artifact from 3 to 4 (#2265) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e0ab4b543..dd63b5f47 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,7 +23,7 @@ jobs: python -m pip install build python -m build - name: Upload distributions - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: slither-dists path: dist/ From b83fa21b3e1fbfbc5b92b780960ba0de084d83c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:42:16 -0600 Subject: [PATCH 321/338] Bump actions/setup-python from 4 to 5 (#2259) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/black.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/doctor.yml | 2 +- .github/workflows/linter.yml | 2 +- .github/workflows/pip-audit.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/pylint.yml | 2 +- .github/workflows/test.yml | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 6017255b2..082333f2f 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9675b0d35..dbde09489 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e28c7136a..3d5eeed65 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.8' - run: pip install -e ".[doc]" diff --git a/.github/workflows/doctor.yml b/.github/workflows/doctor.yml index 0a0eb896d..555452871 100644 --- a/.github/workflows/doctor.yml +++ b/.github/workflows/doctor.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 5415b6d1b..45dc0d8c2 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -31,7 +31,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml index a98f6ab58..1c0a1d40a 100644 --- a/.github/workflows/pip-audit.yml +++ b/.github/workflows/pip-audit.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v4 - name: Install Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index dd63b5f47..7fc17804c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 7e990371f..091da2b96 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -29,7 +29,7 @@ jobs: fetch-depth: 0 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1660a25e9..68a32f80a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} cache: "pip" @@ -102,7 +102,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 From b292175837e9da2252d45ce8dd12d5769551f28d Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Mon, 29 Jan 2024 22:42:45 +0100 Subject: [PATCH 322/338] Detect also in modifiers (#2280) --- slither/detectors/statements/divide_before_multiply.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/detectors/statements/divide_before_multiply.py b/slither/detectors/statements/divide_before_multiply.py index 334da592c..1f6ccd87e 100644 --- a/slither/detectors/statements/divide_before_multiply.py +++ b/slither/detectors/statements/divide_before_multiply.py @@ -133,7 +133,7 @@ def detect_divide_before_multiply( results: List[Tuple[FunctionContract, List[Node]]] = [] # Loop for each function and modifier. - for function in contract.functions_declared: + for function in contract.functions_declared + contract.modifiers_declared: if not function.entry_point: continue From 28a921ec5dcdd25e21cf8b55903f23d4c097f631 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 29 Jan 2024 15:43:14 -0600 Subject: [PATCH 323/338] Fix/iterative update (#2206) * use iterative algo to prevent exceeding recursion limit * proper fixpoint --- slither/solc_parsing/declarations/function.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 59940ec1c..c1b94661d 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1106,11 +1106,13 @@ class FunctionSolc(CallerContextExpression): return node def _update_reachability(self, node: Node) -> None: - if node.is_reachable: - return - node.set_is_reachable(True) - for son in node.sons: - self._update_reachability(son) + worklist = [node] + while worklist: + current = worklist.pop() + # fix point + if not current.is_reachable: + current.set_is_reachable(True) + worklist.extend(current.sons) def _parse_cfg(self, cfg: Dict) -> None: From 4454b3e34af0f21498b2a721e4698013f1100b22 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 29 Jan 2024 15:44:25 -0600 Subject: [PATCH 324/338] fix: detect selfdestruct in internal calls (#2232) * fix: detect selfdestruct in internal calls * update snapshot --- slither/detectors/functions/suicidal.py | 2 +- ...etector_Suicidal_0_7_6_suicidal_sol__0.txt | 2 ++ .../test_data/suicidal/0.7.6/suicidal.sol | 8 ++++++++ .../suicidal/0.7.6/suicidal.sol-0.7.6.zip | Bin 1478 -> 1918 bytes 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py index 1f8cb52f9..f0af978ec 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -59,7 +59,7 @@ Bob calls `kill` and destructs the contract.""" if func.visibility not in ["public", "external"]: return False - calls = [c.name for c in func.internal_calls] + calls = [c.name for c in func.all_internal_calls()] if not ("suicide(address)" in calls or "selfdestruct(address)" in calls): return False diff --git a/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt index 4a784217d..99a6a0295 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_Suicidal_0_7_6_suicidal_sol__0.txt @@ -1,2 +1,4 @@ +C.i_am_a_backdoor2(address) (tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol#8-10) allows anyone to destruct the contract + C.i_am_a_backdoor() (tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol#4-6) allows anyone to destruct the contract diff --git a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol index 428c794d4..31b22d767 100644 --- a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol +++ b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol @@ -5,4 +5,12 @@ contract C{ selfdestruct(msg.sender); } + function i_am_a_backdoor2(address payable to) public{ + internal_selfdestruct(to); + } + + function internal_selfdestruct(address payable to) internal { + selfdestruct(to); + } + } diff --git a/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol-0.7.6.zip b/tests/e2e/detectors/test_data/suicidal/0.7.6/suicidal.sol-0.7.6.zip index 635092d49ecdda4ce21c4da09b8ba5b061e9a72e..ecd80364b245bf08dcb196de7486ec55a28df991 100644 GIT binary patch delta 1676 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 Date: Tue, 30 Jan 2024 08:36:21 -0600 Subject: [PATCH 325/338] Bump actions/deploy-pages from 3 to 4 (#2285) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 3 to 4. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3d5eeed65..4292d5f44 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -43,4 +43,4 @@ jobs: path: './html/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v3 + uses: actions/deploy-pages@v4 From 1bd279a0179fe1ec52f98f02e736cce3ed39c53c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:36:32 -0600 Subject: [PATCH 326/338] Bump cachix/install-nix-action from 24 to 25 (#2286) Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 24 to 25. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v24...v25) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbde09489..7972c96e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v24 + uses: cachix/install-nix-action@v25 - name: Set up cachix if: matrix.type == 'dapp' From 1b0d63b428ac7c66c70ae359fdfa220b445166a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 07:46:35 -0600 Subject: [PATCH 327/338] Bump sigstore/gh-action-sigstore-python from 2.1.0 to 2.1.1 (#2293) Bumps [sigstore/gh-action-sigstore-python](https://github.com/sigstore/gh-action-sigstore-python) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/sigstore/gh-action-sigstore-python/releases) - [Commits](https://github.com/sigstore/gh-action-sigstore-python/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: sigstore/gh-action-sigstore-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7fc17804c..72b002d1e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -47,7 +47,7 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.8.11 - name: sign - uses: sigstore/gh-action-sigstore-python@v2.1.0 + uses: sigstore/gh-action-sigstore-python@v2.1.1 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true From 9bf4d07b04480da90c1f2f023a0dd7d1e8dba21f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 07:50:04 -0600 Subject: [PATCH 328/338] Bump actions/upload-pages-artifact from 2 to 3 (#2294) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4292d5f44..0942afb6d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -37,7 +37,7 @@ jobs: - run: pip install -e ".[doc]" - run: pdoc -o html/ slither '!slither.tools' #TODO fix import errors on pdoc run - name: Upload artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: # Upload the doc path: './html/' From 6620bc926e7d8435256bf9bf0c774c22e0302241 Mon Sep 17 00:00:00 2001 From: Simone <79767264+smonicas@users.noreply.github.com> Date: Tue, 6 Feb 2024 14:54:04 +0100 Subject: [PATCH 329/338] Fix using for when used with "this" (#2224) --- slither/slithir/convert.py | 23 ++++++++++++++++++ tests/e2e/solc_parsing/test_ast_parsing.py | 1 + ...g-for-this-contract.sol-0.8.15-compact.zip | Bin 0 -> 2745 bytes ...-for-this-contract.sol-0.8.15-compact.json | 8 ++++++ .../test_data/using-for-this-contract.sol | 13 ++++++++++ 5 files changed, 45 insertions(+) create mode 100644 tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip create mode 100644 tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json create mode 100644 tests/e2e/solc_parsing/test_data/using-for-this-contract.sol diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 4411e3505..170df8cba 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -630,6 +630,17 @@ def propagate_types(ir: Operation, node: "Node"): # pylint: disable=too-many-lo if new_ir: return new_ir + # convert library function when used with "this" + if ( + isinstance(t, ElementaryType) + and t.name == "address" + and ir.destination.name == "this" + and UserDefinedType(node_function.contract) in using_for + ): + new_ir = convert_to_library_or_top_level(ir, node, using_for) + if new_ir: + return new_ir + if isinstance(t, UserDefinedType): # UserdefinedType t_type = t.type @@ -1564,6 +1575,18 @@ def convert_to_library_or_top_level( if new_ir: return new_ir + if ( + isinstance(t, ElementaryType) + and t.name == "address" + and ir.destination.name == "this" + and UserDefinedType(node.function.contract) in using_for + ): + new_ir = look_for_library_or_top_level( + contract, ir, using_for, UserDefinedType(node.function.contract) + ) + if new_ir: + return new_ir + return None diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py index bc57dc51b..e233fa993 100644 --- a/tests/e2e/solc_parsing/test_ast_parsing.py +++ b/tests/e2e/solc_parsing/test_ast_parsing.py @@ -448,6 +448,7 @@ ALL_TESTS = [ Test("using-for-functions-list-3-0.8.0.sol", ["0.8.15"]), Test("using-for-functions-list-4-0.8.0.sol", ["0.8.15"]), Test("using-for-global-0.8.0.sol", ["0.8.15"]), + Test("using-for-this-contract.sol", ["0.8.15"]), Test("library_event-0.8.16.sol", ["0.8.16"]), Test("top-level-struct-0.8.0.sol", ["0.8.0"]), Test("yul-top-level-0.8.0.sol", ["0.8.0"]), diff --git a/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip b/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip new file mode 100644 index 0000000000000000000000000000000000000000..6950666a479e8b3c138633675a65c8f101cd0069 GIT binary patch literal 2745 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json new file mode 100644 index 000000000..43eca2c9a --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json @@ -0,0 +1,8 @@ +{ + "Lib": { + "f(Hello)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n" + }, + "Hello": { + "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol new file mode 100644 index 000000000..33bbc74cd --- /dev/null +++ b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol @@ -0,0 +1,13 @@ +library Lib { + function f(Hello h) external { + + } +} +contract Hello { + using Lib for Hello; + + function test() external { + this.f(); + } +} + From e876d61fd51fac747fd22f906026037161f7d24f Mon Sep 17 00:00:00 2001 From: Matt Solomon Date: Thu, 8 Feb 2024 13:27:50 -0800 Subject: [PATCH 330/338] fix: broken doc links (#2299) * fix: broken doc links * style: black --- README.md | 6 +++--- slither/detectors/assembly/incorrect_return.py | 4 +++- slither/detectors/assembly/return_instead_of_leave.py | 2 +- tests/e2e/compilation/test_resolution.py | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 37f678d7a..769ac58aa 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Slither - Read the Docs](https://img.shields.io/badge/Slither-Read_the_Docs-2ea44f)](https://crytic.github.io/slither/slither.html) [![Slither - Wiki](https://img.shields.io/badge/Slither-Wiki-2ea44f)](https://github.com/crytic/slither/wiki/SlithIR) -> Join the Empire Hacking Slack +> Join the Empire Hacking Slack > > [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/) > > - Discussions and Support @@ -131,10 +131,10 @@ Num | Detector | What it Detects | Impact | Confidence 20 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium 21 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium 22 | `incorrect-exp` | [Incorrect exponentiation](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation) | High | Medium -23 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +23 | `incorrect-return` | [If a `return` is incorrectly used in assembly mode.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly) | High | Medium 24 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium 25 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium -26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) | High | Medium +26 | `return-leave` | [If a `return` is used instead of a `leave`.](https://github.com/crytic/slither/wiki/Detector-Documentation#return-instead-of-leave-in-assembly) | High | Medium 27 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium 28 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium 29 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium diff --git a/slither/detectors/assembly/incorrect_return.py b/slither/detectors/assembly/incorrect_return.py index f5f0a98d9..bd5a6d844 100644 --- a/slither/detectors/assembly/incorrect_return.py +++ b/slither/detectors/assembly/incorrect_return.py @@ -39,7 +39,9 @@ class IncorrectReturn(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.MEDIUM - WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + WIKI = ( + "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-return-in-assembly" + ) WIKI_TITLE = "Incorrect return in assembly" WIKI_DESCRIPTION = "Detect if `return` in an assembly block halts unexpectedly the execution." diff --git a/slither/detectors/assembly/return_instead_of_leave.py b/slither/detectors/assembly/return_instead_of_leave.py index a1591d834..a1ad9c87e 100644 --- a/slither/detectors/assembly/return_instead_of_leave.py +++ b/slither/detectors/assembly/return_instead_of_leave.py @@ -20,7 +20,7 @@ class ReturnInsteadOfLeave(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.MEDIUM - WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return" + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#return-instead-of-leave-in-assembly" WIKI_TITLE = "Return instead of leave in assembly" WIKI_DESCRIPTION = "Detect if a `return` is used where a `leave` should be used." diff --git a/tests/e2e/compilation/test_resolution.py b/tests/e2e/compilation/test_resolution.py index af7cbe2c7..c3290624b 100644 --- a/tests/e2e/compilation/test_resolution.py +++ b/tests/e2e/compilation/test_resolution.py @@ -57,6 +57,6 @@ def test_contract_function_parameter(solc_binary_path) -> None: function = contract.functions[0] parameters = function.parameters - assert (parameters[0].name == 'param1') - assert (parameters[1].name == '') - assert (parameters[2].name == 'param3') + assert parameters[0].name == "param1" + assert parameters[1].name == "" + assert parameters[2].name == "param3" From 9fd6128b94ef041b8c780ef9aa550693b2ebcec0 Mon Sep 17 00:00:00 2001 From: unknown <951161604@qq.com> Date: Thu, 15 Feb 2024 23:18:28 +0800 Subject: [PATCH 331/338] Changes to be committed: modified: examples/scripts/possible_paths.py --- examples/scripts/possible_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/scripts/possible_paths.py b/examples/scripts/possible_paths.py index 06b68c2bc..6f83e13f0 100644 --- a/examples/scripts/possible_paths.py +++ b/examples/scripts/possible_paths.py @@ -19,7 +19,7 @@ def resolve_function(contract_name, function_name): contract = contracts[0] # Obtain the target function target_function = next( - (function for function in contract.functions if function.name == function_name), None + (function for function in contract.functions_declared if function.name == function_name), None ) # Verify we have resolved the function specified. From b66b3e091f3352c975937972f767ff5ee86f3fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:26:28 -0300 Subject: [PATCH 332/338] slither: utils: respect colorization state when printing tables Closes #2229 --- slither/utils/myprettytable.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/slither/utils/myprettytable.py b/slither/utils/myprettytable.py index d67f570c0..b33fb9c5f 100644 --- a/slither/utils/myprettytable.py +++ b/slither/utils/myprettytable.py @@ -1,7 +1,10 @@ from typing import List, Dict, Union +from prettytable import PrettyTable from prettytable.colortable import ColorTable, Themes +from slither.utils.colors import Colors + class MyPrettyTable: def __init__(self, field_names: List[str], pretty_align: bool = True): # TODO: True by default? @@ -19,8 +22,12 @@ class MyPrettyTable: def add_row(self, row: List[Union[str, List[str]]]) -> None: self._rows.append(row) - def to_pretty_table(self) -> ColorTable: - table = ColorTable(self._field_names, theme=Themes.OCEAN) + def to_pretty_table(self) -> PrettyTable: + if Colors.COLORIZATION_ENABLED: + table = ColorTable(self._field_names, theme=Themes.OCEAN) + else: + table = PrettyTable(self._field_names) + for row in self._rows: table.add_row(row) if len(self._options["set_alignment"]): From 3eebf49c1a3ec54c74ddeb1662df1ae6f9ddb05e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 22:41:00 +0000 Subject: [PATCH 333/338] Bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 72b002d1e..234e2eb05 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -38,7 +38,7 @@ jobs: - build-release steps: - name: fetch dists - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: slither-dists path: dist/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68a32f80a..d67721841 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -109,7 +109,7 @@ jobs: - run: pip install coverage[toml] - name: download coverage data - uses: actions/download-artifact@v3.0.2 + uses: actions/download-artifact@v4 with: name: coverage-data From b107e9e22cd79acce47c02a4aab70144e2e0186a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:37:30 -0300 Subject: [PATCH 334/338] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... --- .github/actions/upload-coverage/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml index ac620c8e6..789509080 100644 --- a/.github/actions/upload-coverage/action.yml +++ b/.github/actions/upload-coverage/action.yml @@ -21,7 +21,7 @@ runs: fi id: coverage-uuid shell: bash - - uses: actions/upload-artifact@v3.1.0 + - uses: actions/upload-artifact@v4 with: name: coverage-data path: | From 4a6920a2b5cfcce5b9f643e96e30280081e3028d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 16:41:47 -0300 Subject: [PATCH 335/338] ci: test: adjust to new artifact merging behavior --- .github/actions/upload-coverage/action.yml | 4 ++-- .github/workflows/test.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml index 789509080..02fb82f65 100644 --- a/.github/actions/upload-coverage/action.yml +++ b/.github/actions/upload-coverage/action.yml @@ -15,7 +15,7 @@ runs: # This method has the limitation of 1 coverage file per run, limiting some coverage between online/offline tests. - run: | COVERAGE_UUID=$(python3 -c "import uuid; print(uuid.uuid4())") - echo "COVERAGE_UUID=${COVERAGE_UUID}" >> $GITHUB_OUTPUT + echo "COVERAGE_UUID=${COVERAGE_UUID}" >> "$GITHUB_OUTPUT" if [ -f .coverage ]; then mv .coverage .coverage.${COVERAGE_UUID} fi @@ -23,7 +23,7 @@ runs: shell: bash - uses: actions/upload-artifact@v4 with: - name: coverage-data + name: coverage-data-${{ steps.coverage-uuid.outputs.COVERAGE_UUID }} path: | .coverage.* *.lcov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d67721841..f91243cc7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -111,7 +111,8 @@ jobs: - name: download coverage data uses: actions/download-artifact@v4 with: - name: coverage-data + pattern: coverage-data-* + merge-multiple: true - name: combine coverage data id: combinecoverage From 261182f34061caefe032170fa8ad6a42522f3d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 21:44:01 -0300 Subject: [PATCH 336/338] tools: properties: correct tool description and usage Closes #568 --- slither/tools/properties/__main__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slither/tools/properties/__main__.py b/slither/tools/properties/__main__.py index 10837bb4b..b5e5c911a 100644 --- a/slither/tools/properties/__main__.py +++ b/slither/tools/properties/__main__.py @@ -68,13 +68,13 @@ def parse_args() -> argparse.Namespace: :return: Returns the arguments for the program. """ parser = argparse.ArgumentParser( - description="Demo", - usage="slither-demo filename", + description="Generates code properties (e.g., invariants) that can be tested with unit tests or Echidna, entirely automatically.", + usage="slither-prop filename", formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( - "filename", help="The filename of the contract or truffle directory to analyze." + "filename", help="The filename of the contract or project directory to analyze." ) parser.add_argument("--contract", help="The targeted contract.") From 9996e4e56e2dbe7273bf213f28b56cbd9bf20397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 16 Feb 2024 22:03:49 -0300 Subject: [PATCH 337/338] tools: documentation: correct tool description --- slither/tools/documentation/__main__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/slither/tools/documentation/__main__.py b/slither/tools/documentation/__main__.py index 39b1eacda..0244dd6c6 100644 --- a/slither/tools/documentation/__main__.py +++ b/slither/tools/documentation/__main__.py @@ -21,7 +21,10 @@ def parse_args() -> argparse.Namespace: Parse the underlying arguments for the program. :return: Returns the arguments for the program. """ - parser = argparse.ArgumentParser(description="Demo", usage="slither-documentation filename") + parser = argparse.ArgumentParser( + description="Auto-generate NatSpec documentation for every function using OpenAI Codex.", + usage="slither-documentation filename", + ) parser.add_argument("project", help="The target directory/Solidity file.") From f2f7598ccf2559a64ae8dd8f79ced7ae9e174c3d Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Sat, 17 Feb 2024 09:05:15 -0600 Subject: [PATCH 338/338] fmt --- examples/scripts/possible_paths.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/scripts/possible_paths.py b/examples/scripts/possible_paths.py index 6f83e13f0..2057782a4 100644 --- a/examples/scripts/possible_paths.py +++ b/examples/scripts/possible_paths.py @@ -19,7 +19,8 @@ def resolve_function(contract_name, function_name): contract = contracts[0] # Obtain the target function target_function = next( - (function for function in contract.functions_declared if function.name == function_name), None + (function for function in contract.functions_declared if function.name == function_name), + None, ) # Verify we have resolved the function specified.