diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index afead53368..7d2ba83d0d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -67,11 +67,11 @@ jobs:
 
       - name: Set up nix
         if: matrix.type == 'dapp'
-        uses: cachix/install-nix-action@v26
+        uses: cachix/install-nix-action@V27
 
       - name: Set up cachix
         if: matrix.type == 'dapp'
-        uses: cachix/cachix-action@v14
+        uses: cachix/cachix-action@v15
         with:
           name: dapp
 
diff --git a/.gitignore b/.gitignore
index 4441c03d18..a895c22ee1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,4 +114,7 @@ test_artifacts/
 crytic-export/
 
 # Auto-generated Github pages docs
-docs/
\ No newline at end of file
+docs/
+
+# slither.db.json 
+slither.db.json
diff --git a/README.md b/README.md
index 558aa72229..d7f0fd3e3d 100644
--- a/README.md
+++ b/README.md
@@ -302,5 +302,12 @@ Title | Usage | Authors | Venue | Code
 [Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) | -
 [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc)
 [Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification)
+[Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022  | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement)
+[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | -
+[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | -
+[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | -
+[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | -
+[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | -
+Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no PDF in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv)
 
 If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/).
diff --git a/scripts/ci_test.sh b/scripts/ci_test.sh
deleted file mode 100755
index 6696a4e890..0000000000
--- a/scripts/ci_test.sh
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env bash
-
-### Test Detectors
-
-DIR="$(cd "$(dirname "$0")" && pwd)"
-
-CURRENT_PATH=$(pwd)
-TRAVIS_PATH='/home/travis/build/crytic/slither'
-
-# test_slither file.sol detectors
-test_slither(){
-
-    expected="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json"
-
-    # run slither detector on input file and save output as json
-    if ! slither "$1" --solc-disable-warnings --detect "$2" --json "$DIR/tmp-test.json";
-    then
-        echo "Slither crashed"
-        exit 255
-    fi
-
-    if [ ! -f "$DIR/tmp-test.json" ]; then
-        echo ""
-        echo "Missing generated file"
-        echo ""
-        exit 1
-    fi
-    sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
-    result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
-
-    rm "$DIR/tmp-test.json"
-    if [ "$result" != "{}" ]; then
-      echo ""
-      echo "failed test of file: $1, detector: $2"
-      echo ""
-      echo "$result"
-      echo ""
-      exit 1
-    fi
-
-    # run slither detector on input file and save output as json
-    if ! slither "$1" --solc-disable-warnings --detect "$2" --legacy-ast --json "$DIR/tmp-test.json";
-    then
-        echo "Slither crashed"
-        exit 255
-    fi
-
-    if [ ! -f "$DIR/tmp-test.json" ]; then
-        echo ""
-        echo "Missing generated file"
-        echo ""
-        exit 1
-    fi
-
-    sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i
-    result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json")
-
-    rm "$DIR/tmp-test.json"
-    if [ "$result" != "{}" ]; then
-      echo ""
-      echo "failed test of file: $1, detector: $2"
-      echo ""
-      echo "$result"
-      echo ""
-      exit 1
-    fi
-}
-
-# generate_expected_json file.sol detectors
-generate_expected_json(){
-    # generate output filename
-    # e.g. file: uninitialized.sol detector: uninitialized-state
-    # ---> uninitialized.uninitialized-state.json
-    output_filename="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json"
-    output_filename_txt="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.txt"
-
-    # run slither detector on input file and save output as json
-    slither "$1" --solc-disable-warnings --detect "$2" --json "$output_filename" > "$output_filename_txt" 2>&1
-
-
-    sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename" -i
-    sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
-}
-
diff --git a/scripts/json_diff.py b/scripts/json_diff.py
deleted file mode 100644
index 9422f6b8df..0000000000
--- a/scripts/json_diff.py
+++ /dev/null
@@ -1,27 +0,0 @@
-import sys
-import json
-from pprint import pprint
-from deepdiff import DeepDiff  # pip install deepdiff
-
-
-if len(sys.argv) != 3:
-    print("Usage: python json_diff.py 1.json 2.json")
-    sys.exit(-1)
-
-with open(sys.argv[1], encoding="utf8") as f:
-    d1 = json.load(f)
-
-with open(sys.argv[2], encoding="utf8") as f:
-    d2 = json.load(f)
-
-
-# Remove description field to allow non deterministic print
-for elem in d1:
-    if "description" in elem:
-        del elem["description"]
-for elem in d2:
-    if "description" in elem:
-        del elem["description"]
-
-
-pprint(DeepDiff(d1, d2, ignore_order=True, verbose_level=2))
diff --git a/slither/__main__.py b/slither/__main__.py
index 4fc83a11e5..886d392c0d 100644
--- a/slither/__main__.py
+++ b/slither/__main__.py
@@ -11,7 +11,7 @@
 import sys
 import traceback
 from importlib import metadata
-from typing import Tuple, Optional, List, Dict, Type, Union, Any, Sequence
+from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
 
 
 from crytic_compile import cryticparser, CryticCompile, InvalidCompilation
@@ -211,44 +211,51 @@ def choose_detectors(
 
     if args.detectors_to_run == "all":
         detectors_to_run = all_detector_classes
-        if args.detectors_to_exclude:
-            detectors_excluded = args.detectors_to_exclude.split(",")
-            for detector in detectors:
-                if detector in detectors_excluded:
-                    detectors_to_run.remove(detectors[detector])
     else:
-        for detector in args.detectors_to_run.split(","):
-            if detector in detectors:
-                detectors_to_run.append(detectors[detector])
-            else:
-                raise ValueError(f"Error: {detector} is not a detector")
-        detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT)
+        detectors_to_run = __include_detectors(
+            set(detectors_to_run), args.detectors_to_run, detectors
+        )
         return detectors_to_run
 
-    if args.exclude_optimization:
-        detectors_to_run = [
-            d for d in detectors_to_run if d.IMPACT != DetectorClassification.OPTIMIZATION
-        ]
+    classification_map = {
+        DetectorClassification.HIGH: args.exclude_high,
+        DetectorClassification.MEDIUM: args.exclude_medium,
+        DetectorClassification.LOW: args.exclude_low,
+        DetectorClassification.INFORMATIONAL: args.exclude_informational,
+        DetectorClassification.OPTIMIZATION: args.exclude_optimization,
+    }
+    excluded_classification = [
+        classification for classification, included in classification_map.items() if included
+    ]
+    detectors_to_run = [d for d in detectors_to_run if d.IMPACT not in excluded_classification]
 
-    if args.exclude_informational:
-        detectors_to_run = [
-            d for d in detectors_to_run if d.IMPACT != DetectorClassification.INFORMATIONAL
-        ]
-    if args.exclude_low:
-        detectors_to_run = [d for d in detectors_to_run if d.IMPACT != DetectorClassification.LOW]
-    if args.exclude_medium:
-        detectors_to_run = [
-            d for d in detectors_to_run if d.IMPACT != DetectorClassification.MEDIUM
-        ]
-    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 = [
             d for d in detectors_to_run if d.ARGUMENT not in args.detectors_to_exclude
         ]
 
-    detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT)
+    if args.detectors_to_include:
+        detectors_to_run = __include_detectors(
+            set(detectors_to_run), args.detectors_to_include, detectors
+        )
+
+    return detectors_to_run
+
+
+def __include_detectors(
+    detectors_to_run: Set[Type[AbstractDetector]],
+    detectors_to_include: str,
+    detectors: Dict[str, Type[AbstractDetector]],
+) -> List[Type[AbstractDetector]]:
+    include_detectors = detectors_to_include.split(",")
+
+    for detector in include_detectors:
+        if detector in detectors:
+            detectors_to_run.add(detectors[detector])
+        else:
+            raise ValueError(f"Error: {detector} is not a detector")
 
+    detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT)
     return detectors_to_run
 
 
@@ -341,6 +348,14 @@ def parse_args(
         default=defaults_flag_in_config["printers_to_run"],
     )
 
+    group_printer.add_argument(
+        "--include-interfaces",
+        help="Include interfaces from inheritance-graph printer",
+        action="store_true",
+        dest="include_interfaces",
+        default=False,
+    )
+
     group_detector.add_argument(
         "--list-detectors",
         help="List available detectors",
@@ -407,6 +422,14 @@ def parse_args(
         default=defaults_flag_in_config["exclude_high"],
     )
 
+    group_detector.add_argument(
+        "--include-detectors",
+        help="Comma-separated list of detectors that should be included",
+        action="store",
+        dest="detectors_to_include",
+        default=defaults_flag_in_config["detectors_to_include"],
+    )
+
     fail_on_group = group_detector.add_mutually_exclusive_group()
     fail_on_group.add_argument(
         "--fail-pedantic",
diff --git a/slither/analyses/evm/convert.py b/slither/analyses/evm/convert.py
index 5e8c4a1280..fe294798e5 100644
--- a/slither/analyses/evm/convert.py
+++ b/slither/analyses/evm/convert.py
@@ -178,15 +178,14 @@ def generate_source_to_evm_ins_mapping(evm_instructions, srcmap_runtime, slither
         # In order to compress these source mappings especially for bytecode, the following rules are used:
         # If a field is empty, the value of the preceding element is used.
         # If a : is missing, all following fields are considered empty.
-
         mapping_item = mapping.split(":")
         mapping_item += prev_mapping[len(mapping_item) :]
 
         for i, _ in enumerate(mapping_item):
             if mapping_item[i] == "":
-                mapping_item[i] = int(prev_mapping[i])
+                mapping_item[i] = prev_mapping[i]
 
-        offset, _length, file_id, *_ = mapping_item
+        offset, _, file_id, *_ = mapping_item
         prev_mapping = mapping_item
 
         if file_id == "-1":
@@ -194,8 +193,7 @@ def generate_source_to_evm_ins_mapping(evm_instructions, srcmap_runtime, slither
             # See https://github.com/ethereum/solidity/issues/6119#issuecomment-467797635
             continue
 
-        offset = int(offset)
-        line_number = file_source[0:offset].count("\n".encode("utf-8")) + 1
+        line_number = file_source[0 : int(offset)].count("\n".encode("utf-8")) + 1
 
         # Append evm instructions to the corresponding source line number
         # Note: Some evm instructions in mapping are not necessarily in program execution order
diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py
index fe617b3313..3f97a33ed2 100644
--- a/slither/core/declarations/contract.py
+++ b/slither/core/declarations/contract.py
@@ -1372,8 +1372,6 @@ def update_read_write_using_ssa(self) -> None:
     def is_upgradeable(self) -> bool:
         if self._is_upgradeable is None:
             self._is_upgradeable = False
-            if self.is_upgradeable_proxy:
-                return False
             initializable = self.file_scope.get_contract_from_name("Initializable")
             if initializable:
                 if initializable in self.inheritance:
diff --git a/slither/core/declarations/custom_error.py b/slither/core/declarations/custom_error.py
index 234873eaca..6e2cf142ff 100644
--- a/slither/core/declarations/custom_error.py
+++ b/slither/core/declarations/custom_error.py
@@ -17,6 +17,7 @@ def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None:
 
         self._solidity_signature: Optional[str] = None
         self._full_name: Optional[str] = None
+        self._pattern = "error"
 
     @property
     def name(self) -> str:
diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py
index be215bd1f2..6e8968dfb2 100644
--- a/slither/core/declarations/function.py
+++ b/slither/core/declarations/function.py
@@ -94,14 +94,11 @@ class FunctionType(Enum):
 
 def _filter_state_variables_written(expressions: List["Expression"]):
     ret = []
+
     for expression in expressions:
-        if isinstance(expression, Identifier):
-            ret.append(expression)
-        if isinstance(expression, UnaryOperation):
-            ret.append(expression.expression)
-        if isinstance(expression, MemberAccess):
+        if isinstance(expression, (Identifier, UnaryOperation, MemberAccess)):
             ret.append(expression.expression)
-        if isinstance(expression, IndexAccess):
+        elif isinstance(expression, IndexAccess):
             ret.append(expression.expression_left)
     return ret
 
diff --git a/slither/core/declarations/import_directive.py b/slither/core/declarations/import_directive.py
index 19ea2cff96..440b09e9cd 100644
--- a/slither/core/declarations/import_directive.py
+++ b/slither/core/declarations/import_directive.py
@@ -16,6 +16,8 @@ def __init__(self, filename: Path, scope: "FileScope") -> None:
         # Map local name -> original name
         self.renaming: Dict[str, str] = {}
 
+        self._pattern = "import"
+
     @property
     def filename(self) -> str:
         """
diff --git a/slither/core/declarations/pragma_directive.py b/slither/core/declarations/pragma_directive.py
index cd790d5a47..90c1da2ddf 100644
--- a/slither/core/declarations/pragma_directive.py
+++ b/slither/core/declarations/pragma_directive.py
@@ -11,6 +11,7 @@ def __init__(self, directive: List[str], scope: "FileScope") -> None:
         super().__init__()
         self._directive = directive
         self.scope: "FileScope" = scope
+        self._pattern = "pragma"
 
     @property
     def directive(self) -> List[str]:
diff --git a/slither/core/expressions/identifier.py b/slither/core/expressions/identifier.py
index 5cd29a9f5d..493620ab18 100644
--- a/slither/core/expressions/identifier.py
+++ b/slither/core/expressions/identifier.py
@@ -78,3 +78,6 @@ def value(
 
     def __str__(self) -> str:
         return str(self._value)
+
+    def expression(self):
+        return self
diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py
index 8eca260fac..1206e564bc 100644
--- a/slither/core/slither_core.py
+++ b/slither/core/slither_core.py
@@ -524,6 +524,7 @@ def write_results_to_hide(self) -> None:
 
     def save_results_to_hide(self, results: List[Dict]) -> None:
         self._results_to_hide += results
+        self.write_results_to_hide()
 
     def add_path_to_filter(self, path: str):
         """
diff --git a/slither/core/solidity_types/elementary_type.py b/slither/core/solidity_types/elementary_type.py
index a9f45c8d81..61729b06a2 100644
--- a/slither/core/solidity_types/elementary_type.py
+++ b/slither/core/solidity_types/elementary_type.py
@@ -225,4 +225,4 @@ def __eq__(self, other: Any) -> bool:
         return self.type == other.type
 
     def __hash__(self) -> int:
-        return hash(str(self))
+        return hash(self._type)
diff --git a/slither/core/solidity_types/type_alias.py b/slither/core/solidity_types/type_alias.py
index ead9b5394f..c22cd257ef 100644
--- a/slither/core/solidity_types/type_alias.py
+++ b/slither/core/solidity_types/type_alias.py
@@ -15,6 +15,7 @@ def __init__(self, underlying_type: ElementaryType, name: str) -> None:
         super().__init__()
         self.name = name
         self.underlying_type = underlying_type
+        self._pattern = "type"
 
     @property
     def type(self) -> ElementaryType:
diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py
index fceab78559..8dda25a241 100644
--- a/slither/core/source_mapping/source_mapping.py
+++ b/slither/core/source_mapping/source_mapping.py
@@ -1,5 +1,4 @@
 import re
-from abc import ABCMeta
 from typing import Dict, Union, List, Tuple, TYPE_CHECKING, Optional, Any
 
 from Crypto.Hash import SHA1
@@ -99,21 +98,29 @@ def __str__(self) -> str:
         return f"{filename_short}{lines}"
 
     def __hash__(self) -> int:
-        return hash(str(self))
+        return hash(
+            (
+                self.start,
+                self.length,
+                self.filename.relative,
+                self.end,
+            )
+        )
 
     def __eq__(self, other: Any) -> bool:
-        if not isinstance(other, type(self)):
+        try:
+            return (
+                self.start == other.start
+                and self.length == other.length
+                and self.filename == other.filename
+                and self.is_dependency == other.is_dependency
+                and self.lines == other.lines
+                and self.starting_column == other.starting_column
+                and self.ending_column == other.ending_column
+                and self.end == other.end
+            )
+        except AttributeError:
             return NotImplemented
-        return (
-            self.start == other.start
-            and self.length == other.length
-            and self.filename == other.filename
-            and self.is_dependency == other.is_dependency
-            and self.lines == other.lines
-            and self.starting_column == other.starting_column
-            and self.ending_column == other.ending_column
-            and self.end == other.end
-        )
 
 
 def _compute_line(
@@ -183,12 +190,14 @@ def _convert_source_mapping(
     return new_source
 
 
-class SourceMapping(Context, metaclass=ABCMeta):
+class SourceMapping(Context):
     def __init__(self) -> None:
         super().__init__()
         self.source_mapping: Optional[Source] = None
         self.references: List[Source] = []
 
+        self._pattern: Union[str, None] = None
+
     def set_offset(
         self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit"
     ) -> None:
@@ -204,3 +213,11 @@ def add_reference_from_raw_source(
     ) -> None:
         s = _convert_source_mapping(offset, compilation_unit)
         self.references.append(s)
+
+    @property
+    def pattern(self) -> str:
+        if self._pattern is None:
+            # Add " " to look after the first solidity keyword
+            return f" {self.name}"  # pylint: disable=no-member
+
+        return self._pattern
diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py
index ff1c352c31..7c54844316 100644
--- a/slither/detectors/all_detectors.py
+++ b/slither/detectors/all_detectors.py
@@ -57,7 +57,6 @@
 from .functions.unimplemented import UnimplementedFunctionDetection
 from .statements.mapping_deletion import MappingDeletionDetection
 from .statements.array_length_assignment import ArrayLengthAssignment
-from .variables.similar_variables import SimilarVarsDetection
 from .variables.function_init_state_variables import FunctionInitializedState
 from .statements.redundant_statements import RedundantStatements
 from .operations.bad_prng import BadPRNG
diff --git a/slither/detectors/statements/unprotected_upgradeable.py b/slither/detectors/statements/unprotected_upgradeable.py
index 30e6300f17..d25aff187d 100644
--- a/slither/detectors/statements/unprotected_upgradeable.py
+++ b/slither/detectors/statements/unprotected_upgradeable.py
@@ -52,7 +52,14 @@ def _whitelisted_modifiers(f: Function) -> bool:
 
 def _initialize_functions(contract: Contract) -> List[Function]:
     return list(
-        filter(_whitelisted_modifiers, [f for f in contract.functions if f.name == "initialize"])
+        filter(
+            _whitelisted_modifiers,
+            [
+                f
+                for f in contract.functions
+                if any((m.name in ["initializer", "reinitializer"]) for m in f.modifiers)
+            ],
+        )
     )
 
 
diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py
deleted file mode 100644
index dccaf09c49..0000000000
--- a/slither/detectors/variables/similar_variables.py
+++ /dev/null
@@ -1,106 +0,0 @@
-"""
-Check for state variables too similar
-Do not check contract inheritance
-"""
-import difflib
-from typing import List, Set, Tuple
-
-from slither.core.declarations.contract import Contract
-from slither.core.variables.local_variable import LocalVariable
-from slither.detectors.abstract_detector import (
-    AbstractDetector,
-    DetectorClassification,
-    DETECTOR_INFO,
-)
-from slither.utils.output import Output
-
-
-class SimilarVarsDetection(AbstractDetector):
-    """
-    Variable similar detector
-    """
-
-    ARGUMENT = "similar-names"
-    HELP = "Variable names are too similar"
-    IMPACT = DetectorClassification.INFORMATIONAL
-    CONFIDENCE = DetectorClassification.MEDIUM
-
-    WIKI = (
-        "https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar"
-    )
-
-    WIKI_TITLE = "Variable names too similar"
-    WIKI_DESCRIPTION = "Detect variables with names that are too similar."
-    WIKI_EXPLOIT_SCENARIO = "Bob uses several variables with similar names. As a result, his code is difficult to review."
-    WIKI_RECOMMENDATION = "Prevent variables from having similar names."
-
-    @staticmethod
-    def similar(seq1: str, seq2: str) -> bool:
-        """Test the name similarity
-
-        Two name are similar if difflib.SequenceMatcher on the lowercase
-        version of the name is greater than 0.90
-        See: https://docs.python.org/2/library/difflib.html
-        Args:
-            seq1 (str): first name
-            seq2 (str): second name
-        Returns:
-            bool: true if names are similar
-        """
-        val = difflib.SequenceMatcher(a=seq1, b=seq2).ratio()
-        ret = val > 0.90
-        return ret
-
-    @staticmethod
-    def detect_sim(contract: Contract) -> Set[Tuple[LocalVariable, LocalVariable]]:
-        """Detect variables with similar name
-
-        Returns:
-            bool: true if variables have similar name
-        """
-        all_var = [x.variables for x in contract.functions]
-        all_var = [x for l in all_var for x in l]
-
-        contract_var = contract.variables
-
-        all_var = list(set(all_var + contract_var))
-
-        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 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 ret
-
-    def _detect(self) -> List[Output]:
-        """Detect similar variables name
-
-        Returns:
-            list: {'vuln', 'filename,'contract','vars'}
-        """
-        results = []
-        for c in self.contracts:
-            allVars = self.detect_sim(c)
-            if allVars:
-                for (v1, v2) in sorted(allVars, key=lambda x: (x[0].name, x[1].name)):
-                    v_left = v1 if v1.name < v2.name else v2
-                    v_right = v2 if v_left == v1 else v1
-                    info: DETECTOR_INFO = [
-                        "Variable ",
-                        v_left,
-                        " is too similar to ",
-                        v_right,
-                        "\n",
-                    ]
-                    json = self.generate_result(info)
-                    results.append(json)
-        return results
diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py
index a16ce273af..54b525c774 100644
--- a/slither/printers/inheritance/inheritance_graph.py
+++ b/slither/printers/inheritance/inheritance_graph.py
@@ -98,12 +98,21 @@ def _summary(self, contract):
         """
         ret = ""
 
+        # Remove contracts that have "mock" in the name and if --include-interfaces in False (default)
+        # removes inherited interfaces
+        inheritance = [
+            i
+            for i in contract.immediate_inheritance
+            if "mock" not in i.name.lower()
+            and (not i.is_interface or self.slither.include_interfaces)
+        ]
+
         # Add arrows (number them if there is more than one path so we know order of declaration for inheritance).
-        if len(contract.immediate_inheritance) == 1:
+        if len(inheritance) == 1:
             immediate_inheritance = contract.immediate_inheritance[0]
             ret += f"c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance};\n"
         else:
-            for i, immediate_inheritance in enumerate(contract.immediate_inheritance):
+            for i, immediate_inheritance in enumerate(inheritance):
                 ret += f'c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance} [ label="{i + 1}" ];\n'
 
         # Functions
@@ -113,6 +122,7 @@ def _summary(self, contract):
             for f in contract.functions
             if not f.is_constructor
             and not f.is_constructor_variables
+            and not f.is_virtual
             and f.contract_declarer == contract
             and f.visibility in visibilities
         ]
@@ -195,6 +205,12 @@ def output(self, filename):
 
         content = 'digraph "" {\n'
         for c in self.contracts:
+            if (
+                "mock" in c.name.lower()
+                or c.is_library
+                or (c.is_interface and not self.slither.include_interfaces)
+            ):
+                continue
             content += self._summary(c) + "\n"
         content += "}"
 
diff --git a/slither/printers/summary/evm.py b/slither/printers/summary/evm.py
index aad71bdff8..b834eb6eb8 100644
--- a/slither/printers/summary/evm.py
+++ b/slither/printers/summary/evm.py
@@ -2,8 +2,11 @@
     Module printing evm mapping of the contract
 """
 import logging
+from typing import Union, List, Dict
 
 from slither.printers.abstract_printer import AbstractPrinter
+from slither.core.declarations.function import Function
+from slither.core.declarations.modifier import Modifier
 from slither.analyses.evm import (
     generate_source_to_evm_ins_mapping,
     load_evm_cfg_builder,
@@ -77,6 +80,33 @@ class PrinterEVM(AbstractPrinter):
 
     WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#evm"
 
+    def build_element_node_str(
+        self,
+        element: Union["Modifier", "Function"],
+        contract_pcs: Dict[int, List[int]],
+        contract_cfg,
+    ) -> str:
+        element_file = self.slither.source_code[
+            element.contract_declarer.source_mapping.filename.absolute
+        ].splitlines()
+
+        return_string = ""
+        for node in element.nodes:
+            return_string += green(f"\t\tNode: {node}\n")
+            node_source_line = node.source_mapping.lines[0]
+            return_string += green(
+                f"\t\tSource line {node_source_line}: {element_file[node_source_line - 1].rstrip()}\n"
+            )
+
+            return_string += magenta("\t\tEVM Instructions:\n")
+            node_pcs = contract_pcs.get(node_source_line, [])
+            for pc in node_pcs:
+                return_string += magenta(
+                    f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n"
+                )
+
+        return return_string
+
     def output(self, _filename):
         """
         _filename is not used
@@ -99,53 +129,27 @@ def output(self, _filename):
                 txt += "\tempty contract\n"
                 continue
 
-            contract_file = self.slither.source_code[
-                contract.source_mapping.filename.absolute
-            ].encode("utf-8")
-            with open(contract.source_mapping.filename.absolute, "r", encoding="utf8") as f:
-                contract_file_lines = f.readlines()
-
-            contract_pcs = {}
-            contract_cfg = {}
-
             for function in contract.functions:
                 txt += blue(f"\tFunction {function.canonical_name}\n")
 
-                # CFG and source mapping depend on function being constructor or not
-                if function.is_constructor:
-                    contract_cfg = evm_info["cfg_init", contract.name]
-                    contract_pcs = evm_info["mapping_init", contract.name]
-                else:
-                    contract_cfg = evm_info["cfg", contract.name]
-                    contract_pcs = evm_info["mapping", contract.name]
-
-                for node in function.nodes:
-                    txt += green("\t\tNode: " + str(node) + "\n")
-                    node_source_line = (
-                        contract_file[0 : node.source_mapping.start].count("\n".encode("utf-8")) + 1
-                    )
-                    txt += green(
-                        f"\t\tSource line {node_source_line}: {contract_file_lines[node_source_line - 1].rstrip()}\n"
-                    )
-                    txt += magenta("\t\tEVM Instructions:\n")
-                    node_pcs = contract_pcs.get(node_source_line, [])
-                    for pc in node_pcs:
-                        txt += magenta(f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n")
+                txt += self.build_element_node_str(
+                    function,
+                    evm_info["mapping", contract.name]
+                    if not function.is_constructor
+                    else evm_info["mapping_init", contract.name],
+                    evm_info["cfg", contract.name]
+                    if not function.is_constructor
+                    else evm_info["cfg_init", contract.name],
+                )
 
             for modifier in contract.modifiers:
                 txt += blue(f"\tModifier {modifier.canonical_name}\n")
-                for node in modifier.nodes:
-                    txt += green("\t\tNode: " + str(node) + "\n")
-                    node_source_line = (
-                        contract_file[0 : node.source_mapping.start].count("\n".encode("utf-8")) + 1
-                    )
-                    txt += green(
-                        f"\t\tSource line {node_source_line}: {contract_file_lines[node_source_line - 1].rstrip()}\n"
-                    )
-                    txt += magenta("\t\tEVM Instructions:\n")
-                    node_pcs = contract_pcs.get(node_source_line, [])
-                    for pc in node_pcs:
-                        txt += magenta(f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n")
+
+                txt += self.build_element_node_str(
+                    modifier,
+                    evm_info["mapping", contract.name],
+                    evm_info["cfg", contract.name],
+                )
 
         self.info(txt)
         res = self.generate_output(txt)
diff --git a/slither/slither.py b/slither/slither.py
index 0f22185353..7adc0694ca 100644
--- a/slither/slither.py
+++ b/slither/slither.py
@@ -196,10 +196,12 @@ def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None:
         if printers_to_run == "echidna":
             self.skip_data_dependency = True
 
+        # Used in inheritance-graph printer
+        self.include_interfaces = kwargs.get("include_interfaces", False)
+
         self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
 
     def _init_parsing_and_analyses(self, skip_analyze: bool) -> None:
-
         for parser in self._parsers:
             try:
                 parser.parse_contracts()
diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py
index 2d8fa58f60..4ea1239e52 100644
--- a/slither/solc_parsing/expressions/find_variable.py
+++ b/slither/solc_parsing/expressions/find_variable.py
@@ -304,7 +304,7 @@ def _find_variable_init(
             scope = underlying_function.file_scope
         else:
             assert isinstance(underlying_function, FunctionContract)
-            scope = underlying_function.contract.file_scope
+            scope = underlying_function.contract_declarer.file_scope
 
     elif isinstance(caller_context, StructureTopLevelSolc):
         direct_contracts = []
diff --git a/slither/tools/documentation/README.md b/slither/tools/documentation/README.md
index b4b3e6a76b..218f2e91d2 100644
--- a/slither/tools/documentation/README.md
+++ b/slither/tools/documentation/README.md
@@ -1,5 +1,5 @@
 # slither-documentation
 
-`slither-documentation` uses [codex](https://beta.openai.com) to generate natspec documenation.
+`slither-documentation` uses [codex](https://platform.openai.com) to generate natspec documenation.
 
 This tool is experimental. See [solmate documentation](https://github.com/montyly/solmate/pull/1) for an example of usage.
diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py
index a37e859133..f5b9ab4527 100644
--- a/slither/utils/command_line.py
+++ b/slither/utils/command_line.py
@@ -48,6 +48,7 @@ class FailOnLevel(enum.Enum):
     "detectors_to_run": "all",
     "printers_to_run": None,
     "detectors_to_exclude": None,
+    "detectors_to_include": None,
     "exclude_dependencies": False,
     "exclude_informational": False,
     "exclude_optimization": False,
diff --git a/slither/utils/source_mapping.py b/slither/utils/source_mapping.py
index 9bf772894e..180c842f72 100644
--- a/slither/utils/source_mapping.py
+++ b/slither/utils/source_mapping.py
@@ -2,37 +2,17 @@
 from crytic_compile import CryticCompile
 from slither.core.declarations import (
     Contract,
-    Function,
-    Enum,
-    Event,
-    Import,
-    Pragma,
-    Structure,
-    CustomError,
     FunctionContract,
 )
-from slither.core.solidity_types import Type, TypeAlias
 from slither.core.source_mapping.source_mapping import Source, SourceMapping
-from slither.core.variables.variable import Variable
 from slither.exceptions import SlitherError
 
 
 def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Source:
-    if isinstance(target, (Contract, Function, Enum, Event, Structure, Variable)):
-        # Add " " to look after the first solidity keyword
-        pattern = " " + target.name
-    elif isinstance(target, Import):
-        pattern = "import"
-    elif isinstance(target, Pragma):
-        pattern = "pragma"  # todo maybe return with the while pragma statement
-    elif isinstance(target, CustomError):
-        pattern = "error"
-    elif isinstance(target, TypeAlias):
-        pattern = "type"
-    elif isinstance(target, Type):
-        raise SlitherError("get_definition_generic not implemented for types")
-    else:
-        raise SlitherError(f"get_definition_generic not implemented for {type(target)}")
+    try:
+        pattern = target.pattern
+    except AttributeError as exc:
+        raise SlitherError(f"get_definition_generic not implemented for {type(target)}") from exc
 
     file_content = crytic_compile.src_content_for_file(target.source_mapping.filename.absolute)
     txt = file_content[
diff --git a/slither/visitors/expression/expression.py b/slither/visitors/expression/expression.py
index 41886a1023..83dd1be51a 100644
--- a/slither/visitors/expression/expression.py
+++ b/slither/visitors/expression/expression.py
@@ -1,4 +1,5 @@
 import logging
+from functools import lru_cache
 
 from slither.core.expressions.assignment_operation import AssignmentOperation
 from slither.core.expressions.binary_operation import BinaryOperation
@@ -16,11 +17,39 @@
 from slither.core.expressions.tuple_expression import TupleExpression
 from slither.core.expressions.type_conversion import TypeConversion
 from slither.core.expressions.unary_operation import UnaryOperation
+from slither.core.expressions.super_call_expression import SuperCallExpression
+from slither.core.expressions.super_identifier import SuperIdentifier
+from slither.core.expressions.self_identifier import SelfIdentifier
 from slither.exceptions import SlitherError
 
 logger = logging.getLogger("ExpressionVisitor")
 
 
+@lru_cache()
+def get_visitor_mapping():
+    """Returns a visitor mapping from expression type to visiting functions."""
+    return {
+        AssignmentOperation: "_visit_assignement_operation",
+        BinaryOperation: "_visit_binary_operation",
+        CallExpression: "_visit_call_expression",
+        ConditionalExpression: "_visit_conditional_expression",
+        ElementaryTypeNameExpression: "_visit_elementary_type_name_expression",
+        Identifier: "_visit_identifier",
+        IndexAccess: "_visit_index_access",
+        Literal: "_visit_literal",
+        MemberAccess: "_visit_member_access",
+        NewArray: "_visit_new_array",
+        NewContract: "_visit_new_contract",
+        NewElementaryType: "_visit_new_elementary_type",
+        TupleExpression: "_visit_tuple_expression",
+        TypeConversion: "_visit_type_conversion",
+        UnaryOperation: "_visit_unary_operation",
+        SelfIdentifier: "_visit_identifier",
+        SuperIdentifier: "_visit_identifier",
+        SuperCallExpression: "_visit_call_expression",
+    }
+
+
 # pylint: disable=too-few-public-methods
 class ExpressionVisitor:
     def __init__(self, expression: Expression) -> None:
@@ -35,60 +64,16 @@ def expression(self) -> Expression:
 
     # visit an expression
     # call pre_visit, visit_expression_name, post_visit
-    # pylint: disable=too-many-branches
     def _visit_expression(self, expression: Expression) -> None:
         self._pre_visit(expression)
 
-        if isinstance(expression, AssignmentOperation):
-            self._visit_assignement_operation(expression)
-
-        elif isinstance(expression, BinaryOperation):
-            self._visit_binary_operation(expression)
-
-        elif isinstance(expression, CallExpression):
-            self._visit_call_expression(expression)
-
-        elif isinstance(expression, ConditionalExpression):
-            self._visit_conditional_expression(expression)
-
-        elif isinstance(expression, ElementaryTypeNameExpression):
-            self._visit_elementary_type_name_expression(expression)
-
-        elif isinstance(expression, Identifier):
-            self._visit_identifier(expression)
-
-        elif isinstance(expression, IndexAccess):
-            self._visit_index_access(expression)
-
-        elif isinstance(expression, Literal):
-            self._visit_literal(expression)
-
-        elif isinstance(expression, MemberAccess):
-            self._visit_member_access(expression)
-
-        elif isinstance(expression, NewArray):
-            self._visit_new_array(expression)
-
-        elif isinstance(expression, NewContract):
-            self._visit_new_contract(expression)
-
-        elif isinstance(expression, NewElementaryType):
-            self._visit_new_elementary_type(expression)
-
-        elif isinstance(expression, TupleExpression):
-            self._visit_tuple_expression(expression)
+        if expression is not None:
+            visitor_method = get_visitor_mapping().get(expression.__class__)
+            if not visitor_method:
+                raise SlitherError(f"Expression not handled: {expression}")
 
-        elif isinstance(expression, TypeConversion):
-            self._visit_type_conversion(expression)
-
-        elif isinstance(expression, UnaryOperation):
-            self._visit_unary_operation(expression)
-
-        elif expression is None:
-            pass
-
-        else:
-            raise SlitherError(f"Expression not handled: {expression}")
+            visitor = getattr(self, visitor_method)
+            visitor(expression)
 
         self._post_visit(expression)
 
diff --git a/slither/visitors/expression/read_var.py b/slither/visitors/expression/read_var.py
index a0efdde618..9619cfff9b 100644
--- a/slither/visitors/expression/read_var.py
+++ b/slither/visitors/expression/read_var.py
@@ -50,8 +50,8 @@ def result(self) -> List[Expression]:
             self._result = list(set(get(self.expression)))
         return self._result
 
-    # overide assignement
-    # dont explore if its direct assignement (we explore if its +=, -=, ...)
+    # override assignment
+    # dont explore if its direct assignment (we explore if its +=, -=, ...)
     def _visit_assignement_operation(self, expression: AssignmentOperation) -> None:
         if expression.type != AssignmentOperationType.ASSIGN:
             self._visit_expression(expression.expression_left)
diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
index 0f91f9bd16..1d68336bd6 100644
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -188,7 +188,7 @@ def _post_assignement_operation(self, expression: AssignmentOperation) -> None:
         right = get(expression.expression_right)
         operation: Operation
         if isinstance(left, list):  # tuple expression:
-            if isinstance(right, list):  # unbox assigment
+            if isinstance(right, list):  # unbox assignment
                 assert len(left) == len(right)
                 for idx, _ in enumerate(left):
                     if (
@@ -448,12 +448,12 @@ def _post_index_access(self, expression: IndexAccess) -> None:
         right = get(expression.expression_right)
         operation: Operation
         # Left can be a type for abi.decode(var, uint[2])
-        if isinstance(left, (Type, Contract, Enum)):
+        if isinstance(left, (Type, Contract, Enum, Structure)):
             # Nested type are not yet supported by abi.decode, so the assumption
             # Is that the right variable must be a constant
             assert isinstance(right, Constant)
             # Case for abi.decode(var, I[2]) where I is an interface/contract or an enum
-            if isinstance(left, (Contract, Enum)):
+            if isinstance(left, (Contract, Enum, Structure)):
                 left = UserDefinedType(left)
             t = ArrayType(left, int(right.value))
             set_val(expression, t)
diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py
index 2acd43e0fa..64fab1c549 100644
--- a/slither/vyper_parsing/declarations/contract.py
+++ b/slither/vyper_parsing/declarations/contract.py
@@ -84,7 +84,7 @@ def _parse_contract_items(self) -> None:
                 self._structuresNotParsed.append(node)
             elif isinstance(node, ImportFrom):
                 # TOOD aliases
-                # We create an `InterfaceDef` sense the compilatuion unit does not contain the actual interface
+                # We create an `InterfaceDef` sense the compilation unit does not contain the actual interface
                 # https://github.com/vyperlang/vyper/tree/master/vyper/builtins/interfaces
                 if node.module == "vyper.interfaces":
                     interfaces = {
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt
deleted file mode 100644
index 7f6fa4da1f..0000000000
--- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol#4)
-
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt
deleted file mode 100644
index 70b5c329b1..0000000000
--- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol#4)
-
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt
deleted file mode 100644
index efb92b5aa8..0000000000
--- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol#4)
-
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt
deleted file mode 100644
index 67d4823289..0000000000
--- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol#4)
-
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt
new file mode 100644
index 0000000000..1ca788ced8
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt
@@ -0,0 +1 @@
+AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt
new file mode 100644
index 0000000000..79cc306fea
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt
@@ -0,0 +1 @@
+Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt
new file mode 100644
index 0000000000..36309ced37
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt
@@ -0,0 +1 @@
+AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt
new file mode 100644
index 0000000000..99eac307d9
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt
@@ -0,0 +1 @@
+Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt
new file mode 100644
index 0000000000..dc9612b837
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt
@@ -0,0 +1 @@
+AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt
new file mode 100644
index 0000000000..2708424239
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt
@@ -0,0 +1 @@
+Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt
new file mode 100644
index 0000000000..5a4ccf71af
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt
@@ -0,0 +1 @@
+AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt
new file mode 100644
index 0000000000..f79c9c662d
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt
@@ -0,0 +1 @@
+Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt
new file mode 100644
index 0000000000..fb08aab174
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt
@@ -0,0 +1 @@
+AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#11-14)
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt
new file mode 100644
index 0000000000..2eb7d5feea
--- /dev/null
+++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt
@@ -0,0 +1 @@
+Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#11-14)
diff --git a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol b/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol
deleted file mode 100644
index 57f9698675..0000000000
--- a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract Similar {
-    function f()  public returns (uint) {
-        uint testVariable = 1;
-        uint textVariable = 2;
-        return testVariable + textVariable;
-    }
-}
\ No newline at end of file
diff --git a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip b/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip
deleted file mode 100644
index b91c8f6ffe..0000000000
Binary files a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip and /dev/null differ
diff --git a/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol b/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol
deleted file mode 100644
index 57f9698675..0000000000
--- a/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract Similar {
-    function f()  public returns (uint) {
-        uint testVariable = 1;
-        uint textVariable = 2;
-        return testVariable + textVariable;
-    }
-}
\ No newline at end of file
diff --git a/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol-0.5.16.zip b/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol-0.5.16.zip
deleted file mode 100644
index d547748aab..0000000000
Binary files a/tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol-0.5.16.zip and /dev/null differ
diff --git a/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol b/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol
deleted file mode 100644
index 57f9698675..0000000000
--- a/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract Similar {
-    function f()  public returns (uint) {
-        uint testVariable = 1;
-        uint textVariable = 2;
-        return testVariable + textVariable;
-    }
-}
\ No newline at end of file
diff --git a/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol-0.6.11.zip b/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol-0.6.11.zip
deleted file mode 100644
index 87dd6c4a68..0000000000
Binary files a/tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol-0.6.11.zip and /dev/null differ
diff --git a/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol b/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol
deleted file mode 100644
index 57f9698675..0000000000
--- a/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol
+++ /dev/null
@@ -1,7 +0,0 @@
-contract Similar {
-    function f()  public returns (uint) {
-        uint testVariable = 1;
-        uint textVariable = 2;
-        return testVariable + textVariable;
-    }
-}
\ No newline at end of file
diff --git a/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol-0.7.6.zip b/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol-0.7.6.zip
deleted file mode 100644
index 5db2e6d7db..0000000000
Binary files a/tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol-0.7.6.zip and /dev/null differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol
new file mode 100644
index 0000000000..9ad63bcdf1
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract AnyInitializer is Initializable {
+    address owner;
+
+    function anyName() external initializer {
+        require(owner == address(0));
+        owner = msg.sender;
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip
new file mode 100644
index 0000000000..143c2bc524
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol
index 779a0e87c9..c19577db34 100644
--- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Initializable.sol
@@ -1,5 +1,9 @@
-contract Initializable{
-      modifier initializer() {
-          _;
-      }
-}
\ No newline at end of file
+contract Initializable {
+    modifier initializer() {
+        _;
+    }
+
+    modifier reinitializer(uint64 version) {
+        _;
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol
new file mode 100644
index 0000000000..6786d15210
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract Reinitializer is Initializable {
+    address owner;
+
+    function initialize() external reinitializer(2) {
+        require(owner == address(0));
+        owner = msg.sender;
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol-0.4.25.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol-0.4.25.zip
new file mode 100644
index 0000000000..054a9f79f4
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol-0.4.25.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol
new file mode 100644
index 0000000000..2afa430964
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract AnyInitializer is Initializable {
+    address payable owner;
+
+    function anyName() external initializer {
+        require(owner == address(0));
+        owner = msg.sender;
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol-0.5.16.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol-0.5.16.zip
new file mode 100644
index 0000000000..eafa90e247
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol-0.5.16.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol
index 779a0e87c9..c19577db34 100644
--- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol
@@ -1,5 +1,9 @@
-contract Initializable{
-      modifier initializer() {
-          _;
-      }
-}
\ No newline at end of file
+contract Initializable {
+    modifier initializer() {
+        _;
+    }
+
+    modifier reinitializer(uint64 version) {
+        _;
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol
new file mode 100644
index 0000000000..cdf587c494
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract Reinitializer is Initializable {
+    address payable owner;
+
+    function initialize() external reinitializer(2) {
+        require(owner == address(0));
+        owner = msg.sender;
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip
new file mode 100644
index 0000000000..0f8b1e9847
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol
new file mode 100644
index 0000000000..bccbbc3ea2
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract AnyInitializer is Initializable {
+    address payable owner;
+
+    function anyName() external initializer {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip
new file mode 100644
index 0000000000..b2608ec199
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol
index 779a0e87c9..c19577db34 100644
--- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol
@@ -1,5 +1,9 @@
-contract Initializable{
-      modifier initializer() {
-          _;
-      }
-}
\ No newline at end of file
+contract Initializable {
+    modifier initializer() {
+        _;
+    }
+
+    modifier reinitializer(uint64 version) {
+        _;
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol
new file mode 100644
index 0000000000..d8a81a4cea
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract Reinitializer is Initializable {
+    address payable owner;
+
+    function initialize() external reinitializer(2) {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip
new file mode 100644
index 0000000000..a74cdfdf4d
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol
new file mode 100644
index 0000000000..bccbbc3ea2
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract AnyInitializer is Initializable {
+    address payable owner;
+
+    function anyName() external initializer {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol-0.7.6.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol-0.7.6.zip
new file mode 100644
index 0000000000..578572ecb3
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol-0.7.6.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Initializable.sol
index cff401bae7..a095b72274 100644
--- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Initializable.sol
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Initializable.sol
@@ -1,4 +1,4 @@
-contract Initializable{
+contract Initializable {
     uint8 private _initialized;
     bool private _initializing;
 
@@ -6,10 +6,14 @@ contract Initializable{
         _;
     }
 
+    modifier reinitializer(uint64 version) {
+        _;
+    }
+
     function _disableInitializers() internal virtual {
         require(!_initializing, "Initializable: contract is initializing");
         if (_initialized < type(uint8).max) {
             _initialized = type(uint8).max;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol
new file mode 100644
index 0000000000..d8a81a4cea
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract Reinitializer is Initializable {
+    address payable owner;
+
+    function initialize() external reinitializer(2) {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol-0.7.6.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol-0.7.6.zip
new file mode 100644
index 0000000000..bbf0f580b5
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol-0.7.6.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol
new file mode 100644
index 0000000000..bccbbc3ea2
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract AnyInitializer is Initializable {
+    address payable owner;
+
+    function anyName() external initializer {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip
new file mode 100644
index 0000000000..9da08b61b0
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip differ
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol
index 4fd7561c84..a095b72274 100644
--- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol
@@ -6,10 +6,14 @@ contract Initializable {
         _;
     }
 
+    modifier reinitializer(uint64 version) {
+        _;
+    }
+
     function _disableInitializers() internal virtual {
         require(!_initializing, "Initializable: contract is initializing");
         if (_initialized < type(uint8).max) {
             _initialized = type(uint8).max;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol
new file mode 100644
index 0000000000..d8a81a4cea
--- /dev/null
+++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol
@@ -0,0 +1,15 @@
+import "./Initializable.sol";
+
+contract Reinitializer is Initializable {
+    address payable owner;
+
+    function initialize() external reinitializer(2) {
+        require(owner == address(0));
+        owner = payable(msg.sender);
+    }
+
+    function kill() external {
+        require(msg.sender == owner);
+        selfdestruct(owner);
+    }
+}
diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip
new file mode 100644
index 0000000000..e58f71c44b
Binary files /dev/null and b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip differ
diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py
index 5604b57dd6..299f2ea031 100644
--- a/tests/e2e/detectors/test_detectors.py
+++ b/tests/e2e/detectors/test_detectors.py
@@ -938,6 +938,16 @@ def id_test(test_item: Test):
         "whitelisted.sol",
         "0.4.25",
     ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "Reinitializer.sol",
+        "0.4.25",
+    ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "AnyInitializer.sol",
+        "0.4.25",
+    ),
     Test(
         all_detectors.UnprotectedUpgradeable,
         "Buggy.sol",
@@ -953,6 +963,16 @@ def id_test(test_item: Test):
         "whitelisted.sol",
         "0.5.16",
     ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "Reinitializer.sol",
+        "0.5.16",
+    ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "AnyInitializer.sol",
+        "0.5.16",
+    ),
     Test(
         all_detectors.UnprotectedUpgradeable,
         "Buggy.sol",
@@ -968,6 +988,16 @@ def id_test(test_item: Test):
         "whitelisted.sol",
         "0.6.11",
     ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "Reinitializer.sol",
+        "0.6.11",
+    ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "AnyInitializer.sol",
+        "0.6.11",
+    ),
     Test(
         all_detectors.UnprotectedUpgradeable,
         "Buggy.sol",
@@ -978,6 +1008,16 @@ def id_test(test_item: Test):
         "Fixed.sol",
         "0.7.6",
     ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "Reinitializer.sol",
+        "0.7.6",
+    ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "AnyInitializer.sol",
+        "0.7.6",
+    ),
     Test(
         all_detectors.UnprotectedUpgradeable,
         "whitelisted.sol",
@@ -998,6 +1038,16 @@ def id_test(test_item: Test):
         "whitelisted.sol",
         "0.8.15",
     ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "Reinitializer.sol",
+        "0.8.15",
+    ),
+    Test(
+        all_detectors.UnprotectedUpgradeable,
+        "AnyInitializer.sol",
+        "0.8.15",
+    ),
     Test(
         all_detectors.ABIEncoderV2Array,
         "storage_ABIEncoderV2_array.sol",
@@ -1403,26 +1453,6 @@ def id_test(test_item: Test):
         "type_based_tautology.sol",
         "0.7.6",
     ),
-    Test(
-        all_detectors.SimilarVarsDetection,
-        "similar_variables.sol",
-        "0.4.25",
-    ),
-    Test(
-        all_detectors.SimilarVarsDetection,
-        "similar_variables.sol",
-        "0.5.16",
-    ),
-    Test(
-        all_detectors.SimilarVarsDetection,
-        "similar_variables.sol",
-        "0.6.11",
-    ),
-    Test(
-        all_detectors.SimilarVarsDetection,
-        "similar_variables.sol",
-        "0.7.6",
-    ),
     Test(
         all_detectors.MsgValueInLoop,
         "msg_value_loop.sol",
diff --git a/tests/e2e/printers/test_data/test_contract_names/C.sol b/tests/e2e/printers/test_data/test_contract_names/C.sol
index 90bc35df39..d6ba9b5c15 100644
--- a/tests/e2e/printers/test_data/test_contract_names/C.sol
+++ b/tests/e2e/printers/test_data/test_contract_names/C.sol
@@ -1,7 +1,21 @@
 import "./A.sol";
 
-contract C is A {
+interface MyInterfaceX {
+    function count() external view returns (uint256);
+
+    function increment() external;
+}
+
+contract C is A, MyInterfaceX {
     function c_main() public pure {
         a_main();
     }
+
+    function count() external view override returns (uint256){
+        return 1;
+    }
+
+    function increment() external override {
+
+    }
 }
diff --git a/tests/e2e/printers/test_printers.py b/tests/e2e/printers/test_printers.py
index b7cd4d3b6b..fc7a22378c 100644
--- a/tests/e2e/printers/test_printers.py
+++ b/tests/e2e/printers/test_printers.py
@@ -35,6 +35,18 @@ def test_inheritance_printer(solc_binary_path) -> None:
 
     assert counter["B -> A"] == 2
     assert counter["C -> A"] == 1
+    
+    # Let also test the include/exclude interface behavior
+    # Check that the interface is not included
+    assert "MyInterfaceX" not in content
+
+    slither.include_interfaces = True
+    output = printer.output("test_printer.dot")
+    content = output.elements[0]["name"]["content"]
+    assert "MyInterfaceX" in content
+
+    # Remove test generated files
+    Path("test_printer.dot").unlink(missing_ok=True)
 
 
 def test_slithir_printer(solc_binary_path) -> None:
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip
index b65e511efb..6c43440c91 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip
index c9a78fceaf..6c8b090357 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip
index 1b69e8e3d5..bdc1f1bfde 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip
index 5661f465da..1d2d91bad4 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip
index cf49507691..3188827199 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.zip
index 16236fd228..c4adafc8e2 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip
index d574a7cb84..4c6db0a424 100644
Binary files a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip and b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json
index 070b687bd8..b040e9ab4d 100644
--- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json
+++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json
@@ -2,6 +2,7 @@
   "I": {},
   "C": {
     "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
-    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+    "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n",
+    "test_decode_struct_array(bytes)": "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/user_defined_value_type/abi-decode-fixed-array.sol b/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol
index 14a59b5a2a..d5bddddc29 100644
--- a/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol
+++ b/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol
@@ -1,10 +1,11 @@
 interface I {}
 enum A {a,b}
-
+struct S {uint256 a;}
 contract C {
     I[6] interfaceArray;
     A[6] enumArray;
 
+
     function test_decode_interface_array(bytes memory data) public {
         interfaceArray = abi.decode(data, (I[6]));
     }
@@ -13,4 +14,8 @@ contract C {
         enumArray = abi.decode(data, (A[6]));
     }
 
+    function test_decode_struct_array(bytes memory data) public {
+        S[6] memory structArray = abi.decode(data, (S[6]));
+    }
+
 }
diff --git a/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol b/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol
new file mode 100644
index 0000000000..5eb92aa2fd
--- /dev/null
+++ b/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {
+    ParentContract
+} from "./ParentContract.sol";
+
+import {
+    MainErrors as Errors
+} from "./../errors/MainErrors.sol";
+
+
+contract MainContract is ParentContract {
+
+    
+    function functionWithMainError1(uint256 a, uint256 b) external pure returns (uint256) {
+        if (a == b) {
+            revert Errors.MainError1();
+        }
+        // Add some arithmetic operations here
+        return a + b;
+    }
+
+    function functionWithMainError2(uint256 a, uint256 b) external pure returns (uint256) {
+        if (a < b) {
+            revert Errors.MainError2();
+        }
+        // Add some arithmetic operations here
+        return a - b;
+    }
+
+    function functionWithMainError3(uint256 a, uint256 b) external pure returns (uint256) {
+        if (b == 0) {
+            revert Errors.MainError3();
+        }
+        // Add some arithmetic operations here
+        return a * b;
+    }
+
+
+}
diff --git a/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol b/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol
new file mode 100644
index 0000000000..9ca32a1a6f
--- /dev/null
+++ b/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+
+import {
+    AccessControlErrors as Errors 
+} from "../errors/ParentContractErrors.sol";
+
+
+contract ParentContract {
+     
+     
+    function functionWithAccessControlErrors1(uint256 a, uint256 b) external pure returns (uint256) {
+        if (a == b) {
+            revert Errors.AccessControlErrors1();
+        }
+        // Add some arithmetic operations here
+        return a + b;
+    }
+
+    function functionWithAccessControlErrors2(uint256 a, uint256 b) external pure returns (uint256) {
+        if (a < b) {
+            revert Errors.AccessControlErrors2();
+        }
+        // Add some arithmetic operations here
+        return a - b;
+    }
+  
+
+}
diff --git a/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol b/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol
new file mode 100644
index 0000000000..e7db5c5c38
--- /dev/null
+++ b/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+// TODO: remove unused errors
+library MainErrors {
+    error MainError1();
+    error MainError2();
+    error MainError3();
+}
diff --git a/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol b/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol
new file mode 100644
index 0000000000..38ce16bdd2
--- /dev/null
+++ b/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+library AccessControlErrors {
+    error AccessControlErrors1();
+    error AccessControlErrors2();
+}
diff --git a/tests/unit/core/test_scope_with_renaming.py b/tests/unit/core/test_scope_with_renaming.py
new file mode 100644
index 0000000000..6984cfaa42
--- /dev/null
+++ b/tests/unit/core/test_scope_with_renaming.py
@@ -0,0 +1,17 @@
+from pathlib import Path
+from crytic_compile import CryticCompile
+from crytic_compile.platform.solc_standard_json import SolcStandardJson
+
+from slither import Slither
+
+TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
+SCOPE_RENAMING_TEST_DATA_DIR = Path(TEST_DATA_DIR, "scope_with_renaming")
+
+# https://github.com/crytic/slither/issues/2454
+def test_find_variable_scope_with_renaming(solc_binary_path) -> None:
+    solc_path = solc_binary_path("0.8.24")
+    standard_json = SolcStandardJson()
+    for source_file in SCOPE_RENAMING_TEST_DATA_DIR.rglob("**/*.sol"):
+        standard_json.add_source_file(Path(source_file).as_posix())
+    compilation = CryticCompile(standard_json, solc=solc_path)
+    Slither(compilation, disallow_partial=True)
diff --git a/tests/unit/core/test_using_for.py b/tests/unit/core/test_using_for.py
index 4d7634c5c9..656fc3a357 100644
--- a/tests/unit/core/test_using_for.py
+++ b/tests/unit/core/test_using_for.py
@@ -17,7 +17,7 @@ def test_using_for_global_collision(solc_binary_path) -> None:
     for source_file in Path(USING_FOR_TEST_DATA_DIR, "using_for_global_collision").rglob("*.sol"):
         standard_json.add_source_file(Path(source_file).as_posix())
     compilation = CryticCompile(standard_json, solc=solc_path)
-    sl = Slither(compilation)
+    sl = Slither(compilation, disallow_partial=True)
     _run_all_detectors(sl)