diff --git a/CITATION.cff b/CITATION.cff
new file mode 100644
index 0000000000..605bd60e5f
--- /dev/null
+++ b/CITATION.cff
@@ -0,0 +1,64 @@
+cff-version: 1.2.0
+title: Slither Analyzer
+message: >-
+ If you use this software, please cite it using the
+ metadata from this file.
+type: software
+authors:
+ - given-names: Josselin
+ family-names: Feist
+ - given-names: Gustavo
+ family-names: Grieco
+ - given-names: Alex
+ family-names: Groce
+identifiers:
+ - type: doi
+ value: 10.48550/arXiv.1908.09878
+ description: arXiv.1908.09878
+ - type: url
+ value: 'https://arxiv.org/abs/1908.09878'
+ description: arxiv
+ - type: doi
+ value: 10.1109/wetseb.2019.00008
+repository-code: 'https://github.com/crytic/slither'
+url: 'https://www.trailofbits.com/'
+repository-artifact: 'https://github.com/crytic/slither/releases'
+abstract: >-
+ Slither is a static analysis framework designed to provide
+ rich information about Ethereum smart contracts.
+
+ It works by converting Solidity smart contracts into an
+ intermediate representation called SlithIR.
+
+ SlithIR uses Static Single Assignment (SSA) form and a
+ reduced instruction set to ease implementation of analyses
+ while preserving semantic information that would be lost
+ in transforming Solidity to bytecode.
+
+ Slither allows for the application of commonly used
+ program analysis techniques like dataflow and taint
+ tracking.
+
+
+ Our framework has four main use cases:
+
+ (1) automated detection of vulnerabilities,
+
+ (2) automated detection of code optimization
+ opportunities,
+
+ (3) improvement of the user's understanding of the
+ contracts, and
+
+ (4) assistance with code review.
+keywords:
+ - Ethereum
+ - Static Analysis
+ - Smart contracts
+ - EVM
+ - bug detection
+ - Software Engineering
+license: AGPL-3.0-only
+commit: 3d4f934d3228f072b7df2c5e7252c64df4601bc8
+version: 0.9.5
+date-released: '2023-06-28'
diff --git a/README.md b/README.md
index cb815561e8..1a0d203c7d 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,57 @@
-# Slither, the Solidity source analyzer
+# [Slither, the Solidity source analyzer](https://crytic.github.io/slither/slither.html)
-
+
[![Build Status](https://img.shields.io/github/actions/workflow/status/crytic/slither/ci.yml?branch=master)](https://github.com/crytic/slither/actions?query=workflow%3ACI)
-[![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com)
-[![PyPI version](https://badge.fury.io/py/slither-analyzer.svg)](https://badge.fury.io/py/slither-analyzer)
-
-Slither is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.
-
-- [Features](#features)
-- [Usage](#usage)
-- [How to Install](#how-to-install)
-- [Detectors](#detectors)
-- [Printers](#printers)
-- [Tools](#tools)
-- [API Documentation](#api-documentation)
-- [Getting Help](#getting-help)
-- [FAQ](#faq)
-- [Publications](#publications)
+![PyPI](https://img.shields.io/pypi/v/slither-analyzer?logo=python&logoColor=white&label=slither-analyzer)
+[![Slither - Read the Docs](https://img.shields.io/badge/Slither-Read_the_Docs-2ea44f)](https://crytic.github.io/slither/slither.html)
+[![Slither - Wiki](https://img.shields.io/badge/Slither-Wiki-2ea44f)](https://github.com/crytic/slither/wiki/SlithIR)
+
+> Join the Empire Hacking Slack
+>
+> [![Slack Status](https://slack.empirehacking.nyc/badge.svg)](https://slack.empirehacking.nyc/)
+> > - Discussions and Support
+
+**Slither** is a Solidity static analysis framework written in Python3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.
+
+* [Features](#features)
+* [Usage](#usage)
+* [How to install](#how-to-install)
+ * [Using Pip](#using-pip)
+ * [Using Git](#using-git)
+ * [Using Docker](#using-docker)
+ * [Integration](#integration)
+* [Detectors](#detectors)
+* [Printers](#printers)
+ * [Quick Review Printers](#quick-review-printers)
+ * [In-Depth Review Printers](#in-depth-review-printers)
+* [Tools](#tools)
+* [API Documentation](#api-documentation)
+* [Getting Help](#getting-help)
+* [FAQ](#faq)
+* [License](#license)
+* [Publications](#publications)
+ * [Trail of Bits publication](#trail-of-bits-publication)
+ * [External publications](#external-publications)
## Features
-- Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md))
-- Identifies where the error condition occurs in the source code
-- Easily integrates into continuous integration and Hardhat/Foundry builds
-- Built-in 'printers' quickly report crucial contract information
-- Detector API to write custom analyses in Python
-- Ability to analyze contracts written with Solidity >= 0.4
-- Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses
-- Correctly parses 99.9% of all public Solidity code
-- Average execution time of less than 1 second per contract
-- Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action)
+* Detects vulnerable Solidity code with low false positives (see the list of [trophies](./trophies.md))
+* Identifies where the error condition occurs in the source code
+* Easily integrates into continuous integration and Hardhat/Foundry builds
+* Built-in 'printers' quickly report crucial contract information
+* Detector API to write custom analyses in Python
+* Ability to analyze contracts written with Solidity >= 0.4
+* Intermediate representation ([SlithIR](https://github.com/trailofbits/slither/wiki/SlithIR)) enables simple, high-precision analyses
+* Correctly parses 99.9% of all public Solidity code
+* Average execution time of less than 1 second per contract
+* Integrates with Github's code scanning in [CI](https://github.com/marketplace/actions/slither-action)
## Usage
Run Slither on a Hardhat/Foundry/Dapp/Brownie application:
-```bash
+```console
slither .
```
@@ -44,18 +59,19 @@ This is the preferred option if your project has dependencies as Slither relies
However, you can run Slither on a single file that does not import dependencies:
-```bash
+```console
slither tests/uninitialized.sol
```
## How to install
-Slither requires Python 3.8+.
+> **Note**
+> Slither requires Python 3.8+.
If you're **not** going to use one of the [supported compilation frameworks](https://github.com/crytic/crytic-compile), you need [solc](https://github.com/ethereum/solidity/), the Solidity compiler; we recommend using [solc-select](https://github.com/crytic/solc-select) to conveniently switch between solc versions.
### Using Pip
-```bash
+```console
pip3 install slither-analyzer
```
@@ -84,9 +100,9 @@ docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
### Integration
-- For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action).
-- To generate a Markdown report, use `slither [target] --checklist`.
-- To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`)
+* For GitHub action integration, use [slither-action](https://github.com/marketplace/actions/slither-action).
+* To generate a Markdown report, use `slither [target] --checklist`.
+* To generate a Markdown with GitHub source code highlighting, use `slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/` (replace `ORG`, `REPO`, `COMMIT`)
## Detectors
@@ -182,23 +198,24 @@ Num | Detector | What it Detects | Impact | Confidence
For more information, see
-- The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector
-- The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run.
-- The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results
+* The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector
+* The [Detection Selection](https://github.com/crytic/slither/wiki/Usage#detector-selection) to run only selected detectors. By default, all the detectors are run.
+* The [Triage Mode](https://github.com/crytic/slither/wiki/Usage#triage-mode) to filter individual results
## Printers
+
### Quick Review Printers
-- `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary)
-- `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph)
-- `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary)
-- `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc)
+* `human-summary`: [Print a human-readable summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#human-summary)
+* `inheritance-graph`: [Export the inheritance graph of each contract to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph)
+* `contract-summary`: [Print a summary of the contracts](https://github.com/trailofbits/slither/wiki/Printer-documentation#contract-summary)
+* `loc`: [Count the total number lines of code (LOC), source lines of code (SLOC), and comment lines of code (CLOC) found in source files (SRC), dependencies (DEP), and test files (TEST).](https://github.com/trailofbits/slither/wiki/Printer-documentation#loc)
### In-Depth Review Printers
-- `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph)
-- `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg)
-- `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary)
-- `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization)
-- `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused).
+* `call-graph`: [Export the call-graph of the contracts to a dot file](https://github.com/trailofbits/slither/wiki/Printer-documentation#call-graph)
+* `cfg`: [Export the CFG of each functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#cfg)
+* `function-summary`: [Print a summary of the functions](https://github.com/trailofbits/slither/wiki/Printer-documentation#function-summary)
+* `vars-and-auth`: [Print the state variables written and the authorization of the functions](https://github.com/crytic/slither/wiki/Printer-documentation#variables-written-and-authorization)
+* `not-pausable`: [Print functions that do not use `whenNotPaused` modifier](https://github.com/trailofbits/slither/wiki/Printer-documentation#when-not-paused).
To run a printer, use `--print` and a comma-separated list of printers.
@@ -206,13 +223,13 @@ See the [Printer documentation](https://github.com/crytic/slither/wiki/Printer-d
## Tools
-- `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](https://github.com/crytic/slither/wiki/Upgradeability-Checks)
-- `slither-prop`: [Automatic unit test and property generation](https://github.com/crytic/slither/wiki/Property-generation)
-- `slither-flat`: [Flatten a codebase](https://github.com/crytic/slither/wiki/Contract-Flattening)
-- `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance)
-- `slither-format`: [Automatic patch generation](https://github.com/crytic/slither/wiki/Slither-format)
-- `slither-read-storage`: [Read storage values from contracts](./slither/tools/read_storage/README.md)
-- `slither-interface`: [Generate an interface for a contract](./slither/tools/interface/README.md)
+* `slither-check-upgradeability`: [Review `delegatecall`-based upgradeability](https://github.com/crytic/slither/wiki/Upgradeability-Checks)
+* `slither-prop`: [Automatic unit test and property generation](https://github.com/crytic/slither/wiki/Property-generation)
+* `slither-flat`: [Flatten a codebase](https://github.com/crytic/slither/wiki/Contract-Flattening)
+* `slither-check-erc`: [Check the ERC's conformance](https://github.com/crytic/slither/wiki/ERC-Conformance)
+* `slither-format`: [Automatic patch generation](https://github.com/crytic/slither/wiki/Slither-format)
+* `slither-read-storage`: [Read storage values from contracts](./slither/tools/read_storage/README.md)
+* `slither-interface`: [Generate an interface for a contract](./slither/tools/interface/README.md)
See the [Tool documentation](https://github.com/crytic/slither/wiki/Tool-Documentation) for additional tools.
@@ -226,23 +243,23 @@ Documentation on Slither's internals is available [here](https://crytic.github.i
Feel free to stop by our [Slack channel](https://empireslacking.herokuapp.com) (#ethereum) for help using or extending Slither.
-- The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract.
+* The [Printer documentation](https://github.com/trailofbits/slither/wiki/Printer-documentation) describes the information Slither is capable of visualizing for each contract.
-- The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses.
+* The [Detector documentation](https://github.com/trailofbits/slither/wiki/Adding-a-new-detector) describes how to write a new vulnerability analyses.
-- The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses.
+* The [API documentation](https://github.com/crytic/slither/wiki/Python-API) describes the methods and objects available for custom analyses.
-- The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation.
+* The [SlithIR documentation](https://github.com/trailofbits/slither/wiki/SlithIR) describes the SlithIR intermediate representation.
## FAQ
How do I exclude mocks or tests?
-- View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering).
+* View our documentation on [path filtering](https://github.com/crytic/slither/wiki/Usage#path-filtering).
How do I fix "unknown file" or compilation issues?
-- Because slither requires the solc AST, it must have all dependencies available.
+* Because slither requires the solc AST, it must have all dependencies available.
If a contract has dependencies, `slither contract.sol` will fail.
Instead, use `slither .` in the parent directory of `contracts/` (you should see `contracts/` when you run `ls`).
If you have a `node_modules/` folder, it must be in the same directory as `contracts/`. To verify that this issue is related to slither,
@@ -257,7 +274,7 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt
### Trail of Bits publication
-- [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19
+* [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19
### External publications
diff --git a/setup.py b/setup.py
index 70d4f71fd4..182b91d35b 100644
--- a/setup.py
+++ b/setup.py
@@ -8,15 +8,15 @@
description="Slither is a Solidity static analysis framework written in Python 3.",
url="https://github.com/crytic/slither",
author="Trail of Bits",
- version="0.9.3",
+ version="0.9.6",
packages=find_packages(),
python_requires=">=3.8",
install_requires=[
"packaging",
"prettytable>=3.3.0",
"pycryptodome>=3.4.6",
- # "crytic-compile>=0.3.1,<0.4.0",
- "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile",
+ "crytic-compile>=0.3.3,<0.4.0",
+ # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@dev#egg=crytic-compile",
"web3>=6.0.0",
"eth-abi>=4.0.0",
"eth-typing>=3.0.0",
@@ -36,7 +36,6 @@
"coverage[toml]",
"filelock",
"pytest-insta",
- "solc-select@git+https://github.com/crytic/solc-select.git@query-artifact-path#egg=solc-select",
],
"doc": [
"pdoc",
diff --git a/slither/core/compilation_unit.py b/slither/core/compilation_unit.py
index 6d24786eb1..35180cefc0 100644
--- a/slither/core/compilation_unit.py
+++ b/slither/core/compilation_unit.py
@@ -47,7 +47,7 @@ def __init__(self, core: "SlitherCore", crytic_compilation_unit: CompilationUnit
self._pragma_directives: List[Pragma] = []
self._import_directives: List[Import] = []
self._custom_errors: List[CustomErrorTopLevel] = []
- self._user_defined_value_types: Dict[str, TypeAliasTopLevel] = {}
+ self._type_aliases: Dict[str, TypeAliasTopLevel] = {}
self._all_functions: Set[Function] = set()
self._all_modifiers: Set[Modifier] = set()
@@ -220,8 +220,8 @@ def custom_errors(self) -> List[CustomErrorTopLevel]:
return self._custom_errors
@property
- def user_defined_value_types(self) -> Dict[str, TypeAliasTopLevel]:
- return self._user_defined_value_types
+ def type_aliases(self) -> Dict[str, TypeAliasTopLevel]:
+ return self._type_aliases
# endregion
###################################################################################
diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py
index 9b1488db31..f9bf153064 100644
--- a/slither/core/declarations/contract.py
+++ b/slither/core/declarations/contract.py
@@ -45,6 +45,7 @@
from slither.core.compilation_unit import SlitherCompilationUnit
from slither.core.scope.scope import FileScope
from slither.core.cfg.node import Node
+ from slither.core.solidity_types import TypeAliasContract
LOGGER = logging.getLogger("Contract")
@@ -81,6 +82,7 @@ def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope
self._functions: Dict[str, "FunctionContract"] = {}
self._linearizedBaseContracts: List[int] = []
self._custom_errors: Dict[str, "CustomErrorContract"] = {}
+ self._type_aliases: Dict[str, "TypeAliasContract"] = {}
# The only str is "*"
self._using_for: Dict[USING_FOR_KEY, USING_FOR_ITEM] = {}
@@ -364,6 +366,38 @@ def custom_errors_declared(self) -> List["CustomErrorContract"]:
def custom_errors_as_dict(self) -> Dict[str, "CustomErrorContract"]:
return self._custom_errors
+ # endregion
+ ###################################################################################
+ ###################################################################################
+ # region Custom Errors
+ ###################################################################################
+ ###################################################################################
+
+ @property
+ def type_aliases(self) -> List["TypeAliasContract"]:
+ """
+ list(TypeAliasContract): List of the contract's custom errors
+ """
+ return list(self._type_aliases.values())
+
+ @property
+ def type_aliases_inherited(self) -> List["TypeAliasContract"]:
+ """
+ list(TypeAliasContract): List of the inherited custom errors
+ """
+ return [s for s in self.type_aliases if s.contract != self]
+
+ @property
+ def type_aliases_declared(self) -> List["TypeAliasContract"]:
+ """
+ list(TypeAliasContract): List of the custom errors declared within the contract (not inherited)
+ """
+ return [s for s in self.type_aliases if s.contract == self]
+
+ @property
+ def type_aliases_as_dict(self) -> Dict[str, "TypeAliasContract"]:
+ return self._type_aliases
+
# endregion
###################################################################################
###################################################################################
diff --git a/slither/core/scope/scope.py b/slither/core/scope/scope.py
index cafeb3585d..937a051361 100644
--- a/slither/core/scope/scope.py
+++ b/slither/core/scope/scope.py
@@ -52,7 +52,7 @@ def __init__(self, filename: Filename) -> None:
# User defined types
# Name -> type alias
- self.user_defined_types: Dict[str, TypeAlias] = {}
+ self.type_aliases: Dict[str, TypeAlias] = {}
def add_accesible_scopes(self) -> bool:
"""
@@ -95,8 +95,8 @@ def add_accesible_scopes(self) -> bool:
if not _dict_contain(new_scope.renaming, self.renaming):
self.renaming.update(new_scope.renaming)
learn_something = True
- if not _dict_contain(new_scope.user_defined_types, self.user_defined_types):
- self.user_defined_types.update(new_scope.user_defined_types)
+ if not _dict_contain(new_scope.type_aliases, self.type_aliases):
+ self.type_aliases.update(new_scope.type_aliases)
learn_something = True
return learn_something
diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py
index 02deb719e7..0633799e56 100644
--- a/slither/detectors/naming_convention/naming_convention.py
+++ b/slither/detectors/naming_convention/naming_convention.py
@@ -167,7 +167,7 @@ def _detect(self) -> List[Output]:
results.append(res)
else:
- if var.visibility == "private":
+ if var.visibility in ["private", "internal"]:
correct_naming = self.is_mixed_case_with_underscore(var.name)
else:
correct_naming = self.is_mixed_case(var.name)
diff --git a/slither/detectors/operations/cache_array_length.py b/slither/detectors/operations/cache_array_length.py
index e4d8cf2c69..59289ed0f7 100644
--- a/slither/detectors/operations/cache_array_length.py
+++ b/slither/detectors/operations/cache_array_length.py
@@ -216,9 +216,8 @@ def _detect(self):
for usage in non_optimal_array_len_usages:
info = [
"Loop condition ",
- f"`{usage.source_mapping.content}` ",
- f"({usage.source_mapping}) ",
- "should use cached array length instead of referencing `length` member "
+ usage,
+ " should use cached array length instead of referencing `length` member "
"of the storage array.\n ",
]
res = self.generate_result(info)
diff --git a/slither/detectors/statements/divide_before_multiply.py b/slither/detectors/statements/divide_before_multiply.py
index 6f199db414..334da592c0 100644
--- a/slither/detectors/statements/divide_before_multiply.py
+++ b/slither/detectors/statements/divide_before_multiply.py
@@ -2,7 +2,7 @@
Module detecting possible loss of precision due to divide before multiple
"""
from collections import defaultdict
-from typing import DefaultDict, List, Set, Tuple
+from typing import DefaultDict, List, Tuple
from slither.core.cfg.node import Node
from slither.core.declarations.contract import Contract
@@ -63,7 +63,7 @@ def is_assert(node: Node) -> bool:
# pylint: disable=too-many-branches
def _explore(
- to_explore: Set[Node], f_results: List[List[Node]], divisions: DefaultDict[LVALUE, List[Node]]
+ to_explore: List[Node], f_results: List[List[Node]], divisions: DefaultDict[LVALUE, List[Node]]
) -> None:
explored = set()
while to_explore: # pylint: disable=too-many-nested-blocks
@@ -114,7 +114,7 @@ def _explore(
f_results.append(node_results)
for son in node.sons:
- to_explore.add(son)
+ to_explore.append(son)
def detect_divide_before_multiply(
@@ -145,7 +145,7 @@ def detect_divide_before_multiply(
# track all the division results (and the assignment of the division results)
divisions: DefaultDict[LVALUE, List[Node]] = defaultdict(list)
- _explore({function.entry_point}, f_results, divisions)
+ _explore([function.entry_point], f_results, divisions)
for f_result in f_results:
results.append((function, f_result))
diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py
index 74a1cbcf0d..a118b1e650 100644
--- a/slither/solc_parsing/declarations/contract.py
+++ b/slither/solc_parsing/declarations/contract.py
@@ -291,10 +291,10 @@ def _parse_type_alias(self, item: Dict) -> None:
alias = item["name"]
alias_canonical = self._contract.name + "." + item["name"]
- user_defined_type = TypeAliasContract(original_type, alias, self.underlying_contract)
- user_defined_type.set_offset(item["src"], self.compilation_unit)
- self._contract.file_scope.user_defined_types[alias] = user_defined_type
- self._contract.file_scope.user_defined_types[alias_canonical] = user_defined_type
+ type_alias = TypeAliasContract(original_type, alias, self.underlying_contract)
+ type_alias.set_offset(item["src"], self.compilation_unit)
+ self._contract.type_aliases_as_dict[alias] = type_alias
+ self._contract.file_scope.type_aliases[alias_canonical] = type_alias
def _parse_struct(self, struct: Dict) -> None:
diff --git a/slither/solc_parsing/declarations/using_for_top_level.py b/slither/solc_parsing/declarations/using_for_top_level.py
index fe72e57809..bfed3c417c 100644
--- a/slither/solc_parsing/declarations/using_for_top_level.py
+++ b/slither/solc_parsing/declarations/using_for_top_level.py
@@ -152,7 +152,7 @@ def _propagate_global(self, type_name: Union[TypeAliasTopLevel, UserDefinedType]
if self._global:
for scope in self.compilation_unit.scopes.values():
if isinstance(type_name, TypeAliasTopLevel):
- for alias in scope.user_defined_types.values():
+ for alias in scope.type_aliases.values():
if alias == type_name:
scope.using_for_directives.add(self._using_for)
elif isinstance(type_name, UserDefinedType):
diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py
index 32f5afc584..3bbdd268ef 100644
--- a/slither/solc_parsing/expressions/find_variable.py
+++ b/slither/solc_parsing/expressions/find_variable.py
@@ -114,6 +114,8 @@ def find_top_level(
:return:
:rtype:
"""
+ if var_name in scope.type_aliases:
+ return scope.type_aliases[var_name], False
if var_name in scope.structures:
return scope.structures[var_name], False
@@ -205,6 +207,10 @@ def _find_in_contract(
if sig == var_name:
return modifier
+ type_aliases = contract.type_aliases_as_dict
+ if var_name in type_aliases:
+ return type_aliases[var_name]
+
# structures are looked on the contract declarer
structures = contract.structures_as_dict
if var_name in structures:
@@ -362,9 +368,6 @@ def find_variable(
if var_name in current_scope.renaming:
var_name = current_scope.renaming[var_name]
- if var_name in current_scope.user_defined_types:
- return current_scope.user_defined_types[var_name], False
-
# Use ret0/ret1 to help mypy
ret0 = _find_variable_from_ref_declaration(
referenced_declaration, direct_contracts, direct_functions
diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py
index 00ac3a5192..ecfecb4f03 100644
--- a/slither/solc_parsing/slither_compilation_unit_solc.py
+++ b/slither/solc_parsing/slither_compilation_unit_solc.py
@@ -344,10 +344,10 @@ def parse_top_level_from_loaded_json(self, data_loaded: Dict, filename: str) ->
original_type = ElementaryType(underlying_type["name"])
- user_defined_type = TypeAliasTopLevel(original_type, alias, scope)
- user_defined_type.set_offset(top_level_data["src"], self._compilation_unit)
- self._compilation_unit.user_defined_value_types[alias] = user_defined_type
- scope.user_defined_types[alias] = user_defined_type
+ type_alias = TypeAliasTopLevel(original_type, alias, scope)
+ type_alias.set_offset(top_level_data["src"], self._compilation_unit)
+ self._compilation_unit.type_aliases[alias] = type_alias
+ scope.type_aliases[alias] = type_alias
else:
raise SlitherException(f"Top level {top_level_data[self.get_key()]} not supported")
diff --git a/slither/solc_parsing/solidity_types/type_parsing.py b/slither/solc_parsing/solidity_types/type_parsing.py
index e12290722f..c03b8e6562 100644
--- a/slither/solc_parsing/solidity_types/type_parsing.py
+++ b/slither/solc_parsing/solidity_types/type_parsing.py
@@ -235,7 +235,7 @@ def parse_type(
sl: "SlitherCompilationUnit"
renaming: Dict[str, str]
- user_defined_types: Dict[str, TypeAlias]
+ type_aliases: Dict[str, TypeAlias]
enums_direct_access: List["Enum"] = []
# Note: for convenicence top level functions use the same parser than function in contract
# but contract_parser is set to None
@@ -247,13 +247,13 @@ def parse_type(
sl = caller_context.compilation_unit
next_context = caller_context
renaming = {}
- user_defined_types = sl.user_defined_value_types
+ type_aliases = sl.type_aliases
else:
assert isinstance(caller_context, FunctionSolc)
sl = caller_context.underlying_function.compilation_unit
next_context = caller_context.slither_parser
renaming = caller_context.underlying_function.file_scope.renaming
- user_defined_types = caller_context.underlying_function.file_scope.user_defined_types
+ type_aliases = caller_context.underlying_function.file_scope.type_aliases
structures_direct_access = sl.structures_top_level
all_structuress = [c.structures for c in sl.contracts]
all_structures = [item for sublist in all_structuress for item in sublist]
@@ -299,7 +299,7 @@ def parse_type(
functions = list(scope.functions)
renaming = scope.renaming
- user_defined_types = scope.user_defined_types
+ type_aliases = scope.type_aliases
elif isinstance(caller_context, (ContractSolc, FunctionSolc)):
sl = caller_context.compilation_unit
if isinstance(caller_context, FunctionSolc):
@@ -329,7 +329,7 @@ def parse_type(
functions = contract.functions + contract.modifiers
renaming = scope.renaming
- user_defined_types = scope.user_defined_types
+ type_aliases = scope.type_aliases
else:
raise ParsingError(f"Incorrect caller context: {type(caller_context)}")
@@ -343,8 +343,8 @@ def parse_type(
name = t.name
if name in renaming:
name = renaming[name]
- if name in user_defined_types:
- return user_defined_types[name]
+ if name in type_aliases:
+ return type_aliases[name]
return _find_from_type_name(
name,
functions,
@@ -365,9 +365,9 @@ def parse_type(
name = t["typeDescriptions"]["typeString"]
if name in renaming:
name = renaming[name]
- if name in user_defined_types:
- _add_type_references(user_defined_types[name], t["src"], sl)
- return user_defined_types[name]
+ if name in type_aliases:
+ _add_type_references(type_aliases[name], t["src"], sl)
+ return type_aliases[name]
type_found = _find_from_type_name(
name,
functions,
@@ -386,9 +386,9 @@ def parse_type(
name = t["attributes"][type_name_key]
if name in renaming:
name = renaming[name]
- if name in user_defined_types:
- _add_type_references(user_defined_types[name], t["src"], sl)
- return user_defined_types[name]
+ if name in type_aliases:
+ _add_type_references(type_aliases[name], t["src"], sl)
+ return type_aliases[name]
type_found = _find_from_type_name(
name,
functions,
@@ -407,8 +407,8 @@ def parse_type(
name = t["name"]
if name in renaming:
name = renaming[name]
- if name in user_defined_types:
- return user_defined_types[name]
+ if name in type_aliases:
+ return type_aliases[name]
type_found = _find_from_type_name(
name,
functions,
diff --git a/slither/utils/expression_manipulations.py b/slither/utils/expression_manipulations.py
index 75d97042c2..32b88e9b32 100644
--- a/slither/utils/expression_manipulations.py
+++ b/slither/utils/expression_manipulations.py
@@ -147,7 +147,7 @@ def convert_expressions(
for next_expr in expression.expressions:
# TODO: can we get rid of `NoneType` expressions in `TupleExpression`?
# montyly: this might happen with unnamed tuple (ex: (,,,) = f()), but it needs to be checked
- if next_expr:
+ if next_expr is not None:
if self.conditional_not_ahead(
next_expr, true_expression, false_expression, f_expressions
@@ -158,6 +158,9 @@ def convert_expressions(
true_expression.expressions[-1],
false_expression.expressions[-1],
)
+ else:
+ true_expression.expressions.append(None)
+ false_expression.expressions.append(None)
def convert_index_access(
self, next_expr: IndexAccess, true_expression: Expression, false_expression: Expression
diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py
index 0e265f909c..9240b70294 100644
--- a/slither/visitors/slithir/expression_to_slithir.py
+++ b/slither/visitors/slithir/expression_to_slithir.py
@@ -529,8 +529,8 @@ def _post_member_access(self, expression: MemberAccess) -> None:
# contract A { type MyInt is int}
# contract B { function f() public{ A.MyInt test = A.MyInt.wrap(1);}}
# The logic is handled by _post_call_expression
- if expression.member_name in expr.file_scope.user_defined_types:
- set_val(expression, expr.file_scope.user_defined_types[expression.member_name])
+ if expression.member_name in expr.file_scope.type_aliases:
+ set_val(expression, expr.file_scope.type_aliases[expression.member_name])
return
# Lookup errors referred to as member of contract e.g. Test.myError.selector
if expression.member_name in expr.custom_errors_as_dict:
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt
index 456c702a58..c2a5023a6f 100644
--- a/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt
+++ b/tests/e2e/detectors/snapshots/detectors__detector_CacheArrayLength_0_8_17_CacheArrayLength_sol__0.txt
@@ -1,20 +1,20 @@
-Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#109) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition k_scope_17 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#133) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#161) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i_scope_23 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#172) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#172) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#37) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `j < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#126) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition j_scope_11 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#109) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#133) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i_scope_4 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#68) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#68) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i_scope_22 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#167) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `k < array2.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#99) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition k_scope_9 < array2.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#99) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#167) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i_scope_6 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#80) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#37) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition j_scope_15 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#126) should use cached array length instead of referencing `length` member of the storage array.
-Loop condition `i < array.length` (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#80) should use cached array length instead of referencing `length` member of the storage array.
+Loop condition i_scope_21 < array.length (tests/e2e/detectors/test_data/cache-array-length/0.8.17/CacheArrayLength.sol#161) should use cached array length instead of referencing `length` member of the storage array.
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt
index ed4177ca17..e4a643678d 100644
--- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt
+++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_4_25_naming_convention_sol__0.txt
@@ -1,10 +1,10 @@
Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#14-16) is not in CapWords
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is not in mixedCase
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is not in mixedCase
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#70) is single letter l, O, or I, which should not be used
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is not in mixedCase
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is not in mixedCase
Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#11) is not in mixedCase
@@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_c
Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#6) is not in CapWords
-Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#59) is not in mixedCase
+Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#60) is not in mixedCase
-Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#56) is not in mixedCase
+Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#57) is not in mixedCase
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#69) is single letter l, O, or I, which should not be used
Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#23) is not in CapWords
@@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.4.25
Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#30-33) is not in mixedCase
-Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#67) is single letter l, O, or I, which should not be used
+Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#68) is single letter l, O, or I, which should not be used
Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol#35) is not in mixedCase
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt
index 35c11193f5..96f6aab3c6 100644
--- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt
+++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_5_16_naming_convention_sol__0.txt
@@ -1,10 +1,10 @@
Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#14-16) is not in CapWords
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is not in mixedCase
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is not in mixedCase
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#70) is single letter l, O, or I, which should not be used
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is not in mixedCase
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is not in mixedCase
Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#11) is not in mixedCase
@@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_c
Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#6) is not in CapWords
-Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#59) is not in mixedCase
+Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#60) is not in mixedCase
-Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#56) is not in mixedCase
+Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#57) is not in mixedCase
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#69) is single letter l, O, or I, which should not be used
Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#23) is not in CapWords
@@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.5.16
Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#30-33) is not in mixedCase
-Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#67) is single letter l, O, or I, which should not be used
+Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#68) is single letter l, O, or I, which should not be used
Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol#35) is not in mixedCase
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt
index f692e211b8..f1986fb781 100644
--- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt
+++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_6_11_naming_convention_sol__0.txt
@@ -1,10 +1,10 @@
Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#14-16) is not in CapWords
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is not in mixedCase
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is not in mixedCase
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is single letter l, O, or I, which should not be used
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#70) is single letter l, O, or I, which should not be used
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is not in mixedCase
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is not in mixedCase
Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#11) is not in mixedCase
@@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_c
Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#6) is not in CapWords
-Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#59) is not in mixedCase
+Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#60) is not in mixedCase
-Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#56) is not in mixedCase
+Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#57) is not in mixedCase
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#69) is single letter l, O, or I, which should not be used
Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#23) is not in CapWords
@@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.6.11
Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#30-33) is not in mixedCase
-Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#67) is single letter l, O, or I, which should not be used
+Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#68) is single letter l, O, or I, which should not be used
Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol#35) is not in mixedCase
diff --git a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt
index af17cabe8f..b471cbfa2f 100644
--- a/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt
+++ b/tests/e2e/detectors/snapshots/detectors__detector_NamingConvention_0_7_6_naming_convention_sol__0.txt
@@ -1,10 +1,10 @@
Struct naming.test (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#14-16) is not in CapWords
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is not in mixedCase
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is not in mixedCase
-Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is single letter l, O, or I, which should not be used
+Variable T.I (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#70) is single letter l, O, or I, which should not be used
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is not in mixedCase
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is not in mixedCase
Variable naming.Var_One (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#11) is not in mixedCase
@@ -14,11 +14,11 @@ Contract naming (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_co
Enum naming.numbers (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#6) is not in CapWords
-Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#59) is not in mixedCase
+Parameter T.test(uint256,uint256)._used (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#60) is not in mixedCase
-Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#56) is not in mixedCase
+Variable T._myPublicVar (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#57) is not in mixedCase
-Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used
+Variable T.O (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#69) is single letter l, O, or I, which should not be used
Event naming.event_(uint256) (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#23) is not in CapWords
@@ -26,7 +26,7 @@ Modifier naming.CantDo() (tests/e2e/detectors/test_data/naming-convention/0.7.6/
Function naming.GetOne() (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#30-33) is not in mixedCase
-Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#67) is single letter l, O, or I, which should not be used
+Variable T.l (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#68) is single letter l, O, or I, which should not be used
Parameter naming.setInt(uint256,uint256).Number2 (tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol#35) is not in mixedCase
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol
index 7181ca9110..add7867e07 100644
--- a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol
+++ b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol
@@ -53,7 +53,8 @@ contract Test {
contract T {
uint private _myPrivateVar;
- uint _myPublicVar;
+ uint internal _myInternalVar;
+ uint public _myPublicVar;
function test(uint _unused, uint _used) public returns(uint){
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip
index c7aaae071d..fe35f0c006 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip and b/tests/e2e/detectors/test_data/naming-convention/0.4.25/naming_convention.sol-0.4.25.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip b/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip
index 2726a771d1..b8c6c58c1d 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip and b/tests/e2e/detectors/test_data/naming-convention/0.4.25/no_warning_for_public_constants.sol-0.4.25.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol
index 7181ca9110..add7867e07 100644
--- a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol
+++ b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol
@@ -53,7 +53,8 @@ contract Test {
contract T {
uint private _myPrivateVar;
- uint _myPublicVar;
+ uint internal _myInternalVar;
+ uint public _myPublicVar;
function test(uint _unused, uint _used) public returns(uint){
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip
index da900f1f69..6c732f786e 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip and b/tests/e2e/detectors/test_data/naming-convention/0.5.16/naming_convention.sol-0.5.16.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip b/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip
index 160fee3a22..600f68386b 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip and b/tests/e2e/detectors/test_data/naming-convention/0.5.16/no_warning_for_public_constants.sol-0.5.16.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol
index 7181ca9110..add7867e07 100644
--- a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol
+++ b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol
@@ -53,7 +53,8 @@ contract Test {
contract T {
uint private _myPrivateVar;
- uint _myPublicVar;
+ uint internal _myInternalVar;
+ uint public _myPublicVar;
function test(uint _unused, uint _used) public returns(uint){
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip
index 3e6277ac1b..b916970874 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip and b/tests/e2e/detectors/test_data/naming-convention/0.6.11/naming_convention.sol-0.6.11.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip b/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip
index 67f8eff7ee..ed813d07b9 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip and b/tests/e2e/detectors/test_data/naming-convention/0.6.11/no_warning_for_public_constants.sol-0.6.11.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol
index 7181ca9110..add7867e07 100644
--- a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol
+++ b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol
@@ -53,7 +53,8 @@ contract Test {
contract T {
uint private _myPrivateVar;
- uint _myPublicVar;
+ uint internal _myInternalVar;
+ uint public _myPublicVar;
function test(uint _unused, uint _used) public returns(uint){
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip
index cc9d43c582..f1e3a8ad55 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip and b/tests/e2e/detectors/test_data/naming-convention/0.7.6/naming_convention.sol-0.7.6.zip differ
diff --git a/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip b/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip
index 7b304b5c0c..9f2c1a1a7d 100644
Binary files a/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip and b/tests/e2e/detectors/test_data/naming-convention/0.7.6/no_warning_for_public_constants.sol-0.7.6.zip differ
diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py
index d6cc1b8b4c..2da4cf1e26 100644
--- a/tests/e2e/solc_parsing/test_ast_parsing.py
+++ b/tests/e2e/solc_parsing/test_ast_parsing.py
@@ -459,6 +459,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
["0.6.9", "0.7.6", "0.8.16"],
),
Test("user_defined_operators-0.8.19.sol", ["0.8.19"]),
+ Test("type-aliases.sol", ["0.8.19"]),
Test("enum-max-min.sol", ["0.8.19"]),
]
# create the output folder if needed
diff --git a/tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip b/tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip
new file mode 100644
index 0000000000..0c4d2b1c5e
Binary files /dev/null and b/tests/e2e/solc_parsing/test_data/compile/type-aliases.sol-0.8.19-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/expected/type-aliases.sol-0.8.19-compact.json b/tests/e2e/solc_parsing/test_data/expected/type-aliases.sol-0.8.19-compact.json
new file mode 100644
index 0000000000..e76cc99ffd
--- /dev/null
+++ b/tests/e2e/solc_parsing/test_data/expected/type-aliases.sol-0.8.19-compact.json
@@ -0,0 +1,6 @@
+{
+ "OtherTest": {
+ "myfunc()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n"
+ },
+ "DeleteTest": {}
+}
\ No newline at end of file
diff --git a/tests/e2e/solc_parsing/test_data/type-aliases.sol b/tests/e2e/solc_parsing/test_data/type-aliases.sol
new file mode 100644
index 0000000000..53fdaabeb8
--- /dev/null
+++ b/tests/e2e/solc_parsing/test_data/type-aliases.sol
@@ -0,0 +1,20 @@
+
+struct Z {
+ int x;
+ int y;
+}
+
+contract OtherTest {
+ struct Z {
+ int x;
+ int y;
+ }
+
+ function myfunc() external {
+ Z memory z = Z(2,3);
+ }
+}
+
+contract DeleteTest {
+ type Z is int;
+}
diff --git a/tests/unit/core/test_source_mapping.py b/tests/unit/core/test_source_mapping.py
index fe53359777..55eb082950 100644
--- a/tests/unit/core/test_source_mapping.py
+++ b/tests/unit/core/test_source_mapping.py
@@ -85,15 +85,13 @@ def test_references_user_defined_aliases(solc_binary_path):
file = Path(SRC_MAPPING_TEST_ROOT, "ReferencesUserDefinedAliases.sol").as_posix()
slither = Slither(file, solc=solc_path)
- alias_top_level = slither.compilation_units[0].user_defined_value_types["aliasTopLevel"]
+ alias_top_level = slither.compilation_units[0].type_aliases["aliasTopLevel"]
assert len(alias_top_level.references) == 2
lines = _sort_references_lines(alias_top_level.references)
assert lines == [12, 16]
alias_contract_level = (
- slither.compilation_units[0]
- .contracts[0]
- .file_scope.user_defined_types["C.aliasContractLevel"]
+ slither.compilation_units[0].contracts[0].file_scope.type_aliases["C.aliasContractLevel"]
)
assert len(alias_contract_level.references) == 2
lines = _sort_references_lines(alias_contract_level.references)
diff --git a/tests/unit/slithir/test_data/ternary_expressions.sol b/tests/unit/slithir/test_data/ternary_expressions.sol
index ebfb96e801..1ccd51d34d 100644
--- a/tests/unit/slithir/test_data/ternary_expressions.sol
+++ b/tests/unit/slithir/test_data/ternary_expressions.sol
@@ -1,6 +1,6 @@
interface Test {
function test() external payable returns (uint);
- function testTuple() external payable returns (uint, uint);
+ function testTuple(uint) external payable returns (uint, uint);
}
contract C {
// TODO
@@ -36,21 +36,23 @@ contract C {
}
// Unused tuple variable
- function g(address one) public {
- (, uint x) = Test(one).testTuple();
- }
-
uint[] myIntegers;
- function _h(uint c) internal returns(uint) {
- return c;
- }
- function h(bool cond, uint a, uint b) public {
- uint d = _h(
- myIntegers[cond ? a : b]
- );
+ function g(address one, bool cond, uint a, uint b) public {
+ (, uint x) = Test(one).testTuple(myIntegers[cond ? a : b]);
}
-
- function i(bool cond) public {
+
+ function h(bool cond) public {
bytes memory a = new bytes(cond ? 1 : 2);
}
}
+
+contract D {
+ function values(uint n) internal returns (uint, uint) {
+ return (0, 1);
+ }
+
+ function a(uint n) external {
+ uint a;
+ (a,) = values(n > 0 ? 1 : 0);
+ }
+}
diff --git a/tests/unit/slithir/test_ternary_expressions.py b/tests/unit/slithir/test_ternary_expressions.py
index 712c9582b0..bf8556f85d 100644
--- a/tests/unit/slithir/test_ternary_expressions.py
+++ b/tests/unit/slithir/test_ternary_expressions.py
@@ -16,30 +16,53 @@ def test_ternary_conversions(solc_binary_path) -> None:
"""This tests that true and false sons define the same number of variables that the father node declares"""
solc_path = solc_binary_path("0.8.0")
slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path)
- for contract in slither.contracts:
- if not contract.is_signature_only:
- for function in contract.functions:
- vars_declared = 0
- vars_assigned = 0
- for node in function.nodes:
- if node.type in [NodeType.IF, NodeType.IFLOOP]:
-
- # Iterate over true and false son
- for inner_node in node.sons:
- # Count all variables declared
- expression = inner_node.expression
- if isinstance(
- expression, (AssignmentOperation, NewElementaryType, CallExpression)
- ):
- var_expr = expression.expression_left
- # Only tuples declare more than one var
- if isinstance(var_expr, TupleExpression):
- vars_declared += len(var_expr.expressions)
- else:
- vars_declared += 1
-
- for ir in inner_node.irs:
- # Count all variables defined
- if isinstance(ir, (Assignment, Unpack)):
- vars_assigned += 1
- assert vars_declared == vars_assigned and vars_assigned != 0
+ contract = next(c for c in slither.contracts if c.name == "C")
+ for function in contract.functions:
+ vars_declared = 0
+ vars_assigned = 0
+ for node in function.nodes:
+ if node.type in [NodeType.IF, NodeType.IFLOOP]:
+
+ # Iterate over true and false son
+ for inner_node in node.sons:
+ # Count all variables declared
+ expression = inner_node.expression
+ if isinstance(
+ expression, (AssignmentOperation, NewElementaryType, CallExpression)
+ ):
+ var_expr = expression.expression_left
+ # Only tuples declare more than one var
+ if isinstance(var_expr, TupleExpression):
+ vars_declared += len(var_expr.expressions)
+ else:
+ vars_declared += 1
+
+ for ir in inner_node.irs:
+ # Count all variables defined
+ if isinstance(ir, (Assignment, Unpack)):
+ vars_assigned += 1
+ assert vars_declared == vars_assigned and vars_assigned != 0
+
+
+def test_ternary_tuple(solc_binary_path) -> None:
+ """
+ Test that in the ternary liftings of an assignment of the form `(z, ) = ...`,
+ we obtain `z` from an unpack operation in both lifitings
+ """
+ solc_path = solc_binary_path("0.8.0")
+ slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix(), solc=solc_path)
+ contract = next(c for c in slither.contracts if c.name == "D")
+ fn = next(f for f in contract.functions if f.name == "a")
+
+ if_nodes = [n for n in fn.nodes if n.type == NodeType.IF]
+ assert len(if_nodes) == 1
+
+ if_node = if_nodes[0]
+ assert isinstance(if_node.son_true.expression, AssignmentOperation)
+ assert (
+ len([ir for ir in if_node.son_true.all_slithir_operations() if isinstance(ir, Unpack)]) == 1
+ )
+ assert (
+ len([ir for ir in if_node.son_false.all_slithir_operations() if isinstance(ir, Unpack)])
+ == 1
+ )