diff --git a/.github/workflows/IR.yml b/.github/workflows/IR.yml index 434cef75b..891de2bfb 100644 --- a/.github/workflows/IR.yml +++ b/.github/workflows/IR.yml @@ -34,9 +34,14 @@ jobs: - name: Install dependencies run: | pip install ".[dev]" - solc-select install all - solc-select use 0.8.11 + solc-select install 0.5.0 + solc-select use 0.8.11 --always-install + + - name: Install old solc + if: matrix.os == 'ubuntu-latest' + run: solc-select install 0.4.0 + - name: Test with pytest run: | - pytest tests/test_ssa_generation.py + pytest tests/test_ssa_generation.py \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6503d2b62..9913e487d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,8 +55,9 @@ jobs: - name: Install dependencies run: | pip install ".[dev]" - solc-select install all - solc-select use 0.5.1 + solc-select use 0.4.25 --always-install + solc-select use 0.8.0 --always-install + solc-select use 0.5.1 --always-install pip install typing_extensions==4.1.1 pip install importlib_metadata==4.8.3 diff --git a/.github/workflows/detectors.yml b/.github/workflows/detectors.yml index 8f3b45d15..15aa8a5dd 100644 --- a/.github/workflows/detectors.yml +++ b/.github/workflows/detectors.yml @@ -35,8 +35,7 @@ jobs: run: | pip install ".[dev]" - solc-select install all - solc-select use 0.7.3 + solc-select use 0.7.3 --always-install - name: Test with pytest run: | pytest tests/test_detectors.py diff --git a/.github/workflows/doctor.yml b/.github/workflows/doctor.yml new file mode 100644 index 000000000..b6124216a --- /dev/null +++ b/.github/workflows/doctor.yml @@ -0,0 +1,87 @@ +--- +name: CI + +defaults: + run: + shell: bash + +on: + workflow_dispatch: + pull_request: + paths: + - 'slither/tools/doctor/**' + - '.github/workflows/doctor.yml' + +jobs: + slither-doctor: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "windows-2022"] + python: ["3.8", "3.9", "3.10", "3.11"] + exclude: + # strange failure + - os: windows-2022 + python: 3.8 + steps: + - uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + + - name: Try system-wide Slither + run: | + echo "::group::Install slither" + pip3 install . + echo "::endgroup::" + + # escape cwd so python doesn't pick up local module + cd / + + echo "::group::Via module" + python3 -m slither.tools.doctor . + echo "::endgroup::" + + echo "::group::Via binary" + slither-doctor . + echo "::endgroup::" + + - name: Try user Slither + run: | + echo "::group::Install slither" + pip3 install --user . + echo "::endgroup::" + + # escape cwd so python doesn't pick up local module + cd / + + echo "::group::Via module" + python3 -m slither.tools.doctor . + echo "::endgroup::" + + echo "::group::Via binary" + slither-doctor . + echo "::endgroup::" + + - name: Try venv Slither + run: | + echo "::group::Install slither" + python3 -m venv venv + source venv/bin/activate || source venv/Scripts/activate + hash -r + pip3 install . + echo "::endgroup::" + + # escape cwd so python doesn't pick up local module + cd / + + echo "::group::Via module" + python3 -m slither.tools.doctor . + echo "::endgroup::" + + echo "::group::Via binary" + slither-doctor . + echo "::endgroup::" diff --git a/.github/workflows/features.yml b/.github/workflows/features.yml index 49db14793..5007fd7bf 100644 --- a/.github/workflows/features.yml +++ b/.github/workflows/features.yml @@ -35,8 +35,7 @@ jobs: run: | pip install ".[dev]" - solc-select install all - solc-select use 0.8.0 + solc-select use 0.8.0 --always-install cd tests/test_node_modules/ npm install hardhat diff --git a/CODEOWNERS b/CODEOWNERS index e76e5a2bb..c92f0d79d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,6 @@ -* @montyly @0xalpharush @smonicas -/slither/tools/read_storage @0xalpharush -/slither/slithir/ @montyly -/slither/analyses/ @montyly +* @montyly @0xalpharush @smonicas +/slither/tools/read_storage/ @0xalpharush +/slither/tools/doctor/ @elopez +/slither/slithir/ @montyly +/slither/analyses/ @montyly +/.github/workflows/ @elopez diff --git a/Dockerfile b/Dockerfile index 71bb9f57f..d0a7d67be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM ubuntu:jammy AS python-wheels RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ gcc \ + git \ python3-dev \ python3-pip \ && rm -rf /var/lib/apt/lists/* @@ -9,7 +10,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins COPY . /slither RUN cd /slither && \ - echo pip3 install --no-cache-dir --upgrade pip && \ + pip3 install --no-cache-dir --upgrade pip && \ pip3 wheel -w /wheels . solc-select pip setuptools wheel @@ -44,7 +45,7 @@ ENV PATH="/home/slither/.local/bin:${PATH}" # no-index ensures we install the freshly-built wheels RUN --mount=type=bind,target=/mnt,source=/wheels,from=python-wheels \ - pip3 install --user --no-cache-dir --upgrade --no-index --find-links /mnt pip slither-analyzer solc-select + pip3 install --user --no-cache-dir --upgrade --no-index --find-links /mnt --no-deps /mnt/*.whl RUN solc-select install 0.4.25 && solc-select use 0.4.25 diff --git a/setup.py b/setup.py index 86db4fa9a..cc125011e 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ setup( packages=find_packages(), python_requires=">=3.8", install_requires=[ + "packaging", "prettytable>=0.7.2", "pycryptodome>=3.4.6", # "crytic-compile>=0.2.4", @@ -46,6 +47,7 @@ setup( "slither-mutate = slither.tools.mutator.__main__:main", "slither-read-storage = slither.tools.read_storage.__main__:main", "slither-doctor = slither.tools.doctor.__main__:main", + "slither-documentation = slither.tools.documentation.__main__:main", ] }, ) diff --git a/slither/__main__.py b/slither/__main__.py index 75707af06..9d611532e 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -24,6 +24,7 @@ from slither.detectors.abstract_detector import AbstractDetector, DetectorClassi from slither.printers import all_printers from slither.printers.abstract_printer import AbstractPrinter from slither.slither import Slither +from slither.utils import codex from slither.utils.output import output_to_json, output_to_zip, output_to_sarif, ZIP_TYPES_ACCEPTED from slither.utils.output_capture import StandardOutputCapture from slither.utils.colors import red, set_colorization_enabled @@ -314,7 +315,6 @@ def parse_args( "Checklist (consider using https://github.com/crytic/slither-action)" ) group_misc = parser.add_argument_group("Additional options") - group_codex = parser.add_argument_group("Codex (https://beta.openai.com/docs/guides/code)") group_detector.add_argument( "--detect", @@ -555,47 +555,14 @@ def parse_args( default=False, ) - group_codex.add_argument( - "--codex", - help="Enable codex (require an OpenAI API Key)", - action="store_true", - default=defaults_flag_in_config["codex"], - ) - - group_codex.add_argument( - "--codex-log", - help="Log codex queries (in crytic_export/codex/)", + group_misc.add_argument( + "--no-fail", + help="Do not fail in case of parsing (echidna mode only)", action="store_true", - default=False, - ) - - group_codex.add_argument( - "--codex-contracts", - help="Comma separated list of contracts to submit to OpenAI Codex", - action="store", - default=defaults_flag_in_config["codex_contracts"], + default=defaults_flag_in_config["no_fail"], ) - group_codex.add_argument( - "--codex-model", - help="Name of the Codex model to use (affects pricing). Defaults to 'text-davinci-003'", - action="store", - default=defaults_flag_in_config["codex_model"], - ) - - group_codex.add_argument( - "--codex-temperature", - help="Temperature to use with Codex. Lower number indicates a more precise answer while higher numbers return more creative answers. Defaults to 0", - action="store", - default=defaults_flag_in_config["codex_temperature"], - ) - - group_codex.add_argument( - "--codex-max-tokens", - help="Maximum amount of tokens to use on the response. This number plus the size of the prompt can be no larger than the limit (4097 for text-davinci-003)", - action="store", - default=defaults_flag_in_config["codex_max_tokens"], - ) + codex.init_parser(parser) # debugger command parser.add_argument("--debug", help=argparse.SUPPRESS, action="store_true", default=False) diff --git a/slither/core/children/child_function.py b/slither/core/children/child_function.py index cb4f0109f..5367320ca 100644 --- a/slither/core/children/child_function.py +++ b/slither/core/children/child_function.py @@ -5,11 +5,11 @@ if TYPE_CHECKING: class ChildFunction: - def __init__(self): + def __init__(self) -> None: super().__init__() self._function = None - def set_function(self, function: "Function"): + def set_function(self, function: "Function") -> None: self._function = function @property diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index a4624feec..2fdea7210 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -220,6 +220,9 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu self._id: Optional[str] = None + # To be improved with a parsing of the documentation + self.has_documentation: bool = False + ################################################################################### ################################################################################### # region General properties diff --git a/slither/core/expressions/identifier.py b/slither/core/expressions/identifier.py index ab40472a4..0b10c5615 100644 --- a/slither/core/expressions/identifier.py +++ b/slither/core/expressions/identifier.py @@ -7,7 +7,7 @@ if TYPE_CHECKING: class Identifier(ExpressionTyped): - def __init__(self, value): + def __init__(self, value) -> None: super().__init__() self._value: "Variable" = value @@ -15,5 +15,5 @@ class Identifier(ExpressionTyped): def value(self) -> "Variable": return self._value - def __str__(self): + def __str__(self) -> str: return str(self._value) diff --git a/slither/core/expressions/literal.py b/slither/core/expressions/literal.py index 87090b93f..2eaeb715d 100644 --- a/slither/core/expressions/literal.py +++ b/slither/core/expressions/literal.py @@ -10,16 +10,25 @@ if TYPE_CHECKING: class Literal(Expression): - def __init__(self, value, custom_type, subdenomination=None): + def __init__( + self, value: Union[int, str], custom_type: "Type", subdenomination: Optional[str] = None + ): super().__init__() - self._value: Union[int, str] = value + self._value = value self._type = custom_type - self._subdenomination: Optional[str] = subdenomination + self._subdenomination = subdenomination @property def value(self) -> Union[int, str]: return self._value + @property + def converted_value(self) -> Union[int, str]: + """Return the value of the literal, accounting for subdenomination e.g. ether""" + if self.subdenomination: + return convert_subdenomination(self._value, self.subdenomination) + return self._value + @property def type(self) -> "Type": return self._type @@ -28,9 +37,9 @@ class Literal(Expression): def subdenomination(self) -> Optional[str]: return self._subdenomination - def __str__(self): + def __str__(self) -> str: if self.subdenomination: - return str(convert_subdenomination(self._value, self.subdenomination)) + return str(self.converted_value) if self.type in Int + Uint + Fixed + Ufixed + ["address"]: return str(convert_string_to_int(self._value)) @@ -38,7 +47,7 @@ class Literal(Expression): # be sure to handle any character return str(self._value) - def __eq__(self, other): + def __eq__(self, other) -> bool: if not isinstance(other, Literal): return False return (self.value, self.subdenomination) == (other.value, other.subdenomination) diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 691699067..66b8fc430 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -92,6 +92,10 @@ class SlitherCore(Context): # But we allow to alter this (ex: file.sol:1) for vscode integration self.line_prefix: str = "#" + # Use by the echidna printer + # If true, partial analysis is allowed + self.no_fail = False + @property def compilation_units(self) -> List[SlitherCompilationUnit]: return list(self._compilation_units) diff --git a/slither/core/variables/local_variable.py b/slither/core/variables/local_variable.py index 5eb641fb4..7b7b4f8bc 100644 --- a/slither/core/variables/local_variable.py +++ b/slither/core/variables/local_variable.py @@ -11,11 +11,11 @@ from slither.core.declarations.structure import Structure class LocalVariable(ChildFunction, Variable): - def __init__(self): + def __init__(self) -> None: super().__init__() self._location: Optional[str] = None - def set_location(self, loc: str): + def set_location(self, loc: str) -> None: self._location = loc @property diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index fb2e3c731..1cab317ad 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -19,7 +19,8 @@ from .reentrancy.reentrancy_eth import ReentrancyEth from .reentrancy.reentrancy_no_gas import ReentrancyNoGas from .reentrancy.reentrancy_events import ReentrancyEvent from .variables.unused_state_variables import UnusedStateVars -from .variables.possible_const_state_variables import ConstCandidateStateVars +from .variables.could_be_constant import CouldBeConstant +from .variables.could_be_immutable import CouldBeImmutable from .statements.tx_origin import TxOrigin from .statements.assembly import Assembly from .operations.low_level_calls import LowLevelCalls diff --git a/slither/detectors/variables/could_be_constant.py b/slither/detectors/variables/could_be_constant.py new file mode 100644 index 000000000..0a294dd8d --- /dev/null +++ b/slither/detectors/variables/could_be_constant.py @@ -0,0 +1,45 @@ +from typing import List, Dict +from slither.utils.output import Output +from slither.core.compilation_unit import SlitherCompilationUnit +from slither.formatters.variables.unchanged_state_variables import custom_format +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from .unchanged_state_variables import UnchangedStateVariables + + +class CouldBeConstant(AbstractDetector): + """ + State variables that could be declared as constant. + Not all types for constants are implemented in Solidity as of 0.4.25. + The only supported types are value types and strings (ElementaryType). + Reference: https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables + """ + + ARGUMENT = "constable-states" + HELP = "State variables that could be declared constant" + IMPACT = DetectorClassification.OPTIMIZATION + CONFIDENCE = DetectorClassification.HIGH + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant" + + WIKI_TITLE = "State variables that could be declared constant" + WIKI_DESCRIPTION = "State variables that are not updated following deployment should be declared constant to save gas." + WIKI_RECOMMENDATION = "Add the `constant` attribute to state variables that never change." + + def _detect(self) -> List[Output]: + """Detect state variables that could be constant""" + results = {} + + unchanged_state_variables = UnchangedStateVariables(self.compilation_unit) + unchanged_state_variables.detect() + + for variable in unchanged_state_variables.constant_candidates: + results[variable.canonical_name] = self.generate_result( + [variable, " should be constant \n"] + ) + + # Order by canonical name for deterministic results + return [results[k] for k in sorted(results)] + + @staticmethod + def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: + custom_format(compilation_unit, result, "constant") diff --git a/slither/detectors/variables/could_be_immutable.py b/slither/detectors/variables/could_be_immutable.py new file mode 100644 index 000000000..a9ecb60cd --- /dev/null +++ b/slither/detectors/variables/could_be_immutable.py @@ -0,0 +1,44 @@ +from typing import List, Dict +from slither.utils.output import Output +from slither.core.compilation_unit import SlitherCompilationUnit +from slither.formatters.variables.unchanged_state_variables import custom_format +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from .unchanged_state_variables import UnchangedStateVariables + + +class CouldBeImmutable(AbstractDetector): + """ + State variables that could be declared immutable. + # Immutable attribute available in Solidity 0.6.5 and above + # https://blog.soliditylang.org/2020/04/06/solidity-0.6.5-release-announcement/ + """ + + # VULNERABLE_SOLC_VERSIONS = + ARGUMENT = "immutable-states" + HELP = "State variables that could be declared immutable" + IMPACT = DetectorClassification.OPTIMIZATION + CONFIDENCE = DetectorClassification.HIGH + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable" + + WIKI_TITLE = "State variables that could be declared immutable" + WIKI_DESCRIPTION = "State variables that are not updated following deployment should be declared immutable to save gas." + WIKI_RECOMMENDATION = "Add the `immutable` attribute to state variables that never change or are set only in the constructor." + + def _detect(self) -> List[Output]: + """Detect state variables that could be immutable""" + results = {} + unchanged_state_variables = UnchangedStateVariables(self.compilation_unit) + unchanged_state_variables.detect() + + for variable in unchanged_state_variables.immutable_candidates: + results[variable.canonical_name] = self.generate_result( + [variable, " should be immutable \n"] + ) + + # Order by canonical name for deterministic results + return [results[k] for k in sorted(results)] + + @staticmethod + def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: + custom_format(compilation_unit, result, "immutable") diff --git a/slither/detectors/variables/possible_const_state_variables.py b/slither/detectors/variables/possible_const_state_variables.py deleted file mode 100644 index e5b35bb79..000000000 --- a/slither/detectors/variables/possible_const_state_variables.py +++ /dev/null @@ -1,125 +0,0 @@ -""" -Module detecting state variables that could be declared as constant -""" -from typing import Set, List, Dict - -from slither.core.compilation_unit import SlitherCompilationUnit -from slither.core.solidity_types.elementary_type import ElementaryType -from slither.core.solidity_types.user_defined_type import UserDefinedType -from slither.core.variables.variable import Variable -from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification -from slither.utils.output import Output -from slither.visitors.expression.export_values import ExportValues -from slither.core.declarations import Contract, Function -from slither.core.declarations.solidity_variables import SolidityFunction -from slither.core.variables.state_variable import StateVariable -from slither.formatters.variables.possible_const_state_variables import custom_format - - -def _is_valid_type(v: StateVariable) -> bool: - t = v.type - if isinstance(t, ElementaryType): - return True - if isinstance(t, UserDefinedType) and isinstance(t.type, Contract): - return True - return False - - -def _valid_candidate(v: StateVariable) -> bool: - return _is_valid_type(v) and not (v.is_constant or v.is_immutable) - - -def _is_constant_var(v: Variable) -> bool: - if isinstance(v, StateVariable): - return v.is_constant - return False - - -class ConstCandidateStateVars(AbstractDetector): - """ - State variables that could be declared as constant detector. - Not all types for constants are implemented in Solidity as of 0.4.25. - The only supported types are value types and strings (ElementaryType). - Reference: https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables - """ - - ARGUMENT = "constable-states" - HELP = "State variables that could be declared constant" - IMPACT = DetectorClassification.OPTIMIZATION - CONFIDENCE = DetectorClassification.HIGH - - WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant" - - WIKI_TITLE = "State variables that could be declared constant" - WIKI_DESCRIPTION = "Constant state variables should be declared constant to save gas." - WIKI_RECOMMENDATION = "Add the `constant` attributes to state variables that never change." - - # https://solidity.readthedocs.io/en/v0.5.2/contracts.html#constant-state-variables - valid_solidity_function = [ - SolidityFunction("keccak256()"), - SolidityFunction("keccak256(bytes)"), - SolidityFunction("sha256()"), - SolidityFunction("sha256(bytes)"), - SolidityFunction("ripemd160()"), - SolidityFunction("ripemd160(bytes)"), - SolidityFunction("ecrecover(bytes32,uint8,bytes32,bytes32)"), - SolidityFunction("addmod(uint256,uint256,uint256)"), - SolidityFunction("mulmod(uint256,uint256,uint256)"), - ] - - def _constant_initial_expression(self, v: Variable) -> bool: - if not v.expression: - return True - - export = ExportValues(v.expression) - values = export.result() - if not values: - return True - if all((val in self.valid_solidity_function or _is_constant_var(val) for val in values)): - return True - return False - - def _detect(self) -> List[Output]: - """Detect state variables that could be const""" - results = [] - - all_variables_l = [c.state_variables for c in self.compilation_unit.contracts] - all_variables: Set[StateVariable] = { - item for sublist in all_variables_l for item in sublist - } - all_non_constant_elementary_variables = {v for v in all_variables if _valid_candidate(v)} - - all_functions_nested = [c.all_functions_called for c in self.compilation_unit.contracts] - all_functions = list( - { - item1 - for sublist in all_functions_nested - for item1 in sublist - if isinstance(item1, Function) - } - ) - - all_variables_written = [ - f.state_variables_written for f in all_functions if not f.is_constructor_variables - ] - all_variables_written = {item for sublist in all_variables_written for item in sublist} - - constable_variables: List[Variable] = [ - v - for v in all_non_constant_elementary_variables - if (v not in all_variables_written) and self._constant_initial_expression(v) - ] - # Order for deterministic results - constable_variables = sorted(constable_variables, key=lambda x: x.canonical_name) - - # Create a result for each finding - for v in constable_variables: - info = [v, " should be constant\n"] - json = self.generate_result(info) - results.append(json) - - return results - - @staticmethod - def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: - custom_format(compilation_unit, result) diff --git a/slither/detectors/variables/unchanged_state_variables.py b/slither/detectors/variables/unchanged_state_variables.py new file mode 100644 index 000000000..0dccb6d1c --- /dev/null +++ b/slither/detectors/variables/unchanged_state_variables.py @@ -0,0 +1,125 @@ +""" +Module detecting state variables that could be declared as constant +""" +from typing import Set, List +from packaging import version +from slither.core.compilation_unit import SlitherCompilationUnit +from slither.core.solidity_types.elementary_type import ElementaryType +from slither.core.solidity_types.user_defined_type import UserDefinedType +from slither.core.variables.variable import Variable + +from slither.visitors.expression.export_values import ExportValues +from slither.core.declarations import Contract, Function +from slither.core.declarations.solidity_variables import SolidityFunction +from slither.core.variables.state_variable import StateVariable +from slither.core.expressions import CallExpression, NewContract + + +def _is_valid_type(v: StateVariable) -> bool: + t = v.type + if isinstance(t, ElementaryType): + return True + if isinstance(t, UserDefinedType) and isinstance(t.type, Contract): + return True + return False + + +def _valid_candidate(v: StateVariable) -> bool: + return _is_valid_type(v) and not (v.is_constant or v.is_immutable) + + +def _is_constant_var(v: Variable) -> bool: + if isinstance(v, StateVariable): + return v.is_constant + return False + + +# https://solidity.readthedocs.io/en/v0.5.2/contracts.html#constant-state-variables +valid_solidity_function = [ + SolidityFunction("keccak256()"), + SolidityFunction("keccak256(bytes)"), + SolidityFunction("sha256()"), + SolidityFunction("sha256(bytes)"), + SolidityFunction("ripemd160()"), + SolidityFunction("ripemd160(bytes)"), + SolidityFunction("ecrecover(bytes32,uint8,bytes32,bytes32)"), + SolidityFunction("addmod(uint256,uint256,uint256)"), + SolidityFunction("mulmod(uint256,uint256,uint256)"), +] + + +def _constant_initial_expression(v: Variable) -> bool: + if not v.expression: + return True + + # B b = new B(); b cannot be constant, so filter out and recommend it be immutable + if isinstance(v.expression, CallExpression) and isinstance(v.expression.called, NewContract): + return False + + export = ExportValues(v.expression) + values = export.result() + if not values: + return True + + return all((val in valid_solidity_function or _is_constant_var(val) for val in values)) + + +class UnchangedStateVariables: + """ + Find state variables that could be declared as constant or immutable (not written after deployment). + """ + + def __init__(self, compilation_unit: SlitherCompilationUnit): + self.compilation_unit = compilation_unit + self._constant_candidates: List[StateVariable] = [] + self._immutable_candidates: List[StateVariable] = [] + + @property + def immutable_candidates(self) -> List[StateVariable]: + """Return the immutable candidates""" + return self._immutable_candidates + + @property + def constant_candidates(self) -> List[StateVariable]: + """Return the constant candidates""" + return self._constant_candidates + + def detect(self): + """Detect state variables that could be constant or immutable""" + for c in self.compilation_unit.contracts_derived: + variables = [] + functions = [] + + variables.append(c.state_variables) + functions.append(c.all_functions_called) + + valid_candidates: Set[StateVariable] = { + item for sublist in variables for item in sublist if _valid_candidate(item) + } + + all_functions: List[Function] = list( + {item1 for sublist in functions for item1 in sublist if isinstance(item1, Function)} + ) + + variables_written = [] + constructor_variables_written = [] + variables_initialized = [] + for f in all_functions: + if f.is_constructor_variables: + variables_initialized.extend(f.state_variables_written) + elif f.is_constructor: + constructor_variables_written.extend(f.state_variables_written) + else: + variables_written.extend(f.state_variables_written) + + for v in valid_candidates: + if v not in variables_written: + if _constant_initial_expression(v) and v not in constructor_variables_written: + self.constant_candidates.append(v) + + elif ( + v in constructor_variables_written or v in variables_initialized + ) and version.parse(self.compilation_unit.solc_version) >= version.parse( + "0.6.5" + ): + self.immutable_candidates.append(v) diff --git a/slither/formatters/variables/possible_const_state_variables.py b/slither/formatters/variables/unchanged_state_variables.py similarity index 94% rename from slither/formatters/variables/possible_const_state_variables.py rename to slither/formatters/variables/unchanged_state_variables.py index 88f92b841..c7c8bf003 100644 --- a/slither/formatters/variables/possible_const_state_variables.py +++ b/slither/formatters/variables/unchanged_state_variables.py @@ -5,7 +5,7 @@ from slither.formatters.exceptions import FormatError, FormatImpossible from slither.formatters.utils.patches import create_patch -def custom_format(compilation_unit: SlitherCompilationUnit, result): +def custom_format(compilation_unit: SlitherCompilationUnit, result, attribute: str) -> None: elements = result["elements"] for element in elements: @@ -15,14 +15,14 @@ def custom_format(compilation_unit: SlitherCompilationUnit, result): contract = scope.get_contract_from_name(contract_name) var = contract.get_state_variable_from_name(element["name"]) if not var.expression: - raise FormatImpossible(f"{var.name} is uninitialized and cannot become constant.") + raise FormatImpossible(f"{var.name} is uninitialized and cannot become {attribute}.") _patch( compilation_unit, result, element["source_mapping"]["filename_absolute"], element["name"], - "constant " + element["name"], + f"{attribute} " + element["name"], element["source_mapping"]["start"], element["source_mapping"]["start"] + element["source_mapping"]["length"], ) diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index dbfa54121..95d113a84 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -30,6 +30,7 @@ from slither.slithir.operations import ( ) from slither.slithir.operations.binary import Binary from slither.slithir.variables import Constant +from slither.visitors.expression.constants_folding import ConstantFolding def _get_name(f: Union[Function, Variable]) -> str: @@ -175,6 +176,11 @@ def _extract_constants_from_irs( # pylint: disable=too-many-branches,too-many-n all_cst_used_in_binary[str(ir.type)].append( ConstantValue(str(r.value), str(r.type)) ) + if isinstance(ir.variable_left, Constant) and isinstance(ir.variable_right, Constant): + if ir.lvalue: + type_ = ir.lvalue.type + cst = ConstantFolding(ir.expression, type_).result() + all_cst_used.append(ConstantValue(str(cst.value), str(type_))) if isinstance(ir, TypeConversion): if isinstance(ir.variable, Constant): all_cst_used.append(ConstantValue(str(ir.variable.value), str(ir.type))) @@ -323,27 +329,32 @@ def _call_a_parameter(slither: SlitherCore) -> Dict[str, List[Dict]]: ret: Dict[str, List[Dict]] = defaultdict(list) for contract in slither.contracts: # pylint: disable=too-many-nested-blocks for function in contract.functions_entry_points: - for ir in function.all_slithir_operations(): - if isinstance(ir, HighLevelCall): - for idx, parameter in enumerate(function.parameters): - if is_dependent(ir.destination, parameter, function): - ret[contract.name].append( - { - "function": _get_name(function), - "parameter_idx": idx, - "signature": _get_name(ir.function), - } - ) - if isinstance(ir, LowLevelCall): - for idx, parameter in enumerate(function.parameters): - if is_dependent(ir.destination, parameter, function): - ret[contract.name].append( - { - "function": _get_name(function), - "parameter_idx": idx, - "signature": None, - } - ) + try: + for ir in function.all_slithir_operations(): + if isinstance(ir, HighLevelCall): + for idx, parameter in enumerate(function.parameters): + if is_dependent(ir.destination, parameter, function): + ret[contract.name].append( + { + "function": _get_name(function), + "parameter_idx": idx, + "signature": _get_name(ir.function), + } + ) + if isinstance(ir, LowLevelCall): + for idx, parameter in enumerate(function.parameters): + if is_dependent(ir.destination, parameter, function): + ret[contract.name].append( + { + "function": _get_name(function), + "parameter_idx": idx, + "signature": None, + } + ) + except Exception as e: + if slither.no_fail: + continue + raise e return ret diff --git a/slither/slither.py b/slither/slither.py index 81e920d01..45d99906f 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -91,6 +91,8 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) self.codex_log = kwargs.get("codex_log", False) + self.no_fail = kwargs.get("no_fail", False) + self._parsers: List[SlitherCompilationUnitSolc] = [] try: if isinstance(target, CryticCompile): @@ -128,41 +130,27 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes triage_mode = kwargs.get("triage_mode", False) self._triage_mode = triage_mode + self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) + + def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: for parser in self._parsers: - parser.parse_contracts() + try: + parser.parse_contracts() + except Exception as e: + if self.no_fail: + continue + raise e # skip_analyze is only used for testing - if not kwargs.get("skip_analyze", False): + if not skip_analyze: for parser in self._parsers: - parser.analyze_contracts() - - # def _init_from_raw_json(self, filename): - # if not os.path.isfile(filename): - # raise SlitherError( - # "{} does not exist (are you in the correct directory?)".format(filename) - # ) - # assert filename.endswith("json") - # with open(filename, encoding="utf8") as astFile: - # stdout = astFile.read() - # if not stdout: - # to_log = f"Empty AST file: {filename}" - # raise SlitherError(to_log) - # contracts_json = stdout.split("\n=") - # - # self._parser = SlitherCompilationUnitSolc(filename, self) - # - # for c in contracts_json: - # self._parser.parse_top_level_from_json(c) - - # def _init_from_list(self, contract): - # self._parser = SlitherCompilationUnitSolc("", self) - # for c in contract: - # if "absolutePath" in c: - # path = c["absolutePath"] - # else: - # path = c["attributes"]["absolutePath"] - # self._parser.parse_top_level_from_loaded_json(c, path) + try: + parser.analyze_contracts() + except Exception as e: + if self.no_fail: + continue + raise e @property def detectors(self): diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 0d2ef1b74..7b9e286fa 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -379,7 +379,7 @@ def integrate_value_gas(result): ################################################################################### -def propagate_type_and_convert_call(result, node): +def propagate_type_and_convert_call(result: List[Operation], node: "Node") -> List[Operation]: """ Propagate the types variables and convert tmp call to real call operation """ @@ -664,7 +664,24 @@ def propagate_types(ir, node: "Node"): # pylint: disable=too-many-locals if ir.variable_right == "selector" and isinstance(ir.variable_left, (CustomError)): assignment = Assignment( ir.lvalue, - Constant(str(get_function_id(ir.variable_left.solidity_signature))), + Constant( + str(get_function_id(ir.variable_left.solidity_signature)), + ElementaryType("bytes4"), + ), + ElementaryType("bytes4"), + ) + assignment.set_expression(ir.expression) + assignment.set_node(ir.node) + assignment.lvalue.set_type(ElementaryType("bytes4")) + return assignment + + if isinstance(ir.variable_right, (CustomError)): + assignment = Assignment( + ir.lvalue, + Constant( + str(get_function_id(ir.variable_left.solidity_signature)), + ElementaryType("bytes4"), + ), ElementaryType("bytes4"), ) assignment.set_expression(ir.expression) @@ -736,7 +753,7 @@ def propagate_types(ir, node: "Node"): # pylint: disable=too-many-locals if f: ir.lvalue.set_type(f) else: - # Allow propgation for variable access through contract's nale + # Allow propgation for variable access through contract's name # like Base_contract.my_variable v = next( ( @@ -1819,7 +1836,7 @@ def _find_source_mapping_references(irs: List[Operation]): ################################################################################### -def apply_ir_heuristics(irs, node): +def apply_ir_heuristics(irs: List[Operation], node: "Node"): """ Apply a set of heuristic to improve slithIR """ diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 269ca580f..6b8aca51e 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -91,6 +91,9 @@ class FunctionSolc(CallerContextExpression): Union[LocalVariableSolc, LocalVariableInitFromTupleSolc] ] = [] + if "documentation" in function_data: + function.has_documentation = True + @property def underlying_function(self) -> Function: return self._function @@ -340,7 +343,6 @@ class FunctionSolc(CallerContextExpression): node, [self._function.name, f"asm_{len(self._node_to_yulobject)}"], scope, - parent_func=self._function, ) self._node_to_yulobject[node] = yul_object return yul_object diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 201cc48cd..591b8bb18 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -48,16 +48,22 @@ def _handle_import_aliases( """ for symbol_alias in symbol_aliases: - if ( - "foreign" in symbol_alias - and "name" in symbol_alias["foreign"] - and "local" in symbol_alias - ): - original_name = symbol_alias["foreign"]["name"] - local_name = symbol_alias["local"] - import_directive.renaming[local_name] = original_name - # Assuming that two imports cannot collide in renaming - scope.renaming[local_name] = original_name + if "foreign" in symbol_alias and "local" in symbol_alias: + if isinstance(symbol_alias["foreign"], dict) and "name" in symbol_alias["foreign"]: + + original_name = symbol_alias["foreign"]["name"] + local_name = symbol_alias["local"] + import_directive.renaming[local_name] = original_name + # Assuming that two imports cannot collide in renaming + scope.renaming[local_name] = original_name + + # This path should only be hit for the malformed AST of solc 0.5.12 where + # the foreign identifier cannot be found but is required to resolve the alias. + # see https://github.com/crytic/slither/issues/1319 + elif symbol_alias["local"]: + raise SlitherException( + "Cannot resolve local alias for import directive due to malformed AST. Please upgrade to solc 0.6.0 or higher." + ) class SlitherCompilationUnitSolc(CallerContextExpression): @@ -513,7 +519,7 @@ Please rename it, this name is reserved for Slither's internals""" self._analyze_third_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self._underlying_contract_to_parser.values()] - self._analyze_using_for(contracts_to_be_analyzed) + self._analyze_using_for(contracts_to_be_analyzed, libraries) self._parsed = True @@ -625,9 +631,14 @@ Please rename it, this name is reserved for Slither's internals""" else: contracts_to_be_analyzed += [contract] - def _analyze_using_for(self, contracts_to_be_analyzed: List[ContractSolc]): + def _analyze_using_for( + self, contracts_to_be_analyzed: List[ContractSolc], libraries: List[ContractSolc] + ): self._analyze_top_level_using_for() + for lib in libraries: + lib.analyze_using_for() + while contracts_to_be_analyzed: contract = contracts_to_be_analyzed[0] diff --git a/slither/solc_parsing/yul/evm_functions.py b/slither/solc_parsing/yul/evm_functions.py index 0276d4bf7..41c150765 100644 --- a/slither/solc_parsing/yul/evm_functions.py +++ b/slither/solc_parsing/yul/evm_functions.py @@ -264,9 +264,9 @@ binary_ops = { class YulBuiltin: # pylint: disable=too-few-public-methods - def __init__(self, name): + def __init__(self, name: str) -> None: self._name = name @property - def name(self): + def name(self) -> str: return self._name diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 8c9ee427e..f7c9938fc 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -24,6 +24,7 @@ from slither.core.expressions import ( UnaryOperation, ) from slither.core.expressions.expression import Expression +from slither.core.scope.scope import FileScope from slither.core.solidity_types import ElementaryType from slither.core.source_mapping.source_mapping import SourceMapping from slither.core.variables.local_variable import LocalVariable @@ -51,30 +52,35 @@ class YulNode: def underlying_node(self) -> Node: return self._node - def add_unparsed_expression(self, expression: Dict): + def add_unparsed_expression(self, expression: Dict) -> None: assert self._unparsed_expression is None self._unparsed_expression = expression - def analyze_expressions(self): + def analyze_expressions(self) -> None: if self._node.type == NodeType.VARIABLE and not self._node.expression: - self._node.add_expression(self._node.variable_declaration.expression) + expression = self._node.variable_declaration.expression + if expression: + self._node.add_expression(expression) if self._unparsed_expression: expression = parse_yul(self._scope, self, self._unparsed_expression) - self._node.add_expression(expression) + if expression: + self._node.add_expression(expression) if self._node.expression: if self._node.type == NodeType.VARIABLE: # Update the expression to be an assignement to the variable - _expression = AssignmentOperation( - Identifier(self._node.variable_declaration), - self._node.expression, - AssignmentOperationType.ASSIGN, - self._node.variable_declaration.type, - ) - _expression.set_offset( - self._node.expression.source_mapping, self._node.compilation_unit - ) - self._node.add_expression(_expression, bypass_verif_empty=True) + variable_declaration = self._node.variable_declaration + if variable_declaration: + _expression = AssignmentOperation( + Identifier(self._node.variable_declaration), + self._node.expression, + AssignmentOperationType.ASSIGN, + variable_declaration.type, + ) + _expression.set_offset( + self._node.expression.source_mapping, self._node.compilation_unit + ) + self._node.add_expression(_expression, bypass_verif_empty=True) expression = self._node.expression read_var = ReadVar(expression) @@ -122,13 +128,13 @@ class YulScope(metaclass=abc.ABCMeta): ] def __init__( - self, contract: Optional[Contract], yul_id: List[str], parent_func: Function = None - ): + self, contract: Optional[Contract], yul_id: List[str], parent_func: Function + ) -> None: self._contract = contract self._id: List[str] = yul_id self._yul_local_variables: List[YulLocalVariable] = [] self._yul_local_functions: List[YulFunction] = [] - self._parent_func = parent_func + self._parent_func: Function = parent_func @property def id(self) -> List[str]: @@ -155,10 +161,14 @@ class YulScope(metaclass=abc.ABCMeta): def new_node(self, node_type: NodeType, src: Union[str, Dict]) -> YulNode: pass - def add_yul_local_variable(self, var): + @property + def file_scope(self) -> FileScope: + return self._parent_func.file_scope + + def add_yul_local_variable(self, var: "YulLocalVariable") -> None: self._yul_local_variables.append(var) - def get_yul_local_variable_from_name(self, variable_name): + def get_yul_local_variable_from_name(self, variable_name: str) -> Optional["YulLocalVariable"]: return next( ( v @@ -168,10 +178,10 @@ class YulScope(metaclass=abc.ABCMeta): None, ) - def add_yul_local_function(self, func): + def add_yul_local_function(self, func: "YulFunction") -> None: self._yul_local_functions.append(func) - def get_yul_local_function_from_name(self, func_name): + def get_yul_local_function_from_name(self, func_name: str) -> Optional["YulLocalVariable"]: return next( (v for v in self._yul_local_functions if v.underlying.name == func_name), None, @@ -242,7 +252,7 @@ class YulFunction(YulScope): def function(self) -> Function: return self._function - def convert_body(self): + def convert_body(self) -> None: node = self.new_node(NodeType.ENTRYPOINT, self._ast["src"]) link_underlying_nodes(self._entrypoint, node) @@ -258,7 +268,7 @@ class YulFunction(YulScope): convert_yul(self, node, self._ast["body"], self.node_scope) - def parse_body(self): + def parse_body(self) -> None: for node in self._nodes: node.analyze_expressions() @@ -289,9 +299,8 @@ class YulBlock(YulScope): entrypoint: Node, yul_id: List[str], node_scope: Union[Scope, Function], - **kwargs, ): - super().__init__(contract, yul_id, **kwargs) + super().__init__(contract, yul_id, entrypoint.function) self._entrypoint: YulNode = YulNode(entrypoint, self) self._nodes: List[YulNode] = [] @@ -318,7 +327,7 @@ class YulBlock(YulScope): def convert(self, ast: Dict) -> YulNode: return convert_yul(self, self._entrypoint, ast, self.node_scope) - def analyze_expressions(self): + def analyze_expressions(self) -> None: for node in self._nodes: node.analyze_expressions() @@ -361,18 +370,22 @@ def convert_yul_function_definition( while not isinstance(top_node_scope, Function): top_node_scope = top_node_scope.father + func: Union[FunctionTopLevel, FunctionContract] if isinstance(top_node_scope, FunctionTopLevel): - scope = root.contract.file_scope + scope = root.file_scope func = FunctionTopLevel(root.compilation_unit, scope) # Note: we do not add the function in the scope # While its a top level function, it is not accessible outside of the function definition # In practice we should probably have a specific function type for function defined within a function else: func = FunctionContract(root.compilation_unit) + func.function_language = FunctionLanguage.Yul yul_function = YulFunction(func, root, ast, node_scope) - root.contract.add_function(func) + if root.contract: + root.contract.add_function(func) + root.compilation_unit.add_function(func) root.add_yul_local_function(yul_function) @@ -774,14 +787,15 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[ # check function-scoped variables parent_func = root.parent_func if parent_func: - variable = parent_func.get_local_variable_from_name(name) - if variable: - return Identifier(variable) + local_variable = parent_func.get_local_variable_from_name(name) + if local_variable: + return Identifier(local_variable) if isinstance(parent_func, FunctionContract): - variable = parent_func.contract.get_state_variable_from_name(name) - if variable: - return Identifier(variable) + assert parent_func.contract + state_variable = parent_func.contract.get_state_variable_from_name(name) + if state_variable: + return Identifier(state_variable) # check yul-scoped variable variable = root.get_yul_local_variable_from_name(name) @@ -798,7 +812,7 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[ if magic_suffix: return magic_suffix - ret, _ = find_top_level(name, root.contract.file_scope) + ret, _ = find_top_level(name, root.file_scope) if ret: return Identifier(ret) @@ -840,7 +854,7 @@ def parse_yul_unsupported(_root: YulScope, _node: YulNode, ast: Dict) -> Optiona def parse_yul(root: YulScope, node: YulNode, ast: Dict) -> Optional[Expression]: - op = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast) + op: Expression = parsers.get(ast["nodeType"], parse_yul_unsupported)(root, node, ast) if op: op.set_offset(ast["src"], root.compilation_unit) return op diff --git a/slither/tools/doctor/__main__.py b/slither/tools/doctor/__main__.py index 94ae865ec..b9b4c5497 100644 --- a/slither/tools/doctor/__main__.py +++ b/slither/tools/doctor/__main__.py @@ -1,4 +1,6 @@ import argparse +import logging +import sys from crytic_compile import cryticparser @@ -25,6 +27,9 @@ def parse_args() -> argparse.Namespace: def main(): + # log on stdout to keep output in order + logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, force=True) + args = parse_args() kwargs = vars(args) diff --git a/slither/tools/doctor/checks/__init__.py b/slither/tools/doctor/checks/__init__.py index 762c60b5d..8a0741940 100644 --- a/slither/tools/doctor/checks/__init__.py +++ b/slither/tools/doctor/checks/__init__.py @@ -1,6 +1,7 @@ from typing import Callable, List from dataclasses import dataclass +from slither.tools.doctor.checks.paths import check_slither_path from slither.tools.doctor.checks.platform import compile_project, detect_platform from slither.tools.doctor.checks.versions import show_versions @@ -12,6 +13,7 @@ class Check: ALL_CHECKS: List[Check] = [ + Check("PATH configuration", check_slither_path), Check("Software versions", show_versions), Check("Project platform", detect_platform), Check("Project compilation", compile_project), diff --git a/slither/tools/doctor/checks/paths.py b/slither/tools/doctor/checks/paths.py new file mode 100644 index 000000000..d388847ef --- /dev/null +++ b/slither/tools/doctor/checks/paths.py @@ -0,0 +1,85 @@ +from pathlib import Path +from typing import List, Optional, Tuple +import shutil +import sys +import sysconfig + +from slither.utils.colors import yellow, green, red + + +def path_is_relative_to(path: Path, relative_to: Path) -> bool: + """ + Check if a path is relative to another one. + + Compatibility wrapper for Path.is_relative_to + """ + if sys.version_info >= (3, 9, 0): + return path.is_relative_to(relative_to) + + path_parts = path.resolve().parts + relative_to_parts = relative_to.resolve().parts + + if len(path_parts) < len(relative_to_parts): + return False + + for (a, b) in zip(path_parts, relative_to_parts): + if a != b: + return False + + return True + + +def check_path_config(name: str) -> Tuple[bool, Optional[Path], List[Path]]: + """ + Check if a given Python binary/script is in PATH. + :return: Returns if the binary on PATH corresponds to this installation, + its path (if present), and a list of possible paths where this + binary might be found. + """ + binary_path = shutil.which(name) + possible_paths = [] + + for scheme in sysconfig.get_scheme_names(): + script_path = Path(sysconfig.get_path("scripts", scheme)) + purelib_path = Path(sysconfig.get_path("purelib", scheme)) + script_binary_path = shutil.which(name, path=script_path) + if script_binary_path is not None: + possible_paths.append((script_path, purelib_path)) + + binary_here = False + if binary_path is not None: + binary_path = Path(binary_path) + this_code = Path(__file__) + this_binary = list(filter(lambda x: path_is_relative_to(this_code, x[1]), possible_paths)) + binary_here = len(this_binary) > 0 and all( + path_is_relative_to(binary_path, script) for script, _ in this_binary + ) + + return binary_here, binary_path, list(set(script for script, _ in possible_paths)) + + +def check_slither_path(**_kwargs) -> None: + binary_here, binary_path, possible_paths = check_path_config("slither") + show_paths = False + + if binary_path: + print(green(f"`slither` found in PATH at `{binary_path}`.")) + if binary_here: + print(green("Its location matches this slither-doctor installation.")) + else: + print( + yellow( + "This path does not correspond to this slither-doctor installation.\n" + + "Double-check the order of directories in PATH if you have several Slither installations." + ) + ) + show_paths = True + else: + print(red("`slither` was not found in PATH.")) + show_paths = True + + if show_paths: + print() + print("Consider adding one of the following directories to PATH:") + for path in possible_paths: + print(f" * {path}") diff --git a/slither/tools/doctor/checks/versions.py b/slither/tools/doctor/checks/versions.py index 909bccf55..ec7ef1d1f 100644 --- a/slither/tools/doctor/checks/versions.py +++ b/slither/tools/doctor/checks/versions.py @@ -3,19 +3,19 @@ import json from typing import Optional import urllib -from packaging.version import parse, LegacyVersion, Version +from packaging.version import parse, Version from slither.utils.colors import yellow, green -def get_installed_version(name: str) -> Optional[LegacyVersion | Version]: +def get_installed_version(name: str) -> Optional[Version]: try: return parse(metadata.version(name)) except metadata.PackageNotFoundError: return None -def get_github_version(name: str) -> Optional[LegacyVersion | Version]: +def get_github_version(name: str) -> Optional[Version]: try: with urllib.request.urlopen( f"https://api.github.com/repos/crytic/{name}/releases/latest" @@ -45,7 +45,9 @@ def show_versions(**_kwargs) -> None: for name, (installed, latest) in versions.items(): color = yellow if name in outdated else green - print(f"{name + ':':<16}{color(installed or 'N/A'):<16} (latest is {latest or 'Unknown'})") + print( + f"{name + ':':<16}{color(str(installed) or 'N/A'):<16} (latest is {str(latest) or 'Unknown'})" + ) if len(outdated) > 0: print() diff --git a/slither/tools/documentation/README.md b/slither/tools/documentation/README.md new file mode 100644 index 000000000..b4b3e6a76 --- /dev/null +++ b/slither/tools/documentation/README.md @@ -0,0 +1,5 @@ +# slither-documentation + +`slither-documentation` uses [codex](https://beta.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/tools/documentation/__init__.py b/slither/tools/documentation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/tools/documentation/__main__.py b/slither/tools/documentation/__main__.py new file mode 100644 index 000000000..8e545fb09 --- /dev/null +++ b/slither/tools/documentation/__main__.py @@ -0,0 +1,280 @@ +import argparse +import logging +import uuid +from typing import Optional, Dict, List +from crytic_compile import cryticparser +from slither import Slither +from slither.core.compilation_unit import SlitherCompilationUnit +from slither.core.declarations import Function + +from slither.formatters.utils.patches import create_patch, apply_patch, create_diff +from slither.utils import codex + +logging.basicConfig() +logging.getLogger("Slither").setLevel(logging.INFO) + +logger = logging.getLogger("Slither") + + +def parse_args() -> argparse.Namespace: + """ + Parse the underlying arguments for the program. + :return: Returns the arguments for the program. + """ + parser = argparse.ArgumentParser(description="Demo", usage="slither-documentation filename") + + parser.add_argument("project", help="The target directory/Solidity file.") + + parser.add_argument( + "--overwrite", help="Overwrite the files (be careful).", action="store_true", default=False + ) + + parser.add_argument( + "--force-answer-parsing", + help="Apply heuristics to better parse codex output (might lead to incorrect results)", + action="store_true", + default=False, + ) + + parser.add_argument( + "--retry", + help="Retry failed query (default 1). Each retry increases the temperature by 0.1", + action="store", + default=1, + ) + + # Add default arguments from crytic-compile + cryticparser.init(parser) + + codex.init_parser(parser, always_enable_codex=True) + + return parser.parse_args() + + +def _use_tab(char: str) -> Optional[bool]: + """ + Check if the char is a tab + + Args: + char: + + Returns: + + """ + if char == " ": + return False + if char == "\t": + return True + return None + + +def _post_processesing( + answer: str, starting_column: int, use_tab: Optional[bool], force_and_stopped: bool +) -> Optional[str]: + """ + Clean answers from codex + + Args: + answer: + starting_column: + + Returns: + + """ + if answer.count("/**") != 1: + return None + # Sometimes codex will miss the */, even if it finished properly the request + # In this case, we allow slither-documentation to force the */ + if answer.count("*/") != 1: + if force_and_stopped: + answer += "*/" + else: + return None + if answer.find("/**") > answer.find("*/"): + return None + answer = answer[answer.find("/**") : answer.find("*/") + 2] + answer_lines = answer.splitlines() + # Add indentation to all the lines, aside the first one + + space_char = "\t" if use_tab else " " + + if len(answer_lines) > 0: + answer = ( + answer_lines[0] + + "\n" + + "\n".join( + [space_char * (starting_column - 1) + line for line in answer_lines[1:] if line] + ) + ) + answer += "\n" + space_char * (starting_column - 1) + return answer + return answer_lines[0] + + +def _handle_codex( + answer: Dict, starting_column: int, use_tab: Optional[bool], force: bool +) -> Optional[str]: + if "choices" in answer: + if answer["choices"]: + if "text" in answer["choices"][0]: + has_stopped = answer["choices"][0].get("finish_reason", "") == "stop" + answer_processed = _post_processesing( + answer["choices"][0]["text"], starting_column, use_tab, force and has_stopped + ) + if answer_processed is None: + return None + return answer_processed + return None + + +# pylint: disable=too-many-locals,too-many-arguments +def _handle_function( + function: Function, + overwrite: bool, + all_patches: Dict, + logging_file: Optional[str], + slither: Slither, + retry: int, + force: bool, +) -> bool: + if ( + function.source_mapping.is_dependency + or function.has_documentation + or function.is_constructor_variables + ): + return overwrite + prompt = "Create a natpsec documentation for this solidity code with only notice and dev.\n" + src_mapping = function.source_mapping + content = function.compilation_unit.core.source_code[src_mapping.filename.absolute] + start = src_mapping.start + end = src_mapping.start + src_mapping.length + prompt += content[start:end] + + use_tab = _use_tab(content[start - 1]) + if use_tab is None and src_mapping.starting_column > 1: + logger.info(f"Non standard space indentation found {content[start - 1:end]}") + if overwrite: + logger.info("Disable overwrite to avoid mistakes") + overwrite = False + + openai = codex.openai_module() # type: ignore + if openai is None: + raise ImportError + + if logging_file: + codex.log_codex(logging_file, "Q: " + prompt) + + tentative = 0 + answer_processed: Optional[str] = None + while tentative < retry: + tentative += 1 + + answer = openai.Completion.create( # type: ignore + prompt=prompt, + model=slither.codex_model, + temperature=min(slither.codex_temperature + tentative * 0.1, 1), + max_tokens=slither.codex_max_tokens, + ) + + if logging_file: + codex.log_codex(logging_file, "A: " + str(answer)) + + answer_processed = _handle_codex(answer, src_mapping.starting_column, use_tab, force) + if answer_processed: + break + + logger.info( + f"Codex could not generate a well formatted answer for {function.canonical_name}" + ) + logger.info(answer) + + if not answer_processed: + return overwrite + + create_patch(all_patches, src_mapping.filename.absolute, start, start, "", answer_processed) + + return overwrite + + +def _handle_compilation_unit( + slither: Slither, + compilation_unit: SlitherCompilationUnit, + overwrite: bool, + force: bool, + retry: int, +) -> None: + logging_file: Optional[str] + if slither.codex_log: + logging_file = str(uuid.uuid4()) + else: + logging_file = None + + for scope in compilation_unit.scopes.values(): + + # Dont send tests file + if ( + ".t.sol" in scope.filename.absolute + or "mock" in scope.filename.absolute.lower() + or "test" in scope.filename.absolute.lower() + ): + continue + + functions_target: List[Function] = [] + + for contract in scope.contracts.values(): + functions_target += contract.functions_declared + + functions_target += list(scope.functions) + + all_patches: Dict = {} + + for function in functions_target: + overwrite = _handle_function( + function, overwrite, all_patches, logging_file, slither, retry, force + ) + + # all_patches["patches"] should have only 1 file + if "patches" not in all_patches: + continue + for file in all_patches["patches"]: + original_txt = compilation_unit.core.source_code[file].encode("utf8") + patched_txt = original_txt + + patches = all_patches["patches"][file] + offset = 0 + patches.sort(key=lambda x: x["start"]) + + for patch in patches: + patched_txt, offset = apply_patch(patched_txt, patch, offset) + + if overwrite: + with open(file, "w", encoding="utf8") as f: + f.write(patched_txt.decode("utf8")) + else: + diff = create_diff(compilation_unit, original_txt, patched_txt, file) + with open(f"{file}.patch", "w", encoding="utf8") as f: + f.write(diff) + + +def main() -> None: + args = parse_args() + + logger.info("This tool is a WIP, use it with cautious") + logger.info("Be aware of OpenAI ToS: https://openai.com/api/policies/terms/") + slither = Slither(args.project, **vars(args)) + + try: + for compilation_unit in slither.compilation_units: + _handle_compilation_unit( + slither, + compilation_unit, + args.overwrite, + args.force_answer_parsing, + int(args.retry), + ) + except ImportError: + pass + + +if __name__ == "__main__": + main() diff --git a/slither/tools/slither_format/slither_format.py b/slither/tools/slither_format/slither_format.py index c165b3fbb..3c37313fd 100644 --- a/slither/tools/slither_format/slither_format.py +++ b/slither/tools/slither_format/slither_format.py @@ -9,7 +9,8 @@ from slither.detectors.attributes.incorrect_solc import IncorrectSolc from slither.detectors.attributes.constant_pragma import ConstantPragma from slither.detectors.naming_convention.naming_convention import NamingConvention from slither.detectors.functions.external_function import ExternalFunction -from slither.detectors.variables.possible_const_state_variables import ConstCandidateStateVars +from slither.detectors.variables.could_be_constant import CouldBeConstant +from slither.detectors.variables.could_be_immutable import CouldBeImmutable from slither.detectors.attributes.const_functions_asm import ConstantFunctionsAsm from slither.detectors.attributes.const_functions_state import ConstantFunctionsState from slither.utils.colors import yellow @@ -23,7 +24,8 @@ all_detectors: Dict[str, Type[AbstractDetector]] = { "pragma": ConstantPragma, "naming-convention": NamingConvention, "external-function": ExternalFunction, - "constable-states": ConstCandidateStateVars, + "constable-states": CouldBeConstant, + "immutable-states": CouldBeImmutable, "constant-function-asm": ConstantFunctionsAsm, "constant-functions-state": ConstantFunctionsState, } diff --git a/slither/utils/codex.py b/slither/utils/codex.py index 0040fb03c..3b06efe6f 100644 --- a/slither/utils/codex.py +++ b/slither/utils/codex.py @@ -1,10 +1,70 @@ import logging import os +from argparse import ArgumentParser from pathlib import Path +from slither.utils.command_line import defaults_flag_in_config + logger = logging.getLogger("Slither") +def init_parser(parser: ArgumentParser, always_enable_codex: bool = False) -> None: + """ + Init the cli arg with codex features + + Args: + parser: + always_enable_codex (Optional(bool)): if true, --codex is not enabled + + Returns: + + """ + group_codex = parser.add_argument_group("Codex (https://beta.openai.com/docs/guides/code)") + + if not always_enable_codex: + group_codex.add_argument( + "--codex", + help="Enable codex (require an OpenAI API Key)", + action="store_true", + default=defaults_flag_in_config["codex"], + ) + + group_codex.add_argument( + "--codex-log", + help="Log codex queries (in crytic_export/codex/)", + action="store_true", + default=False, + ) + + group_codex.add_argument( + "--codex-contracts", + help="Comma separated list of contracts to submit to OpenAI Codex", + action="store", + default=defaults_flag_in_config["codex_contracts"], + ) + + group_codex.add_argument( + "--codex-model", + help="Name of the Codex model to use (affects pricing). Defaults to 'text-davinci-003'", + action="store", + default=defaults_flag_in_config["codex_model"], + ) + + group_codex.add_argument( + "--codex-temperature", + help="Temperature to use with Codex. Lower number indicates a more precise answer while higher numbers return more creative answers. Defaults to 0", + action="store", + default=defaults_flag_in_config["codex_temperature"], + ) + + group_codex.add_argument( + "--codex-max-tokens", + help="Maximum amount of tokens to use on the response. This number plus the size of the prompt can be no larger than the limit (4097 for text-davinci-003)", + action="store", + default=defaults_flag_in_config["codex_max_tokens"], + ) + + # TODO: investigate how to set the correct return type # So that the other modules can work with openai def openai_module(): # type: ignore diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index 71305c56e..174c2a4b6 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -60,6 +60,7 @@ defaults_flag_in_config = { "zip": None, "zip_type": "lzma", "show_ignored_findings": False, + "no_fail": False, **DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, } diff --git a/slither/visitors/expression/constants_folding.py b/slither/visitors/expression/constants_folding.py index b324ed842..797d1f46e 100644 --- a/slither/visitors/expression/constants_folding.py +++ b/slither/visitors/expression/constants_folding.py @@ -1,4 +1,12 @@ -from slither.core.expressions import BinaryOperationType, Literal, UnaryOperationType +from fractions import Fraction +from slither.core.expressions import ( + BinaryOperationType, + Literal, + UnaryOperationType, + Identifier, + BinaryOperation, + UnaryOperation, +) from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int from slither.visitors.expression.expression import ExpressionVisitor @@ -27,9 +35,15 @@ class ConstantFolding(ExpressionVisitor): super().__init__(expression) def result(self): - return Literal(int(get_val(self._expression)), self._type) - - def _post_identifier(self, expression): + value = get_val(self._expression) + if isinstance(value, Fraction): + value = int(value) + # emulate 256-bit wrapping + if str(self._type).startswith("uint"): + value = value & (2**256 - 1) + return Literal(value, self._type) + + def _post_identifier(self, expression: Identifier): if not expression.value.is_constant: raise NotConstant expr = expression.value.expression @@ -37,9 +51,10 @@ class ConstantFolding(ExpressionVisitor): if not isinstance(expr, Literal): cf = ConstantFolding(expr, self._type) expr = cf.result() - set_val(expression, convert_string_to_int(expr.value)) + set_val(expression, convert_string_to_int(expr.converted_value)) - def _post_binary_operation(self, expression): + # pylint: disable=too-many-branches + def _post_binary_operation(self, expression: BinaryOperation): left = get_val(expression.expression_left) right = get_val(expression.expression_right) if expression.type == BinaryOperationType.POWER: @@ -53,18 +68,39 @@ class ConstantFolding(ExpressionVisitor): elif expression.type == BinaryOperationType.ADDITION: set_val(expression, left + right) elif expression.type == BinaryOperationType.SUBTRACTION: - if (left - right) < 0: - # Could trigger underflow - raise NotConstant set_val(expression, left - right) + # Convert to int for operations not supported by Fraction elif expression.type == BinaryOperationType.LEFT_SHIFT: - set_val(expression, left << right) + set_val(expression, int(left) << int(right)) elif expression.type == BinaryOperationType.RIGHT_SHIFT: - set_val(expression, left >> right) + set_val(expression, int(left) >> int(right)) + elif expression.type == BinaryOperationType.AND: + set_val(expression, int(left) & int(right)) + elif expression.type == BinaryOperationType.CARET: + set_val(expression, int(left) ^ int(right)) + elif expression.type == BinaryOperationType.OR: + set_val(expression, int(left) | int(right)) + elif expression.type == BinaryOperationType.LESS: + set_val(expression, int(left) < int(right)) + elif expression.type == BinaryOperationType.LESS_EQUAL: + set_val(expression, int(left) <= int(right)) + elif expression.type == BinaryOperationType.GREATER: + set_val(expression, int(left) > int(right)) + elif expression.type == BinaryOperationType.GREATER_EQUAL: + set_val(expression, int(left) >= int(right)) + elif expression.type == BinaryOperationType.EQUAL: + set_val(expression, int(left) == int(right)) + elif expression.type == BinaryOperationType.NOT_EQUAL: + set_val(expression, int(left) != int(right)) + # Convert boolean literals from string to bool + elif expression.type == BinaryOperationType.ANDAND: + set_val(expression, left == "true" and right == "true") + elif expression.type == BinaryOperationType.OROR: + set_val(expression, left == "true" or right == "true") else: raise NotConstant - def _post_unary_operation(self, expression): + def _post_unary_operation(self, expression: UnaryOperation): # Case of uint a = -7; uint[-a] arr; if expression.type == UnaryOperationType.MINUS_PRE: expr = expression.expression @@ -72,15 +108,18 @@ class ConstantFolding(ExpressionVisitor): cf = ConstantFolding(expr, self._type) expr = cf.result() assert isinstance(expr, Literal) - set_val(expression, -convert_string_to_fraction(expr.value)) + set_val(expression, -convert_string_to_fraction(expr.converted_value)) else: raise NotConstant - def _post_literal(self, expression): - try: - set_val(expression, convert_string_to_fraction(expression.value)) - except ValueError as e: - raise NotConstant from e + def _post_literal(self, expression: Literal): + if expression.converted_value in ["true", "false"]: + set_val(expression, expression.converted_value) + else: + try: + set_val(expression, convert_string_to_fraction(expression.converted_value)) + except ValueError as e: + raise NotConstant from e def _post_assignement_operation(self, expression): raise NotConstant @@ -115,9 +154,12 @@ class ConstantFolding(ExpressionVisitor): cf = ConstantFolding(expression.expressions[0], self._type) expr = cf.result() assert isinstance(expr, Literal) - set_val(expression, convert_string_to_fraction(expr.value)) + set_val(expression, convert_string_to_fraction(expr.converted_value)) return raise NotConstant def _post_type_conversion(self, expression): - raise NotConstant + cf = ConstantFolding(expression.expression, self._type) + expr = cf.result() + assert isinstance(expr, Literal) + set_val(expression, convert_string_to_fraction(expr.converted_value)) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 3c4595b92..6b7b4c264 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -282,10 +282,15 @@ class ExpressionToSlithIR(ExpressionVisitor): and expression_called.member_name in ["wrap", "unwrap"] and len(args) == 1 ): + # wrap: underlying_type -> alias + # unwrap: alias -> underlying_type + dest_type = ( + called if expression_called.member_name == "wrap" else called.underlying_type + ) val = TemporaryVariable(self._node) - var = TypeConversion(val, args[0], called) + var = TypeConversion(val, args[0], dest_type) var.set_expression(expression) - val.set_type(called) + val.set_type(dest_type) self._result.append(var) set_val(expression, val) @@ -455,14 +460,18 @@ class ExpressionToSlithIR(ExpressionVisitor): set_val(expression, expr) return - # Early lookup to detect user defined types from other contracts definitions - # 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 isinstance(expr, Contract): + # Early lookup to detect user defined types from other contracts definitions + # 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]) return + # Lookup errors referred to as member of contract e.g. Test.myError.selector + if expression.member_name in expr.custom_errors_as_dict: + set_val(expression, expr.custom_errors_as_dict[expression.member_name]) + return val = ReferenceVariable(self._node) member = Member(expr, Constant(expression.member_name), val) diff --git a/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.zip b/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.zip new file mode 100644 index 000000000..f1b133056 Binary files /dev/null and b/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.zip differ diff --git a/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.zip b/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.zip new file mode 100644 index 000000000..3f457a34d Binary files /dev/null and b/tests/ast-parsing/compile/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.10-compact.zip new file mode 100644 index 000000000..0d7f3ac0f Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.10-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.11-compact.zip new file mode 100644 index 000000000..193a3c931 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.11-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.12-compact.zip new file mode 100644 index 000000000..02d8a6c37 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.12-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.13-compact.zip new file mode 100644 index 000000000..6225bd2c2 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.13-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.14-compact.zip new file mode 100644 index 000000000..6c13dbacc Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.14-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.15-compact.zip new file mode 100644 index 000000000..fb3120b43 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.4-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.4-compact.zip new file mode 100644 index 000000000..79aa6ddf6 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.4-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.5-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.5-compact.zip new file mode 100644 index 000000000..3c91ae99a Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.5-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.6-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.6-compact.zip new file mode 100644 index 000000000..0c0de9fb8 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.6-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.7-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.7-compact.zip new file mode 100644 index 000000000..7a3ef5b72 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.7-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.8-compact.zip new file mode 100644 index 000000000..0f1e60672 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.8-compact.zip differ diff --git a/tests/ast-parsing/compile/custom-error-selector.sol-0.8.9-compact.zip b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.9-compact.zip new file mode 100644 index 000000000..eae6bf9c1 Binary files /dev/null and b/tests/ast-parsing/compile/custom-error-selector.sol-0.8.9-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.zip new file mode 100644 index 000000000..2dedfd0a6 Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.zip new file mode 100644 index 000000000..373ed8650 Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.zip new file mode 100644 index 000000000..573f4efc0 Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.zip new file mode 100644 index 000000000..798230e9c Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.zip new file mode 100644 index 000000000..db90bfcab Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.zip new file mode 100644 index 000000000..3d3a0f0b2 Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.zip new file mode 100644 index 000000000..89d650f85 Binary files /dev/null and b/tests/ast-parsing/compile/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.zip differ diff --git a/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip new file mode 100644 index 000000000..ca32c7583 Binary files /dev/null and b/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-top-level-0.8.0.sol-0.8.0-compact.zip b/tests/ast-parsing/compile/yul-top-level-0.8.0.sol-0.8.0-compact.zip new file mode 100644 index 000000000..ce81a5c37 Binary files /dev/null and b/tests/ast-parsing/compile/yul-top-level-0.8.0.sol-0.8.0-compact.zip differ diff --git a/tests/ast-parsing/complex_imports/import_aliases_issue_1319/import.sol b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/import.sol new file mode 100644 index 000000000..7cfff4bfa --- /dev/null +++ b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/import.sol @@ -0,0 +1 @@ +contract A {} \ No newline at end of file diff --git a/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test.sol b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test.sol new file mode 100644 index 000000000..7c5bf1eee --- /dev/null +++ b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test.sol @@ -0,0 +1,9 @@ +pragma solidity 0.5.12; + +import {A} from "./import.sol"; + +contract Z is A { + function test() public pure returns (uint) { + return 1; + } +} \ No newline at end of file diff --git a/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test_fail.sol b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test_fail.sol new file mode 100644 index 000000000..eb2ab8af0 --- /dev/null +++ b/tests/ast-parsing/complex_imports/import_aliases_issue_1319/test_fail.sol @@ -0,0 +1,9 @@ +pragma solidity 0.5.12; + +import {A as X, A as Y} from "./import.sol"; + +contract Z is X { + function test() public pure returns (uint) { + return 1; + } +} \ No newline at end of file diff --git a/tests/ast-parsing/custom-error-selector.sol b/tests/ast-parsing/custom-error-selector.sol new file mode 100644 index 000000000..05fe75f99 --- /dev/null +++ b/tests/ast-parsing/custom-error-selector.sol @@ -0,0 +1,13 @@ + contract Test { + error myError(); +} + +interface VM { + function expectRevert(bytes4) external; + function expectRevert(bytes calldata) external; +} +contract A { + function b(address c) public { + VM(c).expectRevert(Test.myError.selector); + } +} diff --git a/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.json b/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.json new file mode 100644 index 000000000..4132f73d9 --- /dev/null +++ b/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-compact.json @@ -0,0 +1,6 @@ +{ + "A": {}, + "Z": { + "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.json b/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.json new file mode 100644 index 000000000..4132f73d9 --- /dev/null +++ b/tests/ast-parsing/expected/complex_imports/import_aliases_issue_1319/test.sol-0.5.12-legacy.json @@ -0,0 +1,6 @@ +{ + "A": {}, + "Z": { + "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.10-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.10-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.10-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.11-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.11-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.11-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.12-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.12-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.12-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.13-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.13-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.13-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.14-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.14-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.14-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.15-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.15-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.15-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.4-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.4-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.4-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.5-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.5-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.5-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.6-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.6-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.6-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.7-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.7-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.7-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.8-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.8-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.8-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/custom-error-selector.sol-0.8.9-compact.json b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.9-compact.json new file mode 100644 index 000000000..d35b14059 --- /dev/null +++ b/tests/ast-parsing/expected/custom-error-selector.sol-0.8.9-compact.json @@ -0,0 +1,10 @@ +{ + "Test": {}, + "VM": { + "expectRevert(bytes4)": "digraph{\n}\n", + "expectRevert(bytes)": "digraph{\n}\n" + }, + "A": { + "b(address)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.10-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.11-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.12-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.13-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.14-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.15-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.json b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.json new file mode 100644 index 000000000..58fb20ce1 --- /dev/null +++ b/tests/ast-parsing/expected/user_defined_value_type/using-for-0.8.8.sol-0.8.8-compact.json @@ -0,0 +1,11 @@ +{ + "MyLib": { + "a()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: RETURN 2\n\"];\n}\n" + }, + "A": { + "b(MyType)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "c(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json b/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json new file mode 100644 index 000000000..4975ab40a --- /dev/null +++ b/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json @@ -0,0 +1,8 @@ +{ + "A": { + "a(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "b(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/user_defined_value_type/using-for-0.8.8.sol b/tests/ast-parsing/user_defined_value_type/using-for-0.8.8.sol new file mode 100644 index 000000000..bc65038ab --- /dev/null +++ b/tests/ast-parsing/user_defined_value_type/using-for-0.8.8.sol @@ -0,0 +1,22 @@ +type MyType is uint256; + +library MyLib { + using A for MyType; + using B for uint; + function a() internal returns(uint){ + MyType myvar = MyType.wrap(4); + return MyType.unwrap(myvar.b()).c(); + } +} + +library A { + function b(MyType e) public returns(MyType){ + return MyType.wrap(3); + } + +} +library B { + function c(uint e) public returns(uint){ + return 345; + } +} \ No newline at end of file diff --git a/tests/ast-parsing/using-for-in-library-0.8.0.sol b/tests/ast-parsing/using-for-in-library-0.8.0.sol new file mode 100644 index 000000000..0e8f6a6b9 --- /dev/null +++ b/tests/ast-parsing/using-for-in-library-0.8.0.sol @@ -0,0 +1,14 @@ + +library A { + using B for uint256; + + function a(uint256 v) public view returns (uint) { + return v.b(); + } +} + +library B { + function b(uint256 v) public view returns (uint) { + return 1; + } +} diff --git a/tests/ast-parsing/yul-top-level-0.8.0.sol b/tests/ast-parsing/yul-top-level-0.8.0.sol new file mode 100644 index 000000000..214db9cb4 --- /dev/null +++ b/tests/ast-parsing/yul-top-level-0.8.0.sol @@ -0,0 +1,16 @@ +function top_level_yul(int256 c) pure returns (uint result) { + assembly { + function internal_yul(a) -> b { + b := a + } + + result := internal_yul(c) + } +} + + +contract Test { + function test() public{ + top_level_yul(10); + } +} \ No newline at end of file diff --git a/tests/constant_folding_binop.sol b/tests/constant_folding_binop.sol new file mode 100644 index 000000000..923418ce7 --- /dev/null +++ b/tests/constant_folding_binop.sol @@ -0,0 +1,14 @@ +contract BinOp { + uint a = 1 & 2; + uint b = 1 ^ 2; + uint c = 1 | 2; + bool d = 2 < 1; + bool e = 1 > 2; + bool f = 1 <= 2; + bool g = 1 >= 2; + bool h = 1 == 2; + bool i = 1 != 2; + bool j = true && false; + bool k = true || false; + uint l = uint(1) - uint(2); +} \ No newline at end of file diff --git a/tests/detectors/constable-states/0.4.25/const_state_variables.sol b/tests/detectors/constable-states/0.4.25/const_state_variables.sol index aed05d97f..45f8cc87a 100644 --- a/tests/detectors/constable-states/0.4.25/const_state_variables.sol +++ b/tests/detectors/constable-states/0.4.25/const_state_variables.sol @@ -44,7 +44,12 @@ contract MyConc{ address not_constant = msg.sender; uint not_constant_2 = getNumber(); uint not_constant_3 = 10 + block.number; + uint not_constant_5; + constructor(uint b) public { + not_constant_5 = b; + } + function getNumber() public returns(uint){ return block.number; } diff --git a/tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.ConstCandidateStateVars.json b/tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.CouldBeConstant.json similarity index 91% rename from tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.ConstCandidateStateVars.json rename to tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.CouldBeConstant.json index 4ab2cfa83..51a485f5b 100644 --- a/tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.ConstCandidateStateVars.json +++ b/tests/detectors/constable-states/0.4.25/const_state_variables.sol.0.4.25.CouldBeConstant.json @@ -4,19 +4,19 @@ "elements": [ { "type": "variable", - "name": "myFriendsAddress", + "name": "text2", "source_mapping": { - "start": 132, - "length": 76, + "start": 333, + "length": 20, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "is_dependency": false, "lines": [ - 7 + 14 ], "starting_column": 5, - "ending_column": 81 + "ending_column": 25 }, "type_specific_fields": { "parent": { @@ -56,10 +56,10 @@ } } ], - "description": "A.myFriendsAddress (tests/detectors/constable-states/0.4.25/const_state_variables.sol#7) should be constant\n", - "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L7) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L7", - "id": "1454db80653b732bf6acbe54ff0ae4707002207a2a8216708c12d61c88a43e5f", + "description": "A.text2 (tests/detectors/constable-states/0.4.25/const_state_variables.sol#14) should be constant \n", + "markdown": "[A.text2](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L14) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L14", + "id": "2f06e04545cea7e7a8998c65d5419f335bf2579a6ce6a832eac9c87392fd5c1a", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -68,19 +68,79 @@ "elements": [ { "type": "variable", - "name": "test", + "name": "mySistersAddress", "source_mapping": { - "start": 237, - "length": 20, + "start": 496, + "length": 76, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "is_dependency": false, "lines": [ - 10 + 26 ], "starting_column": 5, - "ending_column": 25 + "ending_column": 81 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "B", + "source_mapping": { + "start": 473, + "length": 271, + "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "B.mySistersAddress (tests/detectors/constable-states/0.4.25/const_state_variables.sol#26) should be constant \n", + "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L26) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L26", + "id": "3b5bff93954a48a79387e7981e8c45d78edc575a0988a10f1c7f439b9f930539", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "myFriendsAddress", + "source_mapping": { + "start": 132, + "length": 76, + "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 5, + "ending_column": 81 }, "type_specific_fields": { "parent": { @@ -120,10 +180,10 @@ } } ], - "description": "A.test (tests/detectors/constable-states/0.4.25/const_state_variables.sol#10) should be constant\n", - "markdown": "[A.test](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L10) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L10", - "id": "5d9e3fb413322b71a93e90f7e89bd8c83cd4884d577d039598c681fe9db38b1d", + "description": "A.myFriendsAddress (tests/detectors/constable-states/0.4.25/const_state_variables.sol#7) should be constant \n", + "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L7) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L7", + "id": "52fd72f6870c4b504d1bcf9fb44249658e2077474d66208a33a47d2668b8db49", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -132,19 +192,19 @@ "elements": [ { "type": "variable", - "name": "should_be_constant_2", + "name": "should_be_constant", "source_mapping": { - "start": 841, - "length": 33, + "start": 793, + "length": 42, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "is_dependency": false, "lines": [ - 43 + 42 ], "starting_column": 5, - "ending_column": 38 + "ending_column": 47 }, "type_specific_fields": { "parent": { @@ -152,7 +212,7 @@ "name": "MyConc", "source_mapping": { "start": 746, - "length": 342, + "length": 423, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", @@ -171,7 +231,12 @@ 49, 50, 51, - 52 + 52, + 53, + 54, + 55, + 56, + 57 ], "starting_column": 1, "ending_column": 2 @@ -180,70 +245,10 @@ } } ], - "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.4.25/const_state_variables.sol#43) should be constant\n", - "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L43) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L43", - "id": "9a48a4122de1a6a4774a9f1e0d4917bd0fa08f17b4af41b86ba07689e51bf711", - "check": "constable-states", - "impact": "Optimization", - "confidence": "High" - }, - { - "elements": [ - { - "type": "variable", - "name": "mySistersAddress", - "source_mapping": { - "start": 496, - "length": 76, - "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", - "filename_absolute": "/GENERIC_PATH", - "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", - "is_dependency": false, - "lines": [ - 26 - ], - "starting_column": 5, - "ending_column": 81 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "B", - "source_mapping": { - "start": 473, - "length": 271, - "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", - "filename_absolute": "/GENERIC_PATH", - "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", - "is_dependency": false, - "lines": [ - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37 - ], - "starting_column": 1, - "ending_column": 2 - } - } - } - } - ], - "description": "B.mySistersAddress (tests/detectors/constable-states/0.4.25/const_state_variables.sol#26) should be constant\n", - "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L26) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L26", - "id": "bee93a722c8eae4a48aade67d8ef537d84c106f48fc9eb738c795fce10d3bc63", + "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.4.25/const_state_variables.sol#42) should be constant \n", + "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L42) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L42", + "id": "8d08797efc8230b480ec669c7e2bf53c3b3d16bc59bf7770934b34fd892934f8", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -252,19 +257,19 @@ "elements": [ { "type": "variable", - "name": "should_be_constant", + "name": "should_be_constant_2", "source_mapping": { - "start": 793, - "length": 42, + "start": 841, + "length": 33, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "is_dependency": false, "lines": [ - 42 + 43 ], "starting_column": 5, - "ending_column": 47 + "ending_column": 38 }, "type_specific_fields": { "parent": { @@ -272,7 +277,7 @@ "name": "MyConc", "source_mapping": { "start": 746, - "length": 342, + "length": 423, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", @@ -291,7 +296,12 @@ 49, 50, 51, - 52 + 52, + 53, + 54, + 55, + 56, + 57 ], "starting_column": 1, "ending_column": 2 @@ -300,10 +310,10 @@ } } ], - "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.4.25/const_state_variables.sol#42) should be constant\n", - "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L42) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L42", - "id": "cbcafa2a3efba4d21ac1b51b4b823e5082d556bc3d6cf3fd2ab3188f9f218fc1", + "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.4.25/const_state_variables.sol#43) should be constant \n", + "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L43) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L43", + "id": "d08c6d1e331083b42c45c222691dd1e6d880814c66d114971875337ca61ba9c9", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -312,16 +322,16 @@ "elements": [ { "type": "variable", - "name": "text2", + "name": "test", "source_mapping": { - "start": 333, + "start": 237, "length": 20, "filename_relative": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.4.25/const_state_variables.sol", "is_dependency": false, "lines": [ - 14 + 10 ], "starting_column": 5, "ending_column": 25 @@ -364,10 +374,10 @@ } } ], - "description": "A.text2 (tests/detectors/constable-states/0.4.25/const_state_variables.sol#14) should be constant\n", - "markdown": "[A.text2](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L14) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L14", - "id": "df11e6201c4558a8c5cd90b55b134b9ca8f07203b2264d3aa93bd7745e8cb4ba", + "description": "A.test (tests/detectors/constable-states/0.4.25/const_state_variables.sol#10) should be constant \n", + "markdown": "[A.test](tests/detectors/constable-states/0.4.25/const_state_variables.sol#L10) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.4.25/const_state_variables.sol#L10", + "id": "e407a1b57b4d25949ef7c4e6d97197605857099a94774a9c7a848d7dd3463668", "check": "constable-states", "impact": "Optimization", "confidence": "High" diff --git a/tests/detectors/constable-states/0.5.16/const_state_variables.sol b/tests/detectors/constable-states/0.5.16/const_state_variables.sol index aed05d97f..8fd1ca808 100644 --- a/tests/detectors/constable-states/0.5.16/const_state_variables.sol +++ b/tests/detectors/constable-states/0.5.16/const_state_variables.sol @@ -41,10 +41,16 @@ contract MyConc{ uint constant A = 1; bytes32 should_be_constant = sha256('abc'); uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); address not_constant = msg.sender; uint not_constant_2 = getNumber(); uint not_constant_3 = 10 + block.number; + uint not_constant_5; + constructor(uint b) public { + not_constant_5 = b; + } + function getNumber() public returns(uint){ return block.number; } diff --git a/tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.ConstCandidateStateVars.json b/tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.CouldBeConstant.json similarity index 78% rename from tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.ConstCandidateStateVars.json rename to tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.CouldBeConstant.json index 9b435a4a8..f9ed17eb1 100644 --- a/tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.ConstCandidateStateVars.json +++ b/tests/detectors/constable-states/0.5.16/const_state_variables.sol.0.5.16.CouldBeConstant.json @@ -4,50 +4,52 @@ "elements": [ { "type": "variable", - "name": "myFriendsAddress", + "name": "should_be_constant_3", "source_mapping": { - "start": 132, - "length": 76, + "start": 880, + "length": 38, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 7 + 44 ], "starting_column": 5, - "ending_column": 81 + "ending_column": 43 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "A", + "name": "MyConc", "source_mapping": { - "start": 29, - "length": 441, + "start": 746, + "length": 467, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21 + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58 ], "starting_column": 1, "ending_column": 2 @@ -56,10 +58,10 @@ } } ], - "description": "A.myFriendsAddress (tests/detectors/constable-states/0.5.16/const_state_variables.sol#7) should be constant\n", - "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L7) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L7", - "id": "1454db80653b732bf6acbe54ff0ae4707002207a2a8216708c12d61c88a43e5f", + "description": "MyConc.should_be_constant_3 (tests/detectors/constable-states/0.5.16/const_state_variables.sol#44) should be constant \n", + "markdown": "[MyConc.should_be_constant_3](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L44) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L44", + "id": "29247b0a9939e854ad51bf3b2f58705156aa8b7e446e646b1832467d362b5b3e", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -68,16 +70,16 @@ "elements": [ { "type": "variable", - "name": "test", + "name": "text2", "source_mapping": { - "start": 237, + "start": 333, "length": 20, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 10 + 14 ], "starting_column": 5, "ending_column": 25 @@ -120,10 +122,10 @@ } } ], - "description": "A.test (tests/detectors/constable-states/0.5.16/const_state_variables.sol#10) should be constant\n", - "markdown": "[A.test](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L10) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L10", - "id": "5d9e3fb413322b71a93e90f7e89bd8c83cd4884d577d039598c681fe9db38b1d", + "description": "A.text2 (tests/detectors/constable-states/0.5.16/const_state_variables.sol#14) should be constant \n", + "markdown": "[A.text2](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L14) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L14", + "id": "2f06e04545cea7e7a8998c65d5419f335bf2579a6ce6a832eac9c87392fd5c1a", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -132,46 +134,46 @@ "elements": [ { "type": "variable", - "name": "should_be_constant_2", + "name": "mySistersAddress", "source_mapping": { - "start": 841, - "length": 33, + "start": 496, + "length": 76, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 43 + 26 ], "starting_column": 5, - "ending_column": 38 + "ending_column": 81 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "MyConc", + "name": "B", "source_mapping": { - "start": 746, - "length": 342, + "start": 473, + "length": 271, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52 + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37 ], "starting_column": 1, "ending_column": 2 @@ -180,10 +182,10 @@ } } ], - "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.5.16/const_state_variables.sol#43) should be constant\n", - "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L43) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L43", - "id": "9a48a4122de1a6a4774a9f1e0d4917bd0fa08f17b4af41b86ba07689e51bf711", + "description": "B.mySistersAddress (tests/detectors/constable-states/0.5.16/const_state_variables.sol#26) should be constant \n", + "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L26) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L26", + "id": "3b5bff93954a48a79387e7981e8c45d78edc575a0988a10f1c7f439b9f930539", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -192,16 +194,16 @@ "elements": [ { "type": "variable", - "name": "mySistersAddress", + "name": "myFriendsAddress", "source_mapping": { - "start": 496, + "start": 132, "length": 76, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 26 + 7 ], "starting_column": 5, "ending_column": 81 @@ -209,29 +211,33 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "B", + "name": "A", "source_mapping": { - "start": 473, - "length": 271, + "start": 29, + "length": 441, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37 + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21 ], "starting_column": 1, "ending_column": 2 @@ -240,10 +246,10 @@ } } ], - "description": "B.mySistersAddress (tests/detectors/constable-states/0.5.16/const_state_variables.sol#26) should be constant\n", - "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L26) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L26", - "id": "bee93a722c8eae4a48aade67d8ef537d84c106f48fc9eb738c795fce10d3bc63", + "description": "A.myFriendsAddress (tests/detectors/constable-states/0.5.16/const_state_variables.sol#7) should be constant \n", + "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L7) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L7", + "id": "52fd72f6870c4b504d1bcf9fb44249658e2077474d66208a33a47d2668b8db49", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -272,7 +278,7 @@ "name": "MyConc", "source_mapping": { "start": 746, - "length": 342, + "length": 467, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", @@ -291,7 +297,13 @@ 49, 50, 51, - 52 + 52, + 53, + 54, + 55, + 56, + 57, + 58 ], "starting_column": 1, "ending_column": 2 @@ -300,10 +312,10 @@ } } ], - "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.5.16/const_state_variables.sol#42) should be constant\n", - "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L42) should be constant\n", + "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.5.16/const_state_variables.sol#42) should be constant \n", + "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L42) should be constant \n", "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L42", - "id": "cbcafa2a3efba4d21ac1b51b4b823e5082d556bc3d6cf3fd2ab3188f9f218fc1", + "id": "8d08797efc8230b480ec669c7e2bf53c3b3d16bc59bf7770934b34fd892934f8", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -312,16 +324,82 @@ "elements": [ { "type": "variable", - "name": "text2", + "name": "should_be_constant_2", "source_mapping": { - "start": 333, + "start": 841, + "length": 33, + "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 43 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "MyConc", + "source_mapping": { + "start": 746, + "length": 467, + "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.5.16/const_state_variables.sol#43) should be constant \n", + "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L43) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L43", + "id": "d08c6d1e331083b42c45c222691dd1e6d880814c66d114971875337ca61ba9c9", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "test", + "source_mapping": { + "start": 237, "length": 20, "filename_relative": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.5.16/const_state_variables.sol", "is_dependency": false, "lines": [ - 14 + 10 ], "starting_column": 5, "ending_column": 25 @@ -364,10 +442,10 @@ } } ], - "description": "A.text2 (tests/detectors/constable-states/0.5.16/const_state_variables.sol#14) should be constant\n", - "markdown": "[A.text2](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L14) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L14", - "id": "df11e6201c4558a8c5cd90b55b134b9ca8f07203b2264d3aa93bd7745e8cb4ba", + "description": "A.test (tests/detectors/constable-states/0.5.16/const_state_variables.sol#10) should be constant \n", + "markdown": "[A.test](tests/detectors/constable-states/0.5.16/const_state_variables.sol#L10) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.5.16/const_state_variables.sol#L10", + "id": "e407a1b57b4d25949ef7c4e6d97197605857099a94774a9c7a848d7dd3463668", "check": "constable-states", "impact": "Optimization", "confidence": "High" diff --git a/tests/detectors/constable-states/0.6.11/const_state_variables.sol b/tests/detectors/constable-states/0.6.11/const_state_variables.sol index 3b0c1a436..17548f46f 100644 --- a/tests/detectors/constable-states/0.6.11/const_state_variables.sol +++ b/tests/detectors/constable-states/0.6.11/const_state_variables.sol @@ -1,5 +1,3 @@ -//pragma solidity ^0.4.24; - contract A { @@ -36,17 +34,46 @@ contract B is A { } } -contract MyConc{ +contract Bad { uint constant A = 1; bytes32 should_be_constant = sha256('abc'); uint should_be_constant_2 = A + 1; - address not_constant = msg.sender; - uint not_constant_2 = getNumber(); - uint not_constant_3 = 10 + block.number; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + B should_be_immutable_4 = new B(); + uint should_be_immutable_5; + constructor(uint b) public { + should_be_immutable_5 = b; + } + function getNumber() public returns(uint){ return block.number; } } + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) public { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} \ No newline at end of file diff --git a/tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.ConstCandidateStateVars.json b/tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.CouldBeConstant.json similarity index 67% rename from tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.ConstCandidateStateVars.json rename to tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.CouldBeConstant.json index 3c7812877..ac3608f81 100644 --- a/tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.ConstCandidateStateVars.json +++ b/tests/detectors/constable-states/0.6.11/const_state_variables.sol.0.6.11.CouldBeConstant.json @@ -4,32 +4,34 @@ "elements": [ { "type": "variable", - "name": "myFriendsAddress", + "name": "text2", "source_mapping": { - "start": 132, - "length": 76, + "start": 305, + "length": 20, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 7 + 12 ], "starting_column": 5, - "ending_column": 81 + "ending_column": 25 }, "type_specific_fields": { "parent": { "type": "contract", "name": "A", "source_mapping": { - "start": 29, + "start": 1, "length": 441, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ + 2, + 3, 4, 5, 6, @@ -45,9 +47,7 @@ 16, 17, 18, - 19, - 20, - 21 + 19 ], "starting_column": 1, "ending_column": 2 @@ -56,10 +56,10 @@ } } ], - "description": "A.myFriendsAddress (tests/detectors/constable-states/0.6.11/const_state_variables.sol#7) should be constant\n", - "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L7) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L7", - "id": "1454db80653b732bf6acbe54ff0ae4707002207a2a8216708c12d61c88a43e5f", + "description": "A.text2 (tests/detectors/constable-states/0.6.11/const_state_variables.sol#12) should be constant \n", + "markdown": "[A.text2](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L12) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L12", + "id": "2f06e04545cea7e7a8998c65d5419f335bf2579a6ce6a832eac9c87392fd5c1a", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -68,50 +68,53 @@ "elements": [ { "type": "variable", - "name": "test", + "name": "should_be_constant_2", "source_mapping": { - "start": 237, - "length": 20, + "start": 811, + "length": 33, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 10 + 41 ], "starting_column": 5, - "ending_column": 25 + "ending_column": 38 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "A", + "name": "Bad", "source_mapping": { - "start": 29, - "length": 441, + "start": 718, + "length": 539, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21 + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 ], "starting_column": 1, "ending_column": 2 @@ -120,10 +123,10 @@ } } ], - "description": "A.test (tests/detectors/constable-states/0.6.11/const_state_variables.sol#10) should be constant\n", - "markdown": "[A.test](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L10) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L10", - "id": "5d9e3fb413322b71a93e90f7e89bd8c83cd4884d577d039598c681fe9db38b1d", + "description": "Bad.should_be_constant_2 (tests/detectors/constable-states/0.6.11/const_state_variables.sol#41) should be constant \n", + "markdown": "[Bad.should_be_constant_2](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L41) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L41", + "id": "3a8b682f7960750cd8228d6cd3d0bb5d7d6f9faaf1a044de2fa7069d8e475af2", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -132,46 +135,46 @@ "elements": [ { "type": "variable", - "name": "should_be_constant_2", + "name": "mySistersAddress", "source_mapping": { - "start": 841, - "length": 33, + "start": 468, + "length": 76, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 43 + 24 ], "starting_column": 5, - "ending_column": 38 + "ending_column": 81 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "MyConc", + "name": "B", "source_mapping": { - "start": 746, - "length": 342, + "start": 445, + "length": 271, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52 + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35 ], "starting_column": 1, "ending_column": 2 @@ -180,10 +183,10 @@ } } ], - "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.6.11/const_state_variables.sol#43) should be constant\n", - "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L43) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L43", - "id": "9a48a4122de1a6a4774a9f1e0d4917bd0fa08f17b4af41b86ba07689e51bf711", + "description": "B.mySistersAddress (tests/detectors/constable-states/0.6.11/const_state_variables.sol#24) should be constant \n", + "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L24) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L24", + "id": "3b5bff93954a48a79387e7981e8c45d78edc575a0988a10f1c7f439b9f930539", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -192,16 +195,16 @@ "elements": [ { "type": "variable", - "name": "mySistersAddress", + "name": "myFriendsAddress", "source_mapping": { - "start": 496, + "start": 104, "length": 76, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 26 + 5 ], "starting_column": 5, "ending_column": 81 @@ -209,29 +212,33 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "B", + "name": "A", "source_mapping": { - "start": 473, - "length": 271, + "start": 1, + "length": 441, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37 + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 ], "starting_column": 1, "ending_column": 2 @@ -240,10 +247,10 @@ } } ], - "description": "B.mySistersAddress (tests/detectors/constable-states/0.6.11/const_state_variables.sol#26) should be constant\n", - "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L26) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L26", - "id": "bee93a722c8eae4a48aade67d8ef537d84c106f48fc9eb738c795fce10d3bc63", + "description": "A.myFriendsAddress (tests/detectors/constable-states/0.6.11/const_state_variables.sol#5) should be constant \n", + "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L5) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L5", + "id": "52fd72f6870c4b504d1bcf9fb44249658e2077474d66208a33a47d2668b8db49", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -254,14 +261,14 @@ "type": "variable", "name": "should_be_constant", "source_mapping": { - "start": 793, + "start": 763, "length": 42, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 42 + 40 ], "starting_column": 5, "ending_column": 47 @@ -269,15 +276,84 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "MyConc", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_constant (tests/detectors/constable-states/0.6.11/const_state_variables.sol#40) should be constant \n", + "markdown": "[Bad.should_be_constant](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L40) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L40", + "id": "87097c03d57b72ad7c15336eb44e5a30054c50f8daff32e08bc4fbd97852961c", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_constant_3", + "source_mapping": { + "start": 850, + "length": 38, + "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 42 + ], + "starting_column": 5, + "ending_column": 43 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", "source_mapping": { - "start": 746, - "length": 342, + "start": 718, + "length": 539, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ + 37, + 38, 39, 40, 41, @@ -291,7 +367,12 @@ 49, 50, 51, - 52 + 52, + 53, + 54, + 55, + 56, + 57 ], "starting_column": 1, "ending_column": 2 @@ -300,10 +381,10 @@ } } ], - "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.6.11/const_state_variables.sol#42) should be constant\n", - "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L42) should be constant\n", + "description": "Bad.should_be_constant_3 (tests/detectors/constable-states/0.6.11/const_state_variables.sol#42) should be constant \n", + "markdown": "[Bad.should_be_constant_3](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L42) should be constant \n", "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L42", - "id": "cbcafa2a3efba4d21ac1b51b4b823e5082d556bc3d6cf3fd2ab3188f9f218fc1", + "id": "8e991c1370b1adb10f01f2d7e48f341dee92a98b91b56ccb291d9149d2da97d0", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -312,16 +393,16 @@ "elements": [ { "type": "variable", - "name": "text2", + "name": "test", "source_mapping": { - "start": 333, + "start": 209, "length": 20, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ - 14 + 8 ], "starting_column": 5, "ending_column": 25 @@ -331,13 +412,15 @@ "type": "contract", "name": "A", "source_mapping": { - "start": 29, + "start": 1, "length": 441, "filename_relative": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.6.11/const_state_variables.sol", "is_dependency": false, "lines": [ + 2, + 3, 4, 5, 6, @@ -353,9 +436,7 @@ 16, 17, 18, - 19, - 20, - 21 + 19 ], "starting_column": 1, "ending_column": 2 @@ -364,10 +445,10 @@ } } ], - "description": "A.text2 (tests/detectors/constable-states/0.6.11/const_state_variables.sol#14) should be constant\n", - "markdown": "[A.text2](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L14) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L14", - "id": "df11e6201c4558a8c5cd90b55b134b9ca8f07203b2264d3aa93bd7745e8cb4ba", + "description": "A.test (tests/detectors/constable-states/0.6.11/const_state_variables.sol#8) should be constant \n", + "markdown": "[A.test](tests/detectors/constable-states/0.6.11/const_state_variables.sol#L8) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.6.11/const_state_variables.sol#L8", + "id": "e407a1b57b4d25949ef7c4e6d97197605857099a94774a9c7a848d7dd3463668", "check": "constable-states", "impact": "Optimization", "confidence": "High" diff --git a/tests/detectors/constable-states/0.7.6/const_state_variables.sol b/tests/detectors/constable-states/0.7.6/const_state_variables.sol index 3b0c1a436..297dd6294 100644 --- a/tests/detectors/constable-states/0.7.6/const_state_variables.sol +++ b/tests/detectors/constable-states/0.7.6/const_state_variables.sol @@ -1,5 +1,3 @@ -//pragma solidity ^0.4.24; - contract A { @@ -36,15 +34,43 @@ contract B is A { } } -contract MyConc{ +contract Bad { uint constant A = 1; bytes32 should_be_constant = sha256('abc'); uint should_be_constant_2 = A + 1; - address not_constant = msg.sender; - uint not_constant_2 = getNumber(); - uint not_constant_3 = 10 + block.number; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + B should_be_immutable_4 = new B(); + uint should_be_immutable_5; + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } +} + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + function getNumber() public returns(uint){ return block.number; } diff --git a/tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.ConstCandidateStateVars.json b/tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.CouldBeConstant.json similarity index 67% rename from tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.ConstCandidateStateVars.json rename to tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.CouldBeConstant.json index 3cb6d44c4..d54beb405 100644 --- a/tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.ConstCandidateStateVars.json +++ b/tests/detectors/constable-states/0.7.6/const_state_variables.sol.0.7.6.CouldBeConstant.json @@ -4,32 +4,34 @@ "elements": [ { "type": "variable", - "name": "myFriendsAddress", + "name": "text2", "source_mapping": { - "start": 132, - "length": 76, + "start": 305, + "length": 20, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 7 + 12 ], "starting_column": 5, - "ending_column": 81 + "ending_column": 25 }, "type_specific_fields": { "parent": { "type": "contract", "name": "A", "source_mapping": { - "start": 29, + "start": 1, "length": 441, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ + 2, + 3, 4, 5, 6, @@ -45,9 +47,7 @@ 16, 17, 18, - 19, - 20, - 21 + 19 ], "starting_column": 1, "ending_column": 2 @@ -56,10 +56,10 @@ } } ], - "description": "A.myFriendsAddress (tests/detectors/constable-states/0.7.6/const_state_variables.sol#7) should be constant\n", - "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L7) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L7", - "id": "1454db80653b732bf6acbe54ff0ae4707002207a2a8216708c12d61c88a43e5f", + "description": "A.text2 (tests/detectors/constable-states/0.7.6/const_state_variables.sol#12) should be constant \n", + "markdown": "[A.text2](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L12) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L12", + "id": "2f06e04545cea7e7a8998c65d5419f335bf2579a6ce6a832eac9c87392fd5c1a", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -68,50 +68,52 @@ "elements": [ { "type": "variable", - "name": "test", + "name": "should_be_constant_2", "source_mapping": { - "start": 237, - "length": 20, + "start": 811, + "length": 33, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 10 + 41 ], "starting_column": 5, - "ending_column": 25 + "ending_column": 38 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "A", + "name": "Bad", "source_mapping": { - "start": 29, - "length": 441, + "start": 718, + "length": 531, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21 + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 ], "starting_column": 1, "ending_column": 2 @@ -120,10 +122,10 @@ } } ], - "description": "A.test (tests/detectors/constable-states/0.7.6/const_state_variables.sol#10) should be constant\n", - "markdown": "[A.test](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L10) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L10", - "id": "5d9e3fb413322b71a93e90f7e89bd8c83cd4884d577d039598c681fe9db38b1d", + "description": "Bad.should_be_constant_2 (tests/detectors/constable-states/0.7.6/const_state_variables.sol#41) should be constant \n", + "markdown": "[Bad.should_be_constant_2](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L41) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L41", + "id": "3a8b682f7960750cd8228d6cd3d0bb5d7d6f9faaf1a044de2fa7069d8e475af2", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -132,46 +134,46 @@ "elements": [ { "type": "variable", - "name": "should_be_constant_2", + "name": "mySistersAddress", "source_mapping": { - "start": 841, - "length": 33, + "start": 468, + "length": 76, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 43 + 24 ], "starting_column": 5, - "ending_column": 38 + "ending_column": 81 }, "type_specific_fields": { "parent": { "type": "contract", - "name": "MyConc", + "name": "B", "source_mapping": { - "start": 746, - "length": 342, + "start": 445, + "length": 271, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52 + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35 ], "starting_column": 1, "ending_column": 2 @@ -180,10 +182,10 @@ } } ], - "description": "MyConc.should_be_constant_2 (tests/detectors/constable-states/0.7.6/const_state_variables.sol#43) should be constant\n", - "markdown": "[MyConc.should_be_constant_2](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L43) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L43", - "id": "9a48a4122de1a6a4774a9f1e0d4917bd0fa08f17b4af41b86ba07689e51bf711", + "description": "B.mySistersAddress (tests/detectors/constable-states/0.7.6/const_state_variables.sol#24) should be constant \n", + "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L24) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L24", + "id": "3b5bff93954a48a79387e7981e8c45d78edc575a0988a10f1c7f439b9f930539", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -192,16 +194,16 @@ "elements": [ { "type": "variable", - "name": "mySistersAddress", + "name": "myFriendsAddress", "source_mapping": { - "start": 496, + "start": 104, "length": 76, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 26 + 5 ], "starting_column": 5, "ending_column": 81 @@ -209,29 +211,33 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "B", + "name": "A", "source_mapping": { - "start": 473, - "length": 271, + "start": 1, + "length": 441, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37 + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 ], "starting_column": 1, "ending_column": 2 @@ -240,10 +246,10 @@ } } ], - "description": "B.mySistersAddress (tests/detectors/constable-states/0.7.6/const_state_variables.sol#26) should be constant\n", - "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L26) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L26", - "id": "bee93a722c8eae4a48aade67d8ef537d84c106f48fc9eb738c795fce10d3bc63", + "description": "A.myFriendsAddress (tests/detectors/constable-states/0.7.6/const_state_variables.sol#5) should be constant \n", + "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L5) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L5", + "id": "52fd72f6870c4b504d1bcf9fb44249658e2077474d66208a33a47d2668b8db49", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -254,14 +260,14 @@ "type": "variable", "name": "should_be_constant", "source_mapping": { - "start": 793, + "start": 763, "length": 42, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 42 + 40 ], "starting_column": 5, "ending_column": 47 @@ -269,15 +275,83 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "MyConc", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_constant (tests/detectors/constable-states/0.7.6/const_state_variables.sol#40) should be constant \n", + "markdown": "[Bad.should_be_constant](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L40) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L40", + "id": "87097c03d57b72ad7c15336eb44e5a30054c50f8daff32e08bc4fbd97852961c", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_constant_3", + "source_mapping": { + "start": 850, + "length": 38, + "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 42 + ], + "starting_column": 5, + "ending_column": 43 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", "source_mapping": { - "start": 746, - "length": 342, + "start": 718, + "length": 531, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ + 37, + 38, 39, 40, 41, @@ -291,7 +365,11 @@ 49, 50, 51, - 52 + 52, + 53, + 54, + 55, + 56 ], "starting_column": 1, "ending_column": 2 @@ -300,10 +378,10 @@ } } ], - "description": "MyConc.should_be_constant (tests/detectors/constable-states/0.7.6/const_state_variables.sol#42) should be constant\n", - "markdown": "[MyConc.should_be_constant](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L42) should be constant\n", + "description": "Bad.should_be_constant_3 (tests/detectors/constable-states/0.7.6/const_state_variables.sol#42) should be constant \n", + "markdown": "[Bad.should_be_constant_3](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L42) should be constant \n", "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L42", - "id": "cbcafa2a3efba4d21ac1b51b4b823e5082d556bc3d6cf3fd2ab3188f9f218fc1", + "id": "8e991c1370b1adb10f01f2d7e48f341dee92a98b91b56ccb291d9149d2da97d0", "check": "constable-states", "impact": "Optimization", "confidence": "High" @@ -312,16 +390,16 @@ "elements": [ { "type": "variable", - "name": "text2", + "name": "test", "source_mapping": { - "start": 333, + "start": 209, "length": 20, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ - 14 + 8 ], "starting_column": 5, "ending_column": 25 @@ -331,13 +409,15 @@ "type": "contract", "name": "A", "source_mapping": { - "start": 29, + "start": 1, "length": 441, "filename_relative": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "filename_absolute": "/GENERIC_PATH", "filename_short": "tests/detectors/constable-states/0.7.6/const_state_variables.sol", "is_dependency": false, "lines": [ + 2, + 3, 4, 5, 6, @@ -353,9 +433,7 @@ 16, 17, 18, - 19, - 20, - 21 + 19 ], "starting_column": 1, "ending_column": 2 @@ -364,10 +442,10 @@ } } ], - "description": "A.text2 (tests/detectors/constable-states/0.7.6/const_state_variables.sol#14) should be constant\n", - "markdown": "[A.text2](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L14) should be constant\n", - "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L14", - "id": "df11e6201c4558a8c5cd90b55b134b9ca8f07203b2264d3aa93bd7745e8cb4ba", + "description": "A.test (tests/detectors/constable-states/0.7.6/const_state_variables.sol#8) should be constant \n", + "markdown": "[A.test](tests/detectors/constable-states/0.7.6/const_state_variables.sol#L8) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.7.6/const_state_variables.sol#L8", + "id": "e407a1b57b4d25949ef7c4e6d97197605857099a94774a9c7a848d7dd3463668", "check": "constable-states", "impact": "Optimization", "confidence": "High" diff --git a/tests/detectors/constable-states/0.8.0/const_state_variables.sol b/tests/detectors/constable-states/0.8.0/const_state_variables.sol new file mode 100644 index 000000000..f405a1587 --- /dev/null +++ b/tests/detectors/constable-states/0.8.0/const_state_variables.sol @@ -0,0 +1,78 @@ + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + fallback () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract Bad { + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + uint should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} \ No newline at end of file diff --git a/tests/detectors/constable-states/0.8.0/const_state_variables.sol.0.8.0.CouldBeConstant.json b/tests/detectors/constable-states/0.8.0/const_state_variables.sol.0.8.0.CouldBeConstant.json new file mode 100644 index 000000000..7febfd637 --- /dev/null +++ b/tests/detectors/constable-states/0.8.0/const_state_variables.sol.0.8.0.CouldBeConstant.json @@ -0,0 +1,454 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "text2", + "source_mapping": { + "start": 305, + "length": 20, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 12 + ], + "starting_column": 5, + "ending_column": 25 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "A", + "source_mapping": { + "start": 1, + "length": 441, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "A.text2 (tests/detectors/constable-states/0.8.0/const_state_variables.sol#12) should be constant \n", + "markdown": "[A.text2](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L12) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L12", + "id": "2f06e04545cea7e7a8998c65d5419f335bf2579a6ce6a832eac9c87392fd5c1a", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_constant_2", + "source_mapping": { + "start": 811, + "length": 33, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 41 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_constant_2 (tests/detectors/constable-states/0.8.0/const_state_variables.sol#41) should be constant \n", + "markdown": "[Bad.should_be_constant_2](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L41) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L41", + "id": "3a8b682f7960750cd8228d6cd3d0bb5d7d6f9faaf1a044de2fa7069d8e475af2", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "mySistersAddress", + "source_mapping": { + "start": 468, + "length": 76, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 24 + ], + "starting_column": 5, + "ending_column": 81 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "B", + "source_mapping": { + "start": 445, + "length": 271, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "B.mySistersAddress (tests/detectors/constable-states/0.8.0/const_state_variables.sol#24) should be constant \n", + "markdown": "[B.mySistersAddress](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L24) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L24", + "id": "3b5bff93954a48a79387e7981e8c45d78edc575a0988a10f1c7f439b9f930539", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "myFriendsAddress", + "source_mapping": { + "start": 104, + "length": 76, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 5 + ], + "starting_column": 5, + "ending_column": 81 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "A", + "source_mapping": { + "start": 1, + "length": 441, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "A.myFriendsAddress (tests/detectors/constable-states/0.8.0/const_state_variables.sol#5) should be constant \n", + "markdown": "[A.myFriendsAddress](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L5) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L5", + "id": "52fd72f6870c4b504d1bcf9fb44249658e2077474d66208a33a47d2668b8db49", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_constant", + "source_mapping": { + "start": 763, + "length": 42, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 40 + ], + "starting_column": 5, + "ending_column": 47 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_constant (tests/detectors/constable-states/0.8.0/const_state_variables.sol#40) should be constant \n", + "markdown": "[Bad.should_be_constant](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L40) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L40", + "id": "87097c03d57b72ad7c15336eb44e5a30054c50f8daff32e08bc4fbd97852961c", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_constant_3", + "source_mapping": { + "start": 850, + "length": 38, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 42 + ], + "starting_column": 5, + "ending_column": 43 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_constant_3 (tests/detectors/constable-states/0.8.0/const_state_variables.sol#42) should be constant \n", + "markdown": "[Bad.should_be_constant_3](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L42) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L42", + "id": "8e991c1370b1adb10f01f2d7e48f341dee92a98b91b56ccb291d9149d2da97d0", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "test", + "source_mapping": { + "start": 209, + "length": 20, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 8 + ], + "starting_column": 5, + "ending_column": 25 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "A", + "source_mapping": { + "start": 1, + "length": 441, + "filename_relative": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/constable-states/0.8.0/const_state_variables.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "A.test (tests/detectors/constable-states/0.8.0/const_state_variables.sol#8) should be constant \n", + "markdown": "[A.test](tests/detectors/constable-states/0.8.0/const_state_variables.sol#L8) should be constant \n", + "first_markdown_element": "tests/detectors/constable-states/0.8.0/const_state_variables.sol#L8", + "id": "e407a1b57b4d25949ef7c4e6d97197605857099a94774a9c7a848d7dd3463668", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/constable-states/0.8.0/immutable.sol b/tests/detectors/constable-states/0.8.0/immutable.sol deleted file mode 100644 index aeb9fbfa7..000000000 --- a/tests/detectors/constable-states/0.8.0/immutable.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract C{ - uint immutable v; - - constructor() public{ - v = 0; - } -} diff --git a/tests/detectors/immutable-states/0.4.25/immut_state_variables.sol b/tests/detectors/immutable-states/0.4.25/immut_state_variables.sol new file mode 100644 index 000000000..45f8cc87a --- /dev/null +++ b/tests/detectors/immutable-states/0.4.25/immut_state_variables.sol @@ -0,0 +1,57 @@ +//pragma solidity ^0.4.24; + + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + function () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract MyConc{ + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + address not_constant = msg.sender; + uint not_constant_2 = getNumber(); + uint not_constant_3 = 10 + block.number; + uint not_constant_5; + + constructor(uint b) public { + not_constant_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} diff --git a/tests/detectors/constable-states/0.8.0/immutable.sol.0.8.0.ConstCandidateStateVars.json b/tests/detectors/immutable-states/0.4.25/immut_state_variables.sol.0.4.25.CouldBeImmutable.json similarity index 100% rename from tests/detectors/constable-states/0.8.0/immutable.sol.0.8.0.ConstCandidateStateVars.json rename to tests/detectors/immutable-states/0.4.25/immut_state_variables.sol.0.4.25.CouldBeImmutable.json diff --git a/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol b/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol new file mode 100644 index 000000000..8fd1ca808 --- /dev/null +++ b/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol @@ -0,0 +1,58 @@ +//pragma solidity ^0.4.24; + + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + function () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract MyConc{ + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); + address not_constant = msg.sender; + uint not_constant_2 = getNumber(); + uint not_constant_3 = 10 + block.number; + uint not_constant_5; + + constructor(uint b) public { + not_constant_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} diff --git a/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol.0.5.16.CouldBeImmutable.json b/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol.0.5.16.CouldBeImmutable.json new file mode 100644 index 000000000..5825bcacc --- /dev/null +++ b/tests/detectors/immutable-states/0.5.16/immut_state_variables.sol.0.5.16.CouldBeImmutable.json @@ -0,0 +1,3 @@ +[ + [] +] \ No newline at end of file diff --git a/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol b/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol new file mode 100644 index 000000000..17548f46f --- /dev/null +++ b/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol @@ -0,0 +1,79 @@ + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + fallback () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract Bad { + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + B should_be_immutable_4 = new B(); + uint should_be_immutable_5; + + constructor(uint b) public { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) public { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} \ No newline at end of file diff --git a/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol.0.6.11.CouldBeImmutable.json b/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol.0.6.11.CouldBeImmutable.json new file mode 100644 index 000000000..15064ca99 --- /dev/null +++ b/tests/detectors/immutable-states/0.6.11/immut_state_variables.sol.0.6.11.CouldBeImmutable.json @@ -0,0 +1,339 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_5", + "source_mapping": { + "start": 1077, + "length": 26, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 47 + ], + "starting_column": 5, + "ending_column": 31 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_5 (tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#47) should be immutable \n", + "markdown": "[Bad.should_be_immutable_5](tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L47) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L47", + "id": "42d50245236163ceca90dea732165e65c2155934b149a5a1a5c51bddc0b5b02a", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_2", + "source_mapping": { + "start": 940, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 44 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_2 (tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#44) should be immutable \n", + "markdown": "[Bad.should_be_immutable_2](tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L44) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L44", + "id": "70d57aa51dda92c28444a466db8567fa783c85d484259aa5eee2ebc63f97a200", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_4", + "source_mapping": { + "start": 1038, + "length": 33, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_4 (tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#46) should be immutable \n", + "markdown": "[Bad.should_be_immutable_4](tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L46) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L46", + "id": "a26d6df4087ac010928bc4bd18aa70ac58a28e584b1288e348d9c255473c300d", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable", + "source_mapping": { + "start": 894, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 43 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable (tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#43) should be immutable \n", + "markdown": "[Bad.should_be_immutable](tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L43) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L43", + "id": "b163d277f544f7f05ed4bcddda61e444be893e65ba0469688abd7b401a1db222", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_3", + "source_mapping": { + "start": 986, + "length": 46, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 45 + ], + "starting_column": 5, + "ending_column": 51 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 539, + "filename_relative": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_3 (tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#45) should be immutable \n", + "markdown": "[Bad.should_be_immutable_3](tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L45) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.6.11/immut_state_variables.sol#L45", + "id": "f19f7a22a6f17ffd8b5c29021226388aab7548f996b686a8e0b2bc861f72d447", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol b/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol new file mode 100644 index 000000000..297dd6294 --- /dev/null +++ b/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol @@ -0,0 +1,78 @@ + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + fallback () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract Bad { + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + B should_be_immutable_4 = new B(); + uint should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } +} + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} diff --git a/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol.0.7.6.CouldBeImmutable.json b/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol.0.7.6.CouldBeImmutable.json new file mode 100644 index 000000000..40c8b1368 --- /dev/null +++ b/tests/detectors/immutable-states/0.7.6/immut_state_variables.sol.0.7.6.CouldBeImmutable.json @@ -0,0 +1,334 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_5", + "source_mapping": { + "start": 1077, + "length": 26, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 47 + ], + "starting_column": 5, + "ending_column": 31 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_5 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#47) should be immutable \n", + "markdown": "[Bad.should_be_immutable_5](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L47) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L47", + "id": "42d50245236163ceca90dea732165e65c2155934b149a5a1a5c51bddc0b5b02a", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_2", + "source_mapping": { + "start": 940, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 44 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_2 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#44) should be immutable \n", + "markdown": "[Bad.should_be_immutable_2](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L44) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L44", + "id": "70d57aa51dda92c28444a466db8567fa783c85d484259aa5eee2ebc63f97a200", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_4", + "source_mapping": { + "start": 1038, + "length": 33, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 38 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_4 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#46) should be immutable \n", + "markdown": "[Bad.should_be_immutable_4](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L46) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L46", + "id": "a26d6df4087ac010928bc4bd18aa70ac58a28e584b1288e348d9c255473c300d", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable", + "source_mapping": { + "start": 894, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 43 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#43) should be immutable \n", + "markdown": "[Bad.should_be_immutable](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L43) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L43", + "id": "b163d277f544f7f05ed4bcddda61e444be893e65ba0469688abd7b401a1db222", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_3", + "source_mapping": { + "start": 986, + "length": 46, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 45 + ], + "starting_column": 5, + "ending_column": 51 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 531, + "filename_relative": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_3 (tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#45) should be immutable \n", + "markdown": "[Bad.should_be_immutable_3](tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L45) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.7.6/immut_state_variables.sol#L45", + "id": "f19f7a22a6f17ffd8b5c29021226388aab7548f996b686a8e0b2bc861f72d447", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol b/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol new file mode 100644 index 000000000..f405a1587 --- /dev/null +++ b/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol @@ -0,0 +1,78 @@ + +contract A { + + address constant public MY_ADDRESS = 0xE0f5206BBD039e7b0592d8918820024e2a7437b9; + address public myFriendsAddress = 0xc0ffee254729296a45a3885639AC7E10F9d54979; + + uint public used; + uint public test = 5; + + uint constant X = 32**22 + 8; + string constant TEXT1 = "abc"; + string text2 = "xyz"; + + function setUsed() public { + if (msg.sender == MY_ADDRESS) { + used = test; + } + } +} + + +contract B is A { + + address public mySistersAddress = 0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E; + + fallback () external { + used = 0; + } + + function setUsed(uint a) public { + if (msg.sender == MY_ADDRESS) { + used = a; + } + } +} + +contract Bad { + + uint constant A = 1; + bytes32 should_be_constant = sha256('abc'); + uint should_be_constant_2 = A + 1; + B should_be_constant_3 = B(address(0)); + address should_be_immutable = msg.sender; + uint should_be_immutable_2 = getNumber(); + uint should_be_immutable_3 = 10 + block.number; + uint should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} + +contract Good { + + uint constant A = 1; + bytes32 constant should_be_constant = sha256('abc'); + uint constant should_be_constant_2 = A + 1; + B constant should_be_constant_3 = B(address(0)); + address immutable should_be_immutable = msg.sender; + uint immutable should_be_immutable_2 = getNumber(); + uint immutable should_be_immutable_3 = 10 + block.number; + B immutable should_be_immutable_4 = new B(); + uint immutable should_be_immutable_5; + + constructor(uint b) { + should_be_immutable_5 = b; + } + + function getNumber() public returns(uint){ + return block.number; + } + +} \ No newline at end of file diff --git a/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol.0.8.0.CouldBeImmutable.json b/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol.0.8.0.CouldBeImmutable.json new file mode 100644 index 000000000..afa2e3bb2 --- /dev/null +++ b/tests/detectors/immutable-states/0.8.0/immut_state_variables.sol.0.8.0.CouldBeImmutable.json @@ -0,0 +1,268 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_5", + "source_mapping": { + "start": 1038, + "length": 26, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 31 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_5 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#46) should be immutable \n", + "markdown": "[Bad.should_be_immutable_5](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L46) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L46", + "id": "42d50245236163ceca90dea732165e65c2155934b149a5a1a5c51bddc0b5b02a", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_2", + "source_mapping": { + "start": 940, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 44 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_2 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#44) should be immutable \n", + "markdown": "[Bad.should_be_immutable_2](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L44) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L44", + "id": "70d57aa51dda92c28444a466db8567fa783c85d484259aa5eee2ebc63f97a200", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable", + "source_mapping": { + "start": 894, + "length": 40, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 43 + ], + "starting_column": 5, + "ending_column": 45 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#43) should be immutable \n", + "markdown": "[Bad.should_be_immutable](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L43) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L43", + "id": "b163d277f544f7f05ed4bcddda61e444be893e65ba0469688abd7b401a1db222", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + }, + { + "elements": [ + { + "type": "variable", + "name": "should_be_immutable_3", + "source_mapping": { + "start": 986, + "length": 46, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 45 + ], + "starting_column": 5, + "ending_column": 51 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "Bad", + "source_mapping": { + "start": 718, + "length": 493, + "filename_relative": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol", + "is_dependency": false, + "lines": [ + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "Bad.should_be_immutable_3 (tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#45) should be immutable \n", + "markdown": "[Bad.should_be_immutable_3](tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L45) should be immutable \n", + "first_markdown_element": "tests/detectors/immutable-states/0.8.0/immut_state_variables.sol#L45", + "id": "f19f7a22a6f17ffd8b5c29021226388aab7548f996b686a8e0b2bc861f72d447", + "check": "immutable-states", + "impact": "Optimization", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/source_unit/README.md b/tests/source_unit/README.md new file mode 100644 index 000000000..9cf3657e0 --- /dev/null +++ b/tests/source_unit/README.md @@ -0,0 +1,3 @@ +# README + +Before using this project, run `forge init --no-git --no-commit --force` to initialize submodules diff --git a/tests/source_unit/lib/forge-std b/tests/source_unit/lib/forge-std deleted file mode 160000 index eb980e1d4..000000000 --- a/tests/source_unit/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eb980e1d4f0e8173ec27da77297ae411840c8ccb diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py index af5a978c0..14130b428 100644 --- a/tests/test_ast_parsing.py +++ b/tests/test_ast_parsing.py @@ -328,6 +328,7 @@ ALL_TESTS = [ ALL_VERSIONS, ), Test("custom_error-0.8.4.sol", make_version(8, 4, 15)), + Test("custom-error-selector.sol", make_version(8, 4, 15)), Test( "top-level-0.4.0.sol", VERSIONS_04 + VERSIONS_05 + VERSIONS_06 + ["0.7.0"], @@ -419,6 +420,7 @@ ALL_TESTS = [ Test("user_defined_value_type/erc20-0.8.8.sol", ["0.8.8"] + make_version(8, 10, 15)), Test("user_defined_value_type/in_parenthesis-0.8.8.sol", ["0.8.8"] + make_version(8, 10, 15)), Test("user_defined_value_type/top-level-0.8.8.sol", ["0.8.8"] + make_version(8, 10, 15)), + Test("user_defined_value_type/using-for-0.8.8.sol", ["0.8.8"] + make_version(8, 10, 15)), Test("bytes_call.sol", ["0.8.12"]), Test("modifier_identifier_path.sol", VERSIONS_08), Test("free_functions/libraries_from_free.sol", ["0.8.12"]), @@ -429,6 +431,7 @@ ALL_TESTS = [ Test("using-for-2-0.8.0.sol", ["0.8.15"]), Test("using-for-3-0.8.0.sol", ["0.8.15"]), Test("using-for-4-0.8.0.sol", ["0.8.15"]), + Test("using-for-in-library-0.8.0.sol", ["0.8.15"]), Test("using-for-alias-contract-0.8.0.sol", ["0.8.15"]), Test("using-for-alias-top-level-0.8.0.sol", ["0.8.15"]), Test("using-for-functions-list-1-0.8.0.sol", ["0.8.15"]), @@ -438,6 +441,8 @@ ALL_TESTS = [ Test("using-for-global-0.8.0.sol", ["0.8.15"]), Test("library_event-0.8.16.sol", ["0.8.16"]), Test("top-level-struct-0.8.0.sol", ["0.8.0"]), + Test("yul-top-level-0.8.0.sol", ["0.8.0"]), + Test("complex_imports/import_aliases_issue_1319/test.sol", ["0.5.12"]), ] # create the output folder if needed try: diff --git a/tests/test_constant_folding.py b/tests/test_constant_folding.py index efc3119a8..21517ddc4 100644 --- a/tests/test_constant_folding.py +++ b/tests/test_constant_folding.py @@ -43,3 +43,59 @@ def test_constant_folding_rational(): variable_g = contract.get_state_variable_from_name("g") assert str(variable_g.type) == "int64" assert str(ConstantFolding(variable_g.expression, "int64").result()) == "-7" + + +def test_constant_folding_binary_expressions(): + sl = Slither("./tests/constant_folding_binop.sol") + contract = sl.get_contract_from_name("BinOp")[0] + + variable_a = contract.get_state_variable_from_name("a") + assert str(variable_a.type) == "uint256" + assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "0" + + variable_b = contract.get_state_variable_from_name("b") + assert str(variable_b.type) == "uint256" + assert str(ConstantFolding(variable_b.expression, "uint256").result()) == "3" + + variable_c = contract.get_state_variable_from_name("c") + assert str(variable_c.type) == "uint256" + assert str(ConstantFolding(variable_c.expression, "uint256").result()) == "3" + + variable_d = contract.get_state_variable_from_name("d") + assert str(variable_d.type) == "bool" + assert str(ConstantFolding(variable_d.expression, "bool").result()) == "False" + + variable_e = contract.get_state_variable_from_name("e") + assert str(variable_e.type) == "bool" + assert str(ConstantFolding(variable_e.expression, "bool").result()) == "False" + + variable_f = contract.get_state_variable_from_name("f") + assert str(variable_f.type) == "bool" + assert str(ConstantFolding(variable_f.expression, "bool").result()) == "True" + + variable_g = contract.get_state_variable_from_name("g") + assert str(variable_g.type) == "bool" + assert str(ConstantFolding(variable_g.expression, "bool").result()) == "False" + + variable_h = contract.get_state_variable_from_name("h") + assert str(variable_h.type) == "bool" + assert str(ConstantFolding(variable_h.expression, "bool").result()) == "False" + + variable_i = contract.get_state_variable_from_name("i") + assert str(variable_i.type) == "bool" + assert str(ConstantFolding(variable_i.expression, "bool").result()) == "True" + + variable_j = contract.get_state_variable_from_name("j") + assert str(variable_j.type) == "bool" + assert str(ConstantFolding(variable_j.expression, "bool").result()) == "False" + + variable_k = contract.get_state_variable_from_name("k") + assert str(variable_k.type) == "bool" + assert str(ConstantFolding(variable_k.expression, "bool").result()) == "True" + + variable_l = contract.get_state_variable_from_name("l") + assert str(variable_l.type) == "uint256" + assert ( + str(ConstantFolding(variable_l.expression, "uint256").result()) + == "115792089237316195423570985008687907853269984665640564039457584007913129639935" + ) diff --git a/tests/test_detectors.py b/tests/test_detectors.py index a45369fcd..994f87aac 100644 --- a/tests/test_detectors.py +++ b/tests/test_detectors.py @@ -480,28 +480,53 @@ ALL_TEST_OBJECTS = [ "0.7.6", ), Test( - all_detectors.ConstCandidateStateVars, + all_detectors.CouldBeConstant, "const_state_variables.sol", "0.4.25", ), Test( - all_detectors.ConstCandidateStateVars, + all_detectors.CouldBeConstant, "const_state_variables.sol", "0.5.16", ), Test( - all_detectors.ConstCandidateStateVars, + all_detectors.CouldBeConstant, "const_state_variables.sol", "0.6.11", ), Test( - all_detectors.ConstCandidateStateVars, + all_detectors.CouldBeConstant, "const_state_variables.sol", "0.7.6", ), Test( - all_detectors.ConstCandidateStateVars, - "immutable.sol", + all_detectors.CouldBeConstant, + "const_state_variables.sol", + "0.8.0", + ), + Test( + all_detectors.CouldBeImmutable, + "immut_state_variables.sol", + "0.4.25", + ), + Test( + all_detectors.CouldBeImmutable, + "immut_state_variables.sol", + "0.5.16", + ), + Test( + all_detectors.CouldBeImmutable, + "immut_state_variables.sol", + "0.6.11", + ), + Test( + all_detectors.CouldBeImmutable, + "immut_state_variables.sol", + "0.7.6", + ), + Test( + all_detectors.CouldBeImmutable, + "immut_state_variables.sol", "0.8.0", ), Test( diff --git a/tests/test_features.py b/tests/test_features.py index a5541b589..924e0b154 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -128,3 +128,14 @@ def test_using_for_alias_contract() -> None: if isinstance(ir, InternalCall) and ir.function_name == "a": return assert False + + +def test_using_for_in_library() -> None: + solc_select.switch_global_version("0.8.15", always_install=True) + slither = Slither("./tests/ast-parsing/using-for-in-library-0.8.0.sol") + contract_c = slither.get_contract_from_name("A")[0] + libCall = contract_c.get_function_from_full_name("a(uint256)") + for ir in libCall.all_slithir_operations(): + if isinstance(ir, LibraryCall) and ir.destination == "B" and ir.function_name == "b": + return + assert False diff --git a/tests/test_source_unit.py b/tests/test_source_unit.py index 7b653599e..73c165016 100644 --- a/tests/test_source_unit.py +++ b/tests/test_source_unit.py @@ -1,6 +1,18 @@ +from pathlib import Path +import shutil + +import pytest from slither import Slither +# NB: read tests/source_unit/README.md for setup before using this test + +foundry_available = shutil.which("forge") is not None +project_ready = Path("./tests/source_unit/lib/forge-std").exists() + +@pytest.mark.skipif( + not foundry_available or not project_ready, reason="requires Foundry and project setup" +) def test_contract_info() -> None: slither = Slither("./tests/source_unit")